中間色作る。

参考


Google Colab上でhtmlとして動作する。
Google Colabでなくhtmlファイルとして動作させたければ%%htmlを外す。

%%html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>16進数色変換ツール</title>
    <style>
        #colorDisplay {
            width: 300px;
            height: 100px;
            margin-top: 10px;
        }
        canvas {
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <label for="colorInput">16進数色: #</label>
    <input type="text" id="colorInput" placeholder="例:ff5733" oninput="updateColor()">
    <div id="colorDisplay"></div>
    <div id="rgb"></div>
    <div id="hsb"></div>
    <div id="cmyk"></div>
    <canvas id="combinedCanvas" width="1000" height="600"></canvas><br>

    <script>
        function hexToRgb(hex) {
            let bigint = parseInt(hex, 16);
            let r = (bigint >> 16) & 255;
            let g = (bigint >> 8) & 255;
            let b = bigint & 255;
            return [r, g, b];
        }

        function rgbToHsb(r, g, b) {
            let rr = r / 255;
            let gg = g / 255;
            let bb = b / 255;
            let max = Math.max(rr, gg, bb);
            let min = Math.min(rr, gg, bb);
            let h, s;
            let v = max;
            let d = max - min;
            s = max === 0 ? 0 : d / max;
            if (max === min) {
                h = 0;
            } else {
                switch (max) {
                    case rr: h = (gg - bb) + d * (gg < bb ? 6 : 0); h /= 6; break;
                    case gg: h = (bb - rr) + d * 2; h /= 6; break;
                    case bb: h = (rr - gg) + d * 4; h /= 6; break;
                }
            }
            return [h * 360, s * 100, v * 100];
        }

        function rgbToCmyk(r, g, b) {
            let rr = r / 255;
            let gg = g / 255;
            let bb = b / 255;
            let k = 1 - Math.max(rr, gg, bb);
            let c = (1 - rr - k) / (1 - k) || 0;
            let m = (1 - gg - k) / (1 - k) || 0;
            let y = (1 - bb - k) / (1 - k) || 0;
            return [c * 100, m * 100, y * 100, k * 100];
        }

        function hexToHSL(H) {
            let r = parseInt(H.substring(1, 3), 16) / 255;
            let g = parseInt(H.substring(3, 5), 16) / 255;
            let b = parseInt(H.substring(5, 7), 16) / 255;
            let max = Math.max(r, g, b),
                min = Math.min(r, g, b);
            let h, s, l = (max + min) / 2;

            if (max == min) {
                h = s = 0;
            } else {
                let d = max - min;
                s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
                switch (max) {
                    case r:
                        h = (g - b) / d + (g < b ? 6 : 0);
                        break;
                    case g:
                        h = (b - r) / d + 2;
                        break;
                    case b:
                        h = (r - g) / d + 4;
                        break;
                }
                h /= 6;
            }
            return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
        }

        function hslToHex(h, s, l) {
            l /= 100;
            const a = s * Math.min(l, 1 - l) / 100;
            const f = n => {
                const k = (n + h / 30) % 12;
                const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
                return Math.round(255 * color).toString(16).padStart(2, '0');
            };
            return `#${f(0)}${f(8)}${f(4)}`;
        }

        function updateColor() {
            let hex = document.getElementById('colorInput').value;
            if (hex.length === 6) {
                let [r, g, b] = hexToRgb(hex);
                let [h, s, v] = rgbToHsb(r, g, b);
                let [c, m, y, k] = rgbToCmyk(r, g, b);

                document.getElementById('colorDisplay').style.backgroundColor = `#${hex}`;
                document.getElementById('rgb').textContent = `RGB: ${r}, ${g}, ${b}`;
                document.getElementById('hsb').textContent = `HSB: ${h.toFixed(2)}°, ${s.toFixed(2)}%、${v.toFixed(2)}%`;
                document.getElementById('cmyk').textContent = `CMYK: ${c.toFixed(2)}%、${m.toFixed(2)}%、${y.toFixed(2)}%、${k.toFixed(2)}%`;

                const compColorHex = complementaryColor(`#${hex}`);
                const triadicColors = triadicHarmony(`#${hex}`);
                const tetradicColors = tetradicHarmony(`#${hex}`);
                const triadicMiddleColors = generateMiddleColors2(triadicColors, 3);
                const tetradicMiddleColors = generateMiddleColors2(tetradicColors, 4);

                displayAllColorsOnCanvas(`#${hex}`, compColorHex, triadicColors, tetradicColors, triadicMiddleColors, tetradicMiddleColors);
            }
        }

        function generateMiddleColors(colors, numMiddleColors) {
            let middleColors = [];
            for (let i = 0; i < colors.length; i++) {
                let nextColor = colors[(i + 1) % colors.length];
                let middle = interpolateColors(colors[i], nextColor, numMiddleColors);
                middleColors = middleColors.concat(middle);
            }
            return middleColors;
        }

        function generateMiddleColors2(colors, numMiddleColors) {
            let allColors = [];
            for (let i = 0; i < colors.length; i++) {
                allColors.push(colors[i]);
                let nextColor = colors[(i + 1) % colors.length];
                let middle = interpolateColors(colors[i], nextColor, numMiddleColors);
                allColors = allColors.concat(middle);
            }
            return allColors;
        }        

        function interpolateColors(color1, color2, numSteps) {
            let [r1, g1, b1] = hexToRgb(color1.slice(1));
            let [r2, g2, b2] = hexToRgb(color2.slice(1));
            let steps = [];

            for (let i = 1; i <= numSteps; i++) {
                let r = Math.round(r1 + (r2 - r1) * (i / (numSteps + 1)));
                let g = Math.round(g1 + (g2 - g1) * (i / (numSteps + 1)));
                let b = Math.round(b1 + (b2 - b1) * (i / (numSteps + 1)));
                steps.push(`#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`);
            }

            return steps;
        }

        function displayAllColorsOnCanvas(hex, compColorHex, triadicColors, tetradicColors, triadicMiddleColors, tetradicMiddleColors) {
            const canvas = document.getElementById('combinedCanvas');
            const ctx = canvas.getContext('2d');
            const segmentHeight = canvas.height / 6;

            let hindex = 0;

            let [r, g, b] = hexToRgb(hex.slice(1));
            let [h, s, v] = rgbToHsb(r, g, b);
            let [c, m, y, k] = rgbToCmyk(r, g, b);

            ctx.fillStyle = `rgb(${r},${g},${b})`;
            ctx.fillRect(0, segmentHeight * hindex, canvas.width, segmentHeight);

            ctx.fillStyle = 'white';
            ctx.font = '12px Arial';
            ctx.fillText(`HEX: ${hex}`, 10, segmentHeight * hindex + 20);
            ctx.fillText(`RGB: ${r}, ${g}, ${b}`, 10, segmentHeight * hindex + 40);
            ctx.fillText(`HSB: ${h.toFixed(2)}°, ${s.toFixed(2)}%、${v.toFixed(2)}%`, 10, segmentHeight * hindex + 60);
            ctx.fillText(`CMYK: ${c.toFixed(2)}%、${m.toFixed(2)}%、${y.toFixed(2)}%、${k.toFixed(2)}%`, 10, segmentHeight * hindex + 80);

            hindex = 1;

            [r, g, b] = hexToRgb(compColorHex.slice(1));
            [h, s, v] = rgbToHsb(r, g, b);
            [c, m, y, k] = rgbToCmyk(r, g, b);

            ctx.fillStyle = `rgb(${r},${g},${b})`;
            ctx.fillRect(0, segmentHeight * hindex, canvas.width, segmentHeight);

            ctx.fillStyle = 'white';
            ctx.font = '12px Arial';
            ctx.fillText(`HEX: ${compColorHex}`, 10, segmentHeight * hindex + 20);
            ctx.fillText(`RGB: ${r}, ${g}, ${b}`, 10, segmentHeight * hindex + 40);
            ctx.fillText(`HSB: ${h.toFixed(2)}°, ${s.toFixed(2)}%、${v.toFixed(2)}%`, 10, segmentHeight * hindex + 60);
            ctx.fillText(`CMYK: ${c.toFixed(2)}%、${m.toFixed(2)}%、${y.toFixed(2)}%、${k.toFixed(2)}%`, 10, segmentHeight * hindex + 80);

            hindex = 2;
            let segmentWidth = canvas.width / triadicColors.length;

            triadicColors.forEach((triadicColor, rindex) => {
                [r, g, b] = hexToRgb(triadicColor.slice(1));
                [h, s, v] = rgbToHsb(r, g, b);
                [c, m, y, k] = rgbToCmyk(r, g, b);

                ctx.fillStyle = `rgb(${r},${g},${b})`;
                ctx.fillRect(segmentWidth * rindex, segmentHeight * hindex, segmentWidth, segmentHeight);

                ctx.fillStyle = 'white';
                ctx.font = '12px Arial';
                ctx.fillText(`HEX: ${triadicColor}`, segmentWidth * rindex + 10, segmentHeight * hindex + 20);
                ctx.fillText(`RGB: ${r}, ${g}, ${b}`, segmentWidth * rindex + 10, segmentHeight * hindex + 40);
                ctx.fillText(`HSB: ${h.toFixed(2)}°, ${s.toFixed(2)}%、${v.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 60);
                ctx.fillText(`CMYK: ${c.toFixed(2)}%、${m.toFixed(2)}%、${y.toFixed(2)}%、${k.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 80);
            });

            hindex = 3;
            segmentWidth = canvas.width / triadicMiddleColors.length;

            triadicMiddleColors.forEach((middleColor, rindex) => {
                [r, g, b] = hexToRgb(middleColor.slice(1));
                [h, s, v] = rgbToHsb(r, g, b);
                [c, m, y, k] = rgbToCmyk(r, g, b);

                ctx.fillStyle = `rgb(${r},${g},${b})`;
                ctx.fillRect(segmentWidth * rindex, segmentHeight * hindex, segmentWidth, segmentHeight);

                ctx.fillStyle = 'white';
                ctx.font = '12px Arial';
                ctx.fillText(`HEX: ${middleColor}`, segmentWidth * rindex + 10, segmentHeight * hindex + 20);
                ctx.fillText(`RGB: ${r}, ${g}, ${b}`, segmentWidth * rindex + 10, segmentHeight * hindex + 40);
                ctx.fillText(`HSB: ${h.toFixed(2)}°, ${s.toFixed(2)}%、${v.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 60);
                ctx.fillText(`CMYK: ${c.toFixed(2)}%、${m.toFixed(2)}%、${y.toFixed(2)}%、${k.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 80);
            });

            hindex = 4;
            segmentWidth = canvas.width / tetradicColors.length;

            tetradicColors.forEach((tetradicColor, rindex) => {
                [r, g, b] = hexToRgb(tetradicColor.slice(1));
                [h, s, v] = rgbToHsb(r, g, b);
                [c, m, y, k] = rgbToCmyk(r, g, b);

                ctx.fillStyle = `rgb(${r},${g},${b})`;
                ctx.fillRect(segmentWidth * rindex, segmentHeight * hindex, segmentWidth, segmentHeight);

                ctx.fillStyle = 'white';
                ctx.font = '12px Arial';
                ctx.fillText(`HEX: ${tetradicColor}`, segmentWidth * rindex + 10, segmentHeight * hindex + 20);
                ctx.fillText(`RGB: ${r}, ${g}, ${b}`, segmentWidth * rindex + 10, segmentHeight * hindex + 40);
                ctx.fillText(`HSB: ${h.toFixed(2)}°, ${s.toFixed(2)}%、${v.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 60);
                ctx.fillText(`CMYK: ${c.toFixed(2)}%、${m.toFixed(2)}%、${y.toFixed(2)}%、${k.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 80);
            });

            hindex = 5;
            segmentWidth = canvas.width / tetradicMiddleColors.length;

            tetradicMiddleColors.forEach((middleColor, rindex) => {
                [r, g, b] = hexToRgb(middleColor.slice(1));
                [h, s, v] = rgbToHsb(r, g, b);
                [c, m, y, k] = rgbToCmyk(r, g, b);

                ctx.fillStyle = `rgb(${r},${g},${b})`;
                ctx.fillRect(segmentWidth * rindex, segmentHeight * hindex, segmentWidth, segmentHeight);

                ctx.fillStyle = 'white';
                ctx.font = '12px Arial';
                ctx.fillText(`HEX: ${middleColor}`, segmentWidth * rindex + 10, segmentHeight * hindex + 20);
                ctx.fillText(`RGB: ${r}, ${g}, ${b}`, segmentWidth * rindex + 10, segmentHeight * hindex + 40);
                ctx.fillText(`HSB: ${h.toFixed(2)}°, ${s.toFixed(2)}%、${v.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 60);
                ctx.fillText(`CMYK: ${c.toFixed(2)}%、${m.toFixed(2)}%、${y.toFixed(2)}%、${k.toFixed(2)}%`, segmentWidth * rindex + 10, segmentHeight * hindex + 80);
            });
        }

        function complementaryColor(hex) {
            if (!/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(hex)) {
                throw new Error('Invalid HEX format');
            }

            let red = 255 - parseInt(hex.slice(1, 3), 16);
            let green = 255 - parseInt(hex.slice(3, 5), 16);
            let blue = 255 - parseInt(hex.slice(5, 7), 16);

            let compColor = `#${red.toString(16).padStart(2, '0')}${green.toString(16).padStart(2, '0')}${blue.toString(16).padStart(2, '0')}`;

            return compColor.toUpperCase();
        }

        function triadicHarmony(hex) {
            return [hex, rotateHue(hex, 120), rotateHue(hex, 240)];
        }

        function rotateHue(hex, degree) {
            let [h, s, l] = hexToHSL(hex);
            h = (h + degree) % 360;

            return hslToHex(h, s, l);
        }

        function tetradicHarmony(hex) {
            return [hex, rotateHue(hex, 90), rotateHue(hex, 180), rotateHue(hex, 270)];
        }
    </script>
</body>
</html>



この記事が気に入ったらサポートをしてみませんか?