原生JS实现 color picker 颜色选择器(canvas

2019-03-07  本文已影响0人  Allan要做活神仙

2019-03-07-15:32于公司:
最近在搞TMS,碰到了颜色选择器,想了解下用原生JS如何实现。记录下:

效果如下:


image.png

先上源码稍后来分析,到时候搞成react版本

<!DOCTYPE html>
<html lang="zh">
 
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            body {
                background: #535353;
                padding: 0;
                margin: 0;
            }
             
            canvas {
                cursor: crosshair;
            }
             
            #cur {
                width: 3px;
                height: 3px;
                outline: 2px solid #535353;
                margin-left: -1px;
                margin-top: -1px;
                position: absolute;
            }
             
            .wrapper {
                position: relative;
            }
             
            #color_show {
                width: 50px;
                height: 50px;
                background: #f00;
            }
             
            .panel {
                width: 200px;
                height: 200px;
                position: fixed;
                top: 20px;
                right: 20px;
                background-color: #fff;
                padding: 10px;
                text-align: center;
                line-height: 2em;
            }
        </style>
    </head>
 
    <body>
        <div class="wrapper">
            <canvas id="canvas" width="600" height="600"></canvas>
            <em id="cur"></em>
            <div class="panel">
                <div id="color_show"></div>
                <label>
            rgb <input type="text"  class="color_input" value="" id="rgb_value">
        </label><br>
                <label>
            hex <input type="text"  class="color_input" value="" id="hex_value">
        </label>
            </div>
        </div>
        <script>
            (function() {
                var width = 256;
                var can = document.getElementById('canvas');
                var ctx = can.getContext('2d');
                var curColor = 'rgba(255,0,0,1)';
                var cur = document.getElementById('cur');
                var rgbValue = document.getElementById('rgb_value');
                var hexValue = document.getElementById('hex_value');
                var colorShow = document.getElementById('color_show');
 
                var aColorInput = document.getElementsByClassName('color_input');
 
                function colorBar() {
                    var gradientBar = ctx.createLinearGradient(0, 0, 0, width);
                    gradientBar.addColorStop(0, '#f00');
                    gradientBar.addColorStop(1 / 6, '#f0f');
                    gradientBar.addColorStop(2 / 6, '#00f');
                    gradientBar.addColorStop(3 / 6, '#0ff');
                    gradientBar.addColorStop(4 / 6, '#0f0');
                    gradientBar.addColorStop(5 / 6, '#ff0');
                    gradientBar.addColorStop(1, '#f00');
 
                    ctx.fillStyle = gradientBar;
                    ctx.fillRect(0, 0, 20, width);
                }
 
                function rgb2hex(rgb) {
                    var aRgb = rgb instanceof Array ? rgb : (rgb.split(',') || [0, 0, 0]);
                    var temp;
                    return [
                        (temp = Number(aRgb[0]).toString(16)).length == 1 ? ('0' + temp) : temp,
                        (temp = Number(aRgb[1]).toString(16)).length == 1 ? ('0' + temp) : temp,
                        (temp = Number(aRgb[2]).toString(16)).length == 1 ? ('0' + temp) : temp,
                    ].join('');
                }
 
                function hex2rgb(hex) {
                    if(hex.length == 3) {
                        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
                    }
                    return [
                        parseInt(hex[0] + hex[1], 16),
                        parseInt(hex[2] + hex[3], 16),
                        parseInt(hex[4] + hex[5], 16),
                    ].join();
                }
 
                function putCurDom(color) {
                    if(/([0-9a-f]{3}|[0-9a-f]{6})/i.test(color)) {
                        // hex
                        color = hex2rgb(color);
                    } else if(color instanceof Array) {
                        color = color.join(',');
                    } else if(/\d{1,3}(\,\d{1,3}){2}/i.test(color)) {
 
                    } else {
                        return;
                    }
                }
 
                function colorBox(color) {
                    // 底色填充,也就是(举例红色)到白色
                    var gradientBase = ctx.createLinearGradient(30, 0, width + 30, 0);
                    gradientBase.addColorStop(1, color);
                    gradientBase.addColorStop(0, 'rgba(255,255,255,1)');
                    ctx.fillStyle = gradientBase;
                    ctx.fillRect(30, 0, width, width);
                    // 第二次填充,黑色到透明
                    var my_gradient1 = ctx.createLinearGradient(0, 0, 0, width);
                    my_gradient1.addColorStop(0, 'rgba(0,0,0,0)');
                    my_gradient1.addColorStop(1, 'rgba(0,0,0,1)');
                    ctx.fillStyle = my_gradient1;
                    ctx.fillRect(30, 0, width, width);
                }
 
                function init() {
                    colorBar();
                    colorBox(curColor);
                    bind();
                }
 
                function bind() {
                    can.addEventListener('click', function(e) {
                        var ePos = {
                            x: e.offsetX || e.layerX,
                            y: e.offsetY || e.layerY
                        }
                        var rgbaStr = '#000';
                        if(ePos.x >= 0 && ePos.x < 20 && ePos.y >= 0 && ePos.y < width) {
                            // in
                            rgbaStr = getRgbaAtPoint(ePos, 'bar');
                            colorBox('rgba(' + rgbaStr + ')');
                        } else if(ePos.x >= 30 && ePos.x < 30 + width && ePos.y >= 0 && ePos.y < width) {
                            rgbaStr = getRgbaAtPoint(ePos, 'box');
                        } else {
                            return;
                        }
                        outColor(rgbaStr.slice(0, 3).join());
                        cur.style.left = ePos.x + 'px';
                        cur.style.top = ePos.y + 'px';
                        cur.style.outlineColor = (rgbaStr[0] > 256 / 2 || rgbaStr[1] > 256 / 2 || rgbaStr[2] > 256 / 2) ? '#000' : '#fff';
                    });
 
                    can.addEventListener('mousedown', function(e) {
                        var ePos = {
                            x: e.layerX || e.offsetX,
                            y: e.layerY || e.offsetY
                        }
                        if(ePos.x >= 30 && ePos.x < 30 + width && ePos.y >= 0 && ePos.y < width) {
                            document.onmousemove = function(e) {
                                var pos = {
                                    x: e.clientX,
                                    y: e.clientY
                                }
 
                                pos.x = pos.x < 30 ? 30 : pos.x && (pos.x > (30 + width - 1) ? (30 + width - 1) : pos.x);
                                pos.y = pos.y < 0 ? 0 : pos.y && (pos.y > (width - 1) ? (width - 1) : pos.y);
 
                                rgbaStr = getRgbaAtPoint(pos, 'box');
                                cur.style.left = pos.x + 'px';
                                cur.style.top = pos.y + 'px';
                                cur.style.outlineColor = (rgbaStr[0] > 256 / 2 || rgbaStr[1] > 256 / 2 || rgbaStr[2] > 256 / 2) ? '#000' : '#fff';
                                outColor(rgbaStr.slice(0, 3).join());
                            };
                            document.onmouseup = function() {
                                // outColor(rgbaStr.slice(0, 3).join());
                                document.onmouseup = document.onmousemove = null;
                            }
                        }
 
                    });
                }
 
                function outColor(rgb) {
                    rgbValue.value = rgb;
                    hexValue.value = rgb2hex(rgb);
                    colorShow.style.backgroundColor = 'rgb(' + rgb + ')';
                }
 
                function getRgbaAtPoint(pos, area) {
                    if(area == 'bar') {
                        var imgData = ctx.getImageData(0, 0, 20, width);
                    } else {
                        var imgData = ctx.getImageData(0, 0, can.width, can.height);
                    }
 
                    var data = imgData.data;
                    var dataIndex = (pos.y * imgData.width + pos.x) * 4;
                    return [
                        data[dataIndex],
                        data[dataIndex + 1],
                        data[dataIndex + 2],
                        (data[dataIndex + 3] / 255).toFixed(2),
                    ];
                }
 
                init();
            })()
        </script>
    </body>
 
</html>
上一篇下一篇

猜你喜欢

热点阅读