<template>    <div class="wzc_color_picker" :style="styleVar">        <div class="wzc_color_wrap">            <div class="wzc_color_left" @mousedown="mouseClick($event)">                <div class="white_panel"></div>                <div class="black_panel"></div>                <div class="wzc_color_pointer" ref="wzcColorPointer"  >                    <div ></div>                </div>            </div>            <div class="wzc_color_right" >                <div class="wzc_hue_slider" @mousedown="thumbClick($event)"></div>                <div class="wzc_hue_slider_thumb" ref="wzcthumb"></div>            </div>        </div>        <div class="wzc_color_btns">            <input type="text" class="wzc_input" v-model="currentColor" @input="inputHex">
            <div class="wzc_color_show" :style="{ 'background-color': currentColor }"></div>        </div>    </div></template>
<script>export default {    name:"wzc_color_picker",    components: {},    props: {        color: {            type: String,            default: "#FF0000"        }    },    data() {        return {            currentColor: "",            backgroundColor: "",        };    },    created() {},    mounted() {        this.dragColorPointer(this.$refs.wzcColorPointer);        this.dragColorPointer(this.$refs.wzcthumb, "thumb");        this.backgroundColor = this.color;        this.currentColor = this.rgbToHex(this.color);        this.$refs.wzcColorPointer.style.left = '280px';        this.$refs.wzcColorPointer.style.top = '0px';    },    watch: {    },    computed: {        styleVar() {            return {                '--wzc-picker-color': this.backgroundColor ,            }        }    },    methods: {        dragColorPointer (el, dom) {            let dragBox = el;             dragBox.onmousedown = (e) => {                e = e || window.event;                let disX = e.clientX - dragBox.offsetLeft;                let disY = e.clientY - dragBox.offsetTop;                document.onmousemove = e => {                    let left = e.clientX - disX;                    let top = e.clientY - disY;                    if(left > 280){ left = 280; }                    if(left < 0)  { left = 0; }                    if(top > 180) { top = 180; }                    if(top < 0)   { top = 0; }                    dragBox.style.top = top + "px";                    if( dom == "thumb" ) {                        dragBox.style.left = "0px";                        this.changeThumbColor(top);                    } else {                        dragBox.style.left = left + "px";                        this.changeColor(left, top )                    }                };                document.onmouseup = e => {                    document.onmousemove = null;                    document.onmouseup = null;                };            }        },        mouseClick (e) {            if(e.target.className.indexOf("black_panel") != -1) {                this.$refs.wzcColorPointer.style.left = e.offsetX + 'px';                this.$refs.wzcColorPointer.style.top = e.offsetY + 'px';            } else {                if(e.target.className.indexOf("wzc_color_pointer") != -1) {                    if(this.$refs.wzcColorPointer.offsetLeft + e.offsetX <= 280){                        this.$refs.wzcColorPointer.style.left = this.$refs.wzcColorPointer.offsetLeft + e.offsetX + 'px';                    } else {                        this.$refs.wzcColorPointer.style.left = '280px';                    }                    if(this.$refs.wzcColorPointer.offsetTop + e.offsetY <= 180) {                        this.$refs.wzcColorPointer.style.top = this.$refs.wzcColorPointer.offsetTop + e.offsetY + 'px';                    } else {                        this.$refs.wzcColorPointer.style.top = '180px';                    }                } else{                    this.$refs.wzcColorPointer.style.left = this.$refs.wzcColorPointer.offsetLeft + e.offsetX - 6 + 'px';                    this.$refs.wzcColorPointer.style.top = this.$refs.wzcColorPointer.offsetTop + e.offsetY - 6 + 'px';                    if((this.$refs.wzcColorPointer.offsetLeft + e.offsetX - 6) < 0){                        this.$refs.wzcColorPointer.style.left = "0px"                    }                    if((this.$refs.wzcColorPointer.offsetLeft + e.offsetX - 6) >= 280){                        this.$refs.wzcColorPointer.style.left = '280px';                    }                    if((this.$refs.wzcColorPointer.offsetTop + e.offsetY - 6) < 0){                        this.$refs.wzcColorPointer.style.top = "0px";                    }                    if((this.$refs.wzcColorPointer.offsetTop + e.offsetY - 6) >= 180){                        this.$refs.wzcColorPointer.style.top = "180px";                    }                }            }            this.changeColor(parseInt(this.$refs.wzcColorPointer.style.left), parseInt(this.$refs.wzcColorPointer.style.top) )        },        thumbClick (e) {            this.$refs.wzcthumb.style.top = e.offsetY + 'px';            this.changeThumbColor(e.offsetY);        },        // 计算颜色  HSV方式计算rgb        changeColor (left, top) {            let saturation = Math.round(left / 280 * 100) / 100;            let value = Math.round((1 - top / 180) * 100) / 100;            let hue = this.getHue(this.getRGB(""+this.backgroundColor));            this.currentColor = this.rgbToHex(this.HSVtoRGB(hue, saturation, value));            this.$emit('update:color', this.currentColor);        },        changeThumbColor (top) {            let hue = Math.round((top / 180) * 360 * 100) / 100;            this.backgroundColor = this.HuetoRGB(hue);            this.changeColor(parseInt(this.$refs.wzcColorPointer.style.left), parseInt(this.$refs.wzcColorPointer.style.top) )        },        getRGB (str){            if(str.indexOf('rgb') == -1 && str.indexOf('#') > -1){                // str = "rgba(" + str.match(/[A-Za-z0-9]{2}/g).map(function(v) { return parseInt(v, 16) }).join(",") + ")";                str = this.HexTorgb( str );            }             let match = str.match(/rgba?\((\d{1,3}), ?(\d{1,3}), ?(\d{1,3})\)?(?:, ?(\d(?:\.\d?))\))?/);            return match ? {                red: match[1],                green: match[2],                blue: match[3]            } : {};        },        // Hex(16进制颜色值) and RGB          rgbToHex (color){            if(color.indexOf("#") != -1) {                return color;            }            let arr = color.split(',');            let r = +arr[0].split('(')[1];            let g = +arr[1];            let b = +arr[2].split(')')[0];            let value = (1 << 24) + r * (1 << 16) + g * (1 << 8) + b;            value = value.toString(16);            return '#' + value.slice(1);        },        HexTorgb (hex){            var hexNum = hex.substring(1);            hexNum = '0x' + (hexNum.length < 6 ? repeatLetter(hexNum, 2) : hexNum);            var r = hexNum >> 16;            var g = hexNum >> 8 & '0xff';            var b = hexNum & '0xff';            return `rgb(${r},${g},${b})`;                        function repeatWord(word, num){                var result = '';                for(let i = 0; i < num; i ++){                    result += word;                }                return result;            }            function repeatLetter(word, num){                var result = '';                for(let letter of word){                    result += repeatWord(letter, num);                }                return result;            }        },        // 根据Hue色相计算rgb纯色        HuetoRGB(h) {            let doHandle = (num) =>{                if( num > 255) {                    return 255;                } else if(num < 0){                    return 0;                } else {                    return Math.round(num);                }            }
            let hueRGB = h/60 * 255;            let r = doHandle(Math.abs(hueRGB-765)-255);            let g = doHandle(510 - Math.abs(hueRGB-510));            let b = doHandle(510 - Math.abs(hueRGB-1020));            return 'rgb(' +r + ',' + g + ',' + b + ')';          },        // rgb to Hue(色相)        getHue (rgbArray) {            let r, g, b, max, min;            for(let i = 0; i < 3; i++){                r = parseInt(rgbArray.red);                g = parseInt(rgbArray.green);                b = parseInt(rgbArray.blue);            }            max = Math.max(r, g, b)            min = Math.min(r, g, b)            if(max == min) {                return 0;            } else {                if( max == r && g >= b) {                    return 60 * (g - b)/(max - min);                } else if ( max == r && g < b) {                    return 60 * (g - b)/(max - min) + 360;                } else if (max == g) {                    return 60 * (b - r)/(max - min) + 120;                } else if (max == b) {                    return 60 * (r - g)/(max - min) + 240;                }              }        },        // HSV(色相、饱和度、亮度) and RGB        RGBtoHSV(rgb) {            rgb = this.getRGB(rgb)            var rr, gg, bb,            r = parseInt(rgb.red) / 255,            g = parseInt(rgb.green) / 255,            b = parseInt(rgb.blue) / 255,            h, s,            v = Math.max(r, g, b),            diff = v - Math.min(r, g, b),            diffc = function(c){                return (v - c) / 6 / diff + 1 / 2;            };            if (diff == 0) {                h = s = 0;            } else {                s = diff / v;  rr = diffc(r); gg = diffc(g); bb = diffc(b);                if (r === v) {                    h = bb - gg;                }else if (g === v) {                    h = (1 / 3) + rr - bb;                }else if (b === v) {                    h = (2 / 3) + gg - rr;                }                if (h < 0) {                    h += 1;                }else if (h > 1) {                    h -= 1;                }            }            return {                h: Math.round(h * 360),                s: Math.round(s * 100),                v: Math.round(v * 100)            };        },        HSVtoRGB(h, s, v) {            let i, f, p1, p2, p3;            let r = 0, g = 0, b = 0;            if (s < 0) s = 0;            if (s > 1) s = 1;            if (v < 0) v = 0;            if (v > 1) v = 1;            h %= 360;            if (h < 0) h += 360;            h /= 60;            i = Math.floor(h);            f = h - i;            p1 = v * (1 - s);            p2 = v * (1 - s * f);            p3 = v * (1 - s * (1 - f));            switch(i) {                case 0: r = v;  g = p3; b = p1; break;                case 1: r = p2; g = v;  b = p1; break;                case 2: r = p1; g = v;  b = p3; break;                case 3: r = p1; g = p2; b = v;  break;                case 4: r = p3; g = p1; b = v;  break;                case 5: r = v;  g = p1; b = p2; break;            }            return 'rgb(' + Math.round(r * 255) + ',' + Math.round(g * 255) + ',' + Math.round(b * 255) + ')';        },        // 根据HSV计算位置        HSVtoPos (hsv) {            let left = hsv.s / 100 * 280;            let top = 180 - ( hsv.v / 100 * 180 );            this.$refs.wzcColorPointer.style.left = Math.round(left) + 'px';            this.$refs.wzcColorPointer.style.top = Math.round(top) + 'px';        },        inputHex (item){            let str = item.target.value;            if( str.length < 4 ) return ;            if( this.getHue(this.getRGB(str)) == undefined || this.getHue(this.getRGB(str)) > 360 || this.getHue(this.getRGB(str)) < 0 ) {                return ;            } else {                let hsv = this.RGBtoHSV(str);                let backgroundHue = this.getHue(this.getRGB(this.backgroundColor));                if (hsv.h == backgroundHue) {                    this.HSVtoPos(hsv);                } else {                    this.backgroundColor = str;                    this.$refs.wzcColorPointer.style.left = '280px';                    this.$refs.wzcColorPointer.style.top = '0px';                }            }            this.$emit('update:color', this.currentColor);        }    },};</script><style scoped>    .wzc_color_picker {        width: 314px;        height: 228px;        padding: 6px;        box-sizing: content-box;        background-color: #fff;        border: 1px solid #ebeef5;        border-radius: 4px;        box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);    }    .wzc_color_wrap {        width: 100%;        height: 180px;        display: flex;        justify-content: space-around;    }    .wzc_color_left {        width: 280px;        height: 100%;        position: relative;        background-color: var(--wzc-picker-color);        overflow: hidden;    }    .wzc_color_right {        width: 12px;        height: 100%;        position: relative;    }    .wzc_color_left .white_panel,    .wzc_color_left .black_panel{        position: absolute;        top: 0;        left: 0;        right: 0;        bottom: 0;    }    .wzc_color_left .white_panel {        background: linear-gradient(90deg,#fff,hsla(0,0%,100%,0));    }    .wzc_color_left .black_panel {        background: linear-gradient(0deg,#000,transparent);    }    .wzc_color_pointer {        position: absolute;        top: 0px;        left: 280px;    }    .wzc_color_pointer > div {        width: 12px;        height: 12px;        border-radius: 6px;        box-shadow: rgb(255, 255, 255) 0px 0px 0px 1px inset;        transform: translate(-6px, -6px);    }    .wzc_color_right .wzc_hue_slider {        height: 100%;        background: linear-gradient(180deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red);    }    .wzc_hue_slider_thumb {        position: absolute;        cursor: pointer;        box-sizing: border-box;        left: 0;        top: 0;        width: 12px;        height: 4px;        border-radius: 1px;        background: #fff;        border: 1px solid #f0f0f0;        box-shadow: 0 0 2px rgba(0,0,0,.6);        z-index: 1;    }    .wzc_color_btns .wzc_input {        width: 155px;        height: 28px;        line-height: 28px;        background-color: #fff;        background-image: none;        border-radius: 4px;        border: 1px solid #dcdfe6;        box-sizing: border-box;        color: #606266;        display: inline-block;        font-size: inherit;        outline: none;        padding: 0 15px;        margin-left: 5px;    }    .wzc_color_show {        width: 28px;        height: 28px;        border-radius: 5px;        margin-left: 15px;    }    .wzc_color_btns {        width: 100%;        height: 28px;        margin-top: 10px;        display: flex;    }</style>
评论