You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
audioUrl = "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
songTitle = "Incoming Call Ringtone",
artistName = "Android MP3 Player",
themeColor = "#3ddc84"
) {
// Create the outer wrapper
const wrapper = document.createElement('div');
wrapper.style.display = "flex";
wrapper.style.justifyContent = "center";
wrapper.style.alignItems = "center";
wrapper.style.padding = "20px";
wrapper.style.fontFamily = "'Roboto', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif";
// Create scoped styles for the player
const style = document.createElement('style');
style.innerHTML = `
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap');
.android-player {
width: 320px;
background: #1e1e22;
border-radius: 28px;
padding: 28px 24px;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 20px 40px rgba(0,0,0,0.4), inset 0 1px 1px rgba(255,255,255,0.1);
color: #ffffff;
position: relative;
overflow: hidden;
font-family: 'Roboto', sans-serif;
}
.ap-header {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 2.5px;
color: #999999;
margin-bottom: 24px;
font-weight: 700;
}
.ap-album {
width: 220px;
height: 220px;
border-radius: 20px;
box-shadow: 0 12px 28px rgba(0,0,0,0.6);
margin-bottom: 30px;
background: #222;
}
.ap-info {
text-align: center;
width: 100%;
margin-bottom: 24px;
}
.ap-title {
font-size: 22px;
font-weight: 700;
margin: 0 0 6px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #ffffff;
}
.ap-artist {
font-size: 15px;
color: #aaaaaa;
margin: 0;
font-weight: 400;
}
.ap-progress {
width: 100%;
display: flex;
flex-direction: column;
margin-bottom: 24px;
}
.ap-time {
display: flex;
justify-content: space-between;
font-size: 11px;
color: #888888;
margin-top: 10px;
font-weight: 500;
}
input[type=range].ap-slider {
-webkit-appearance: none;
width: 100%;
background: transparent;
margin: 0;
}
input[type=range].ap-slider::-webkit-slider-thumb {
-webkit-appearance: none;
height: 12px;
width: 12px;
border-radius: 50%;
background: ${themeColor};
cursor: pointer;
margin-top: -4px;
box-shadow: 0 0 8px rgba(0,0,0,0.3);
transition: transform 0.1s;
}
input[type=range].ap-slider::-webkit-slider-thumb:hover {
transform: scale(1.3);
}
input[type=range].ap-slider::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;
background: #444;
border-radius: 2px;
}
.ap-controls {
display: flex;
width: 100%;
justify-content: space-evenly;
align-items: center;
}
.ap-btn {
background: none;
border: none;
color: #ffffff;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
outline: none;
transition: transform 0.15s, color 0.2s;
padding: 0;
}
.ap-btn:hover {
color: ${themeColor};
}
.ap-btn:active {
transform: scale(0.9);
}
.ap-btn-play {
width: 68px;
height: 68px;
border-radius: 50%;
background: ${themeColor};
color: #1a1a1a;
box-shadow: 0 6px 16px rgba(0,0,0,0.3);
}
.ap-btn-play:hover {
color: #1a1a1a;
transform: scale(1.05);
background: ${themeColor};
filter: brightness(1.1);
}
.ap-btn-play:active {
transform: scale(0.95);
}
.ap-btn svg {
width: 28px;
height: 28px;
}
.ap-btn-play svg {
width: 36px;
height: 36px;
}
`;
wrapper.appendChild(style);
// Build Player UI layout
const player = document.createElement('div');
player.className = 'android-player';
const header = document.createElement('div');
header.className = 'ap-header';
header.innerText = 'Now Playing';
// Album Art Canvas setup (covers the image intelligently)
const canvas = document.createElement('canvas');
canvas.className = 'ap-album';
const canvasSize = 400; // Render target size
canvas.width = canvasSize;
canvas.height = canvasSize;
const ctx = canvas.getContext('2d');
// Provide defaults to avoid NaN if image structure is somewhat corrupted
const imgW = originalImg.width || 1;
const imgH = originalImg.height || 1;
// Scale and center to mimic object-fit: cover
const scale = Math.max(canvasSize / imgW, canvasSize / imgH);
const w = imgW * scale;
const h = imgH * scale;
const x = (canvasSize - w) / 2;
const y = (canvasSize - h) / 2;
ctx.fillStyle = "#1e1e22";
ctx.fillRect(0, 0, canvasSize, canvasSize);
// Make sure we have drawn the actual image
try {
ctx.drawImage(originalImg, x, y, w, h);
} catch(e) {
console.error("Could not draw image", e);
}
// Info section (Title and Artist)
const info = document.createElement('div');
info.className = 'ap-info';
const title = document.createElement('h2');
title.className = 'ap-title';
title.innerText = songTitle;
const artist = document.createElement('p');
artist.className = 'ap-artist';
artist.innerText = artistName;
info.appendChild(title);
info.appendChild(artist);
// Audio Element configuration
const audio = document.createElement('audio');
audio.src = audioUrl;
audio.crossOrigin = "anonymous";
// Progress Bar Elements
const progressContainer = document.createElement('div');
progressContainer.className = 'ap-progress';
const slider = document.createElement('input');
slider.type = 'range';
slider.className = 'ap-slider';
slider.min = 0;
slider.max = 100;
slider.value = 0;
const timeRow = document.createElement('div');
timeRow.className = 'ap-time';
const currTimeLabel = document.createElement('span');
currTimeLabel.innerText = '0:00';
const durTimeLabel = document.createElement('span');
durTimeLabel.innerText = '0:00';
timeRow.appendChild(currTimeLabel);
timeRow.appendChild(durTimeLabel);
progressContainer.appendChild(slider);
progressContainer.appendChild(timeRow);
// Utility: format seconds into MM:SS
function formatTime(seconds) {
if (isNaN(seconds) || !isFinite(seconds) || seconds < 0) return '0:00';
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return m + ':' + (s < 10 ? '0' : '') + s;
}
// Audio event listeners for timeline
audio.addEventListener('loadedmetadata', () => {
slider.max = audio.duration;
durTimeLabel.innerText = formatTime(audio.duration);
});
let isSeeking = false;
audio.addEventListener('timeupdate', () => {
if (!isSeeking) {
slider.value = audio.currentTime;
currTimeLabel.innerText = formatTime(audio.currentTime);
}
});
slider.addEventListener('input', () => {
isSeeking = true;
currTimeLabel.innerText = formatTime(slider.value);
});
slider.addEventListener('change', () => {
audio.currentTime = slider.value;
isSeeking = false;
});
// Control Elements (Prev, Play, Next)
const controls = document.createElement('div');
controls.className = 'ap-controls';
const btnPrev = document.createElement('button');
btnPrev.className = 'ap-btn';
btnPrev.innerHTML = `<svg viewBox="0 0 24 24"><path fill="currentColor" d="M6,18V6H8V18H6M9.5,12L18,6V18L9.5,12Z" /></svg>`;
const btnPlay = document.createElement('button');
btnPlay.className = 'ap-btn ap-btn-play';
const playIcon = `<svg viewBox="0 0 24 24"><path fill="currentColor" d="M8,5.14V19.14L19,12.14L8,5.14Z" /></svg>`;
const pauseIcon = `<svg viewBox="0 0 24 24"><path fill="currentColor" d="M14,19H18V5H14M6,19H10V5H6V19Z" /></svg>`;
btnPlay.innerHTML = playIcon;
const btnNext = document.createElement('button');
btnNext.className = 'ap-btn';
btnNext.innerHTML = `<svg viewBox="0 0 24 24"><path fill="currentColor" d="M16,18H18V6H16M6,18L14.5,12L6,6V18Z" /></svg>`;
// Audio Playback Functionality
btnPlay.addEventListener('click', () => {
if (audio.paused) {
audio.play().catch(e => console.warn("Audio playback was blocked", e));
btnPlay.innerHTML = pauseIcon;
} else {
audio.pause();
btnPlay.innerHTML = playIcon;
}
});
audio.addEventListener('ended', () => {
btnPlay.innerHTML = playIcon;
slider.value = 0;
currTimeLabel.innerText = formatTime(0);
});
// Previous decreases time by 5s or goes back to start
btnPrev.addEventListener('click', () => {
audio.currentTime = Math.max(0, audio.currentTime - 5);
});
// Next increases time by 5s or goes to end
btnNext.addEventListener('click', () => {
audio.currentTime = Math.min(audio.duration || 0, audio.currentTime + 5);
});
// Append controls
controls.appendChild(btnPrev);
controls.appendChild(btnPlay);
controls.appendChild(btnNext);
// Assembly of Player UI
player.appendChild(header);
player.appendChild(canvas);
player.appendChild(info);
player.appendChild(progressContainer);
player.appendChild(controls);
player.appendChild(audio);
wrapper.appendChild(player);
return wrapper;
}
Apply Changes