function Control( el, { min = 0, max = 255, step = 1, value = 0, onChange, minAngle = 0, wheelStepRatio = 0.01, maxAngle = 360, src = "1@3x.png", } = {} ) { this.value = value; const img = document.createElement("img"); el.appendChild(img); img.src = src; const angleRatio = (maxAngle - minAngle) / (max - min); const getAngle = () => (value - min) * angleRatio + minAngle; const updateImg = (angle = getAngle()) => (img.style.transform = `rotate(${angle}deg)`); updateImg(); const updateValue = (st = step) => { value >= max ? (value -= max) : value < min ? (value += max) : value; value += st; onChange(Math.floor(value)); updateImg(); }; img.onclick = (e) => { const { x: imgX, width: imgWidth } = img.getBoundingClientRect(); const xOnImg = e.clientX - imgX; const st = xOnImg > imgWidth / 2 ? step : -step; updateValue(st); }; img.onmousewheel = (e) => { const st = e.deltaY * wheelStepRatio; updateValue(st); }; const toDeg = (rad) => (360 / (2 * Math.PI)) * rad; let startAngle; const getAngleByCoords = (x, y) => { const { x: imgX, y: imgY, width, height } = img.getBoundingClientRect(); const xOnImg = x - imgX - width / 2; const yOnImg = y - imgY - height / 2; const angle = toDeg(Math.atan2(yOnImg, xOnImg)); return angle; }; img.onmousedown = (e) => { startAngle = getAngleByCoords(e.clientX, e.clientY); e.preventDefault(); }; img.onmousemove = (e) => { if (e.buttons && startAngle) { const angleDiff = getAngleByCoords(e.clientX, e.clientY) - startAngle; const angle = getAngle(); updateImg(angle + angleDiff); } }; img.onmouseup = (e) => { const angleDiff = getAngleByCoords(e.clientX, e.clientY) - startAngle; updateValue(angleDiff / angleRatio); startAngle = null; }; } let rgb = { red: 0, green: 0, blue: 0 }; function mixPalette(colors) { let { red, green, blue } = colors; let paletteForMix = document.querySelector("body"); paletteForMix.style = `width:500px;height:500px;background:rgb(${red},${green},${blue})`; } let soundlRed = new Control(sound1, { max: 255, onChange: (value) => { sound1.style = `width:500px;background:rgb(${value},0,0)`; rgb.red = value; mixPalette(rgb); }, }); let soundlGreen = new Control(sound2, { max: 255, onChange: (value) => { sound2.style = `width:500px;background:rgb(0,${value},0)`; rgb.green = value; mixPalette(rgb); }, }); let soundlBlue = new Control(sound3, { max: 255, onChange: (value) => { sound3.style = `width:500px;background:rgb(0,0,${value})`; rgb.blue = value; mixPalette(rgb); }, });