vue自定义颜色选择器(重置版)

实现效果

相较于上次发布的颜色选择器,这次加入了圆形的选择器,并且优化了代码。

<SquareColor ref="squareColor" :color="color" @change="changeColor1" />

setColor1() {
            // this.color = 'rgba(255, 82, 111, 0.5)'
            this.$refs.squareColor.changeColor('rgba(255, 82, 111, 0.5)')
        }

使用方式:可以使用color属性传入默认颜色,目前支持hex16进制,rgb,rgba,hsl这四种格式,使用change事件获取颜色修改后的值,如果需要父组件动态修改其中的颜色则需要调用组件中的changeColor方法。

如果需要修改传出的颜色类型可以在组件中的getRGBA方法中进行修改,或者在父组件中使用color-convert进行转换。

在使用该组件之前需要引入color-convert依赖

npm install color-convert

完整代码:该代码主要分为四个部分(方形选择器组件,圆形选择器组件,utils,父组件示例)

方形选择器:

<template>
    <div class="color-box">
        <div class="color-panel" ref="colorPanel" @mousedown="colorPanelMD" :style="{ background: colorPanelColor }">
            <div class="color-white-panel"></div>
            <div class="color-black-panel"></div>
            <div ref="colorPanelSliderThumb" class="color-panel-slider-thumb"></div>
        </div>
        <div class="hue-panel" ref="huePanel" @mousedown="huePanelMD">
            <div ref="huePanelSliderThumb" class="hue-slider-thumb"></div>
        </div>
        <div class="alpha-panel" ref="alphaPanel" @mousedown="alphaPanelMD">
            <div class="alpha-panel-cover"
                :style="{ background: `linear-gradient(to right, rgba(255, 255, 255, 0) 0, ${colorPanelColor} 100%)` }">
            </div>
            <div ref="alphaPanelSliderThumb" class="alpha-slider-thumb"></div>
        </div>
    </div>
</template>

<script>
import convert from 'color-convert'
import { colorTypeConversion } from '@/utils'
export default {
    props: {
        color: {
            type: String,
            required: true,
            default: ''
        }
    },
    data() {
        return {
            colorPanelColor: 'red',
            h: 0,
            s: 0,
            v: 100,
            alpha: 1,
        };
    },
    mounted() {
        this.changeColor(this.color)
    },

    methods: {
        // 设置颜色 转换颜色为hsv类型
        changeColor(val) {
            let colorObj = colorTypeConversion(val)
            if (colorObj?.alpha) {
                this.alpha = colorObj.alpha
            }
            if (colorObj?.color?.length == 3) {
                let [h, s, v] = colorObj.color
                // 判断当前颜色是否和需要转换的颜色是否一致,一致则不进行转换
                if (this.h !== h || this.s !== s || this.v !== v) {
                    this.h = colorObj.color[0]
                    this.s = colorObj.color[1]
                    this.v = colorObj.color[2]
                    this.$nextTick(() => {
                        this.initPosi();
                    })
                }
            }
        },
        // 初始化hsv初始位置
        initPosi() {
            // 设置色相条按钮位置
            this.$refs.huePanelSliderThumb.style.left = this.h / 360 * this.$refs.huePanel.offsetWidth + 'px'
            // 设置透明度条按钮位置
            this.$refs.alphaPanelSliderThumb.style.left = this.alpha * this.$refs.alphaPanel.offsetWidth + 'px'
            // 设置色盘按钮位置
            this.$refs.colorPanelSliderThumb.style.left = this.s / 100 * this.$refs.colorPanel.offsetWidth + 'px'
            this.$refs.colorPanelSliderThumb.style.top = (100 - this.v) / 100 * this.$refs.colorPanel.offsetHeight + 'px'
            // 设置色盘和透明度背景色
            this.colorPanelColor = '#' + convert.hsv.hex(this.h, this.s, this.v)
        },
        // 色盘鼠标事件
        colorPanelMD(e) {
            let that = this
            let colorPanel = that.$refs.colorPanel
            let colorPanelSliderThumb = that.$refs.colorPanelSliderThumb
            let { width, height } = colorPanel.getBoundingClientRect()
            colorPanelSliderThumb.style.left = that.judgeBoundary(e.offsetX, 0, width) + 'px'
            colorPanelSliderThumb.style.top = that.judgeBoundary(e.offsetY, 0, height) + 'px'
            that.getSV()
            let initLeft = colorPanelSliderThumb.offsetLeft
            let initTop = colorPanelSliderThumb.offsetTop
            let initX = e.pageX
            let initY = e.pageY
            document.addEventListener('mousemove', mouseMove)
            function mouseMove(e) {
                colorPanelSliderThumb.style.left = that.judgeBoundary(e.pageX - initX + initLeft, 0, width) + 'px'
                colorPanelSliderThumb.style.top = that.judgeBoundary(e.pageY - initY + initTop, 0, height) + 'px'
                that.getSV()
            }
            document.addEventListener('mouseup', mouseUp)
            function mouseUp() {
                document.removeEventListener('mousemove', mouseMove)
                document.removeEventListener('mouseup', mouseUp)
            }
        },
        // 获取饱和度和明值
        getSV() {
            let that = this
            let colorPanel = that.$refs.colorPanel
            let colorPanelSliderThumb = that.$refs.colorPanelSliderThumb
            let { width, height } = colorPanel.getBoundingClientRect()
            let left = colorPanelSliderThumb.offsetLeft
            let top = colorPanelSliderThumb.offsetTop
            let s = left / width * 100
            let v = 100 - top / height * 100
            that.s = s
            that.v = v
            that.getRGBA();
        },
        // 色相鼠标事件
        huePanelMD(e) {
            let that = this
            let huePanel = that.$refs.huePanel
            let huePanelSliderThumb = that.$refs.huePanelSliderThumb
            let { width } = huePanel.getBoundingClientRect()
            huePanelSliderThumb.style.left = that.judgeBoundary(e.offsetX, 0, width) + 'px'
            that.getHue();
            let initLeft = huePanelSliderThumb.offsetLeft
            let initX = e.pageX
            document.addEventListener('mousemove', mouseMove)
            function mouseMove(e) {
                huePanelSliderThumb.style.left = that.judgeBoundary(e.pageX - initX + initLeft, 0, width) + 'px'
                that.getHue();
            }
            document.addEventListener('mouseup', mouseUp)
            function mouseUp() {
                document.removeEventListener('mousemove', mouseMove)
                document.removeEventListener('mouseup', mouseUp)
            }
        },
        // 获取色相并转换成颜色
        getHue() {
            let that = this
            let huePanel = that.$refs.huePanel
            let huePanelSliderThumb = that.$refs.huePanelSliderThumb
            let { width } = huePanel.getBoundingClientRect()
            let hue = huePanelSliderThumb.offsetLeft / width * 360
            that.h = hue
            let color = convert.hsv.hex(hue, 100, 100)
            that.colorPanelColor = '#' + color
            that.getRGBA();
        },
        // 透明度鼠标事件
        alphaPanelMD(e) {
            let that = this
            let alphaPanel = that.$refs.alphaPanel
            let alphaPanelSliderThumb = that.$refs.alphaPanelSliderThumb
            let { width } = alphaPanel.getBoundingClientRect()
            alphaPanelSliderThumb.style.left = that.judgeBoundary(e.offsetX, 0, width) + 'px'
            that.getAlpha();
            let initLeft = alphaPanelSliderThumb.offsetLeft
            let initX = e.pageX
            document.addEventListener('mousemove', mouseMove)
            function mouseMove(e) {
                alphaPanelSliderThumb.style.left = that.judgeBoundary(e.pageX - initX + initLeft, 0, width) + 'px'
                that.getAlpha();
            }
            document.addEventListener('mouseup', mouseUp)
            function mouseUp() {
                document.removeEventListener('mousemove', mouseMove)
                document.removeEventListener('mouseup', mouseUp)
            }
        },
        getAlpha() {
            let that = this
            let alphaPanel = that.$refs.alphaPanel
            let alphaPanelSliderThumb = that.$refs.alphaPanelSliderThumb
            let { width } = alphaPanel.getBoundingClientRect()
            let alpha = (alphaPanelSliderThumb.offsetLeft / width).toFixed(2)
            that.alpha = alpha
            this.getRGBA();
        },
        // 获取RGBA色值
        getRGBA() {
            let color = convert.hsv.rgb(this.h, this.s, this.v)
            let rgba = `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${this.alpha})`
            this.$emit('change', rgba)
        },
        // 边界判断
        judgeBoundary(value, min, max) {
            if (value < min) {
                return min
            }
            if (value > max) {
                return max
            }
            return value
        },
    },
};
</script>

<style lang="scss" scoped>
.color-box {
    width: 300px;

    .color-panel {
        position: relative;
        height: 200px;
        // background-color: red;

        .color-white-panel {
            position: absolute;
            inset: 0;
            background: linear-gradient(to right, #fff 0%, transparent 100%);
        }

        .color-black-panel {
            position: absolute;
            inset: 0;
            background: linear-gradient(to top, #000 0%, transparent 100%);
        }

        .color-panel-slider-thumb {
            position: absolute;
            top: 0;
            left: 0;
            transform: translate(-50%, -50%);
            width: 5px;
            height: 5px;
            box-shadow: 0 0 2px #5a5a5a;
            border: 3px solid #fff;
            border-radius: 50%;
            pointer-events: none;
        }
    }

    .hue-panel {
        position: relative;
        height: 12px;
        margin: 20px 0;
        background: linear-gradient(to right, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red);
    }

    .alpha-panel {
        position: relative;
        height: 12px;
        background: url('../../assets/images/alpha.png');

        .alpha-panel-cover {
            position: absolute;
            inset: 0;
        }

        .alpha-slider-thumb {
            left: 100%;
        }
    }
}


.hue-slider-thumb,
.alpha-slider-thumb {
    position: absolute;
    left: 0;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 5px;
    height: 140%;
    border-radius: 4px;
    background-color: #fff;
    box-shadow: 0 0 2px #5a5a5a;
    cursor: pointer;
    pointer-events: none;
}
</style>

圆形选择器:

<template>
    <div class="color-box">
        <div class="top-part">
            <div :style="{ width: width + 'px', height: width + 'px' }" class="color-panel" ref="colorPanel"
                @mousedown="colorPanelMD">
                <div class="value-bg" ref="valueBg"></div>
                <div ref="colorPanelSliderThumb" class="color-panel-slider-thumb"></div>
            </div>
            <div class="value-panel" @mousedown="valuePanelMD" ref="valuePanel" :style="{ height: width + 'px' }">
                <div ref="valuePanelSliderThumb" class="value-slider-thumb"></div>
            </div>
        </div>
        <div :style="{ width: width + 'px' }" class="alpha-panel" ref="alphaPanel" @mousedown="alphaPanelMD">
            <div class="alpha-panel-cover"
                :style="{ background: `linear-gradient(to right, rgba(255, 255, 255, 0) 0, ${colorPanelColor} 100%)` }">
            </div>
            <div ref="alphaPanelSliderThumb" class="alpha-slider-thumb"></div>
        </div>
    </div>
</template>

<script>
import convert from 'color-convert'
import { colorTypeConversion } from '@/utils'
export default {
    props: {
        width: {
            type: Number,
            default: 200,
            required: false,
        },
        color: {
            type: String,
            required: true,
            default: ''
        }
    },
    data() {
        return {
            h: 0,
            s: 0,
            v: 100,
            alpha: 1,
            colorPanelColor: '#fff',
        };
    },

    mounted() {
        this.changeColor(this.color)
    },

    methods: {
        // 设置颜色 转换颜色为hsv类型
        changeColor(val) {
            let colorObj = colorTypeConversion(val)
            if (colorObj?.alpha) {
                this.alpha = colorObj.alpha
            }
            if (colorObj?.color?.length == 3) {
                let [h, s, v] = colorObj.color
                // 判断当前颜色是否和需要转换的颜色是否一致,一致则不进行转换
                if (this.h !== h || this.s !== s || this.v !== v) {
                    this.h = colorObj.color[0]
                    this.s = colorObj.color[1]
                    this.v = colorObj.color[2]
                    this.$nextTick(() => {
                        this.initPosi();
                    })
                }
            }
        },
        // 初始化hsv初始位置
        initPosi() {
            // 设置明值位置即右侧柱子按钮位置
            let height = this.$refs.valuePanel.getBoundingClientRect().height
            this.$refs.valuePanelSliderThumb.style.top = height - height * this.v / 100 + 'px'
            this.$refs.valueBg.style.background = `rgba(0, 0, 0, ${Number(1 - (this.v / 100).toFixed(2))})`
            // 获取饱和度(长度) 和 色相(夹角)
            const vector = [0, 1]; // 假设圆心为坐标原点,并使用夹角度数配合旋转矩阵以及按钮距离圆心的长度求取按钮在色盘中的位置
            let r = this.width / 2
            let length = this.s / 100 * r
            let angle = -Number((this.h - Math.PI / 180).toFixed(2))
            // 将角度转为弧度
            const angleInRadians = angle * Math.PI / 180;
            // 计算另一个向量
            const x = vector[0] * Math.cos(angleInRadians) - vector[1] * Math.sin(angleInRadians);
            const y = vector[0] * Math.sin(angleInRadians) + vector[1] * Math.cos(angleInRadians);
            // 根据长度进行缩放
            const scaleFactor = length / Math.sqrt(x * x + y * y);
            const newX = x * scaleFactor;
            const newY = y * scaleFactor;
            this.$refs.colorPanelSliderThumb.style.left = newX + r + 'px'
            this.$refs.colorPanelSliderThumb.style.top = r - newY + 'px'
            // 给底部透明度设置背景
            this.colorPanelColor = '#' + convert.hsv.hex(this.h, this.s, this.v)
            // 设置透明度按钮位置
            let { width } = this.$refs.alphaPanel.getBoundingClientRect()
            this.$refs.alphaPanelSliderThumb.style.left = width * this.alpha + 'px'
        },
        colorPanelMD(e) {
            let that = this
            const colorPanelSliderThumb = that.$refs.colorPanelSliderThumb
            colorPanelSliderThumb.style.left = e.offsetX + 'px'
            colorPanelSliderThumb.style.top = e.offsetY + 'px'
            that.calculateAngle() // 计算夹角 获取色相
            let initLeft = colorPanelSliderThumb.offsetLeft
            let initTop = colorPanelSliderThumb.offsetTop
            let initX = e.pageX
            let initY = e.pageY
            document.addEventListener('mousemove', mouseMove)
            function mouseMove(e) {
                let x = e.pageX - initX + initLeft
                let y = e.pageY - initY + initTop
                colorPanelSliderThumb.style.left = that.circleJudgeBoundary(x, y).targetX + 'px'
                colorPanelSliderThumb.style.top = that.circleJudgeBoundary(x, y).targetY + 'px'
                that.calculateAngle() // 计算夹角 获取色相
            }

            document.addEventListener('mouseup', mouseUp)
            function mouseUp(e) {
                document.removeEventListener('mousemove', mouseMove)
                document.removeEventListener('mouseup', mouseUp)
            }
        },
        // 获取当前滑块的向量坐标归一化 并获取其饱和度值
        calcSliderThumbVector() {
            let r = this.width / 2
            const colorPanel = this.$refs.colorPanel
            const colorPanelSliderThumb = this.$refs.colorPanelSliderThumb
            let { width, height, left, top } = colorPanel.getBoundingClientRect()
            let originX = left + width / 2 - colorPanel.offsetLeft
            let originY = top + height / 2 - colorPanel.offsetTop
            let x = (colorPanelSliderThumb.getBoundingClientRect().left - left + colorPanelSliderThumb.getBoundingClientRect().width / 2) - originX
            let y = originY - (colorPanelSliderThumb.getBoundingClientRect().top - top + colorPanelSliderThumb.getBoundingClientRect().height / 2)
            // 获取饱和度
            let s = Number((Math.sqrt(x ** 2 + y ** 2) / r * 100).toFixed(2))
            this.s = s <= 100 ? s : 100
            return this.normalizeVector([x, y])
        },
        // 归一化二维向量
        normalizeVector(vector) {
            // 计算向量的模长
            const magnitude = Math.sqrt(vector[0] ** 2 + vector[1] ** 2);
            // 将向量的每个分量除以模长
            const normalizedVector = [vector[0] / magnitude, vector[1] / magnitude];
            return normalizedVector;
        },
        // 计算两个二维向量的夹角 夹角度数即色相
        calculateAngle(vectorA = [0, 1], vectorB = this.calcSliderThumbVector(), isGetRGBA = true) {
            // 计算向量的点积
            const dotProduct = vectorA[0] * vectorB[0] + vectorA[1] * vectorB[1];
            // 计算向量的模长
            const magnitudeA = Math.sqrt(vectorA[0] ** 2 + vectorA[1] ** 2);
            const magnitudeB = Math.sqrt(vectorB[0] ** 2 + vectorB[1] ** 2);
            // 计算夹角的余弦值
            let cosTheta;
            if (magnitudeA * magnitudeB === 0) {
                cosTheta = 0
            } else {
                cosTheta = dotProduct / (magnitudeA * magnitudeB);
            }
            // 计算夹角的弧度值
            const angleRad = Math.acos(cosTheta);
            let h;
            if (vectorB[0] < 0 && isGetRGBA) {
                h = Number((((2 * Math.PI - angleRad) * 180) / Math.PI).toFixed(2));

            } else {
                h = Number(((angleRad * 180) / Math.PI).toFixed(2));

            }
            this.h = h
            if (isGetRGBA) this.getRGBA();
            return h;
        },
        // 圆盘边界判断
        circleJudgeBoundary(targetX, targetY) {
            const colorPanel = this.$refs.colorPanel
            let { width, height, left, top } = colorPanel.getBoundingClientRect()
            let originX = left + width / 2 - colorPanel.offsetLeft
            let originY = top + height / 2 - colorPanel.offsetTop
            let x = targetX - originX
            let y = originY - targetY
            // 判断鼠标是否已经超出的圆盘 如果超出了圆盘 则将鼠标位置限制在圆盘内
            if (Math.sqrt(x ** 2 + y ** 2) <= this.width / 2) {
                return { targetX, targetY }
            } else {
                // 计算目标坐标的夹角
                let angle = this.calculateAngle([x, 0], [x, y], false)
                // 计算标记点在圆盘边缘的坐标位置 以圆盘中心为原点
                let r = this.width / 2 // 半径
                let realX = (r * Math.cos(angle * Math.PI / 180)) * (x / Math.abs(x)) + r
                let realY = r - (r * Math.sin(angle * Math.PI / 180)) * (y / Math.abs(y))
                return { targetX: Number(realX.toFixed(2)), targetY: Number(realY.toFixed(2)) }
            }
        },
        valuePanelMD(e) {
            let that = this
            let valuePanel = that.$refs.valuePanel
            let { top, height } = valuePanel.getBoundingClientRect()
            let valuePanelSliderThumb = that.$refs.valuePanelSliderThumb
            let initY = e.pageY
            valuePanelSliderThumb.style.top = initY - top - valuePanelSliderThumb.getBoundingClientRect().height / 2 + 'px'
            that.getValue()
            let initTop = valuePanelSliderThumb.offsetTop

            document.addEventListener('mousemove', mouseMove)
            function mouseMove(e) {
                valuePanelSliderThumb.style.top = that.judgeBoundary(initTop + e.pageY - initY, 0, height) + 'px'
                that.getValue()
            }
            document.addEventListener('mouseup', mouseUp)
            function mouseUp() {
                document.removeEventListener('mousemove', mouseMove)
                document.removeEventListener('mouseup', mouseUp)
            }
        },
        // 获取明值
        getValue() {
            let valuePanel = this.$refs.valuePanel
            let { height } = valuePanel.getBoundingClientRect()
            let offsetTop = this.$refs.valuePanelSliderThumb.offsetTop
            this.v = 100 - Number((offsetTop / height * 100).toFixed(2))
            this.$refs.valueBg.style.background = `rgba(0, 0, 0, ${Number(1 - (this.v / 100).toFixed(2))})`
            this.getRGBA()
        },
        // 透明度鼠标事件
        alphaPanelMD(e) {
            let that = this
            let alphaPanel = that.$refs.alphaPanel
            let alphaPanelSliderThumb = that.$refs.alphaPanelSliderThumb
            let { width } = alphaPanel.getBoundingClientRect()
            alphaPanelSliderThumb.style.left = that.judgeBoundary(e.offsetX, 0, width) + 'px'
            that.getAlpha();
            let initLeft = alphaPanelSliderThumb.offsetLeft
            let initX = e.pageX
            document.addEventListener('mousemove', mouseMove)
            function mouseMove(e) {
                alphaPanelSliderThumb.style.left = that.judgeBoundary(e.pageX - initX + initLeft, 0, width) + 'px'
                that.getAlpha();
            }
            document.addEventListener('mouseup', mouseUp)
            function mouseUp() {
                document.removeEventListener('mousemove', mouseMove)
                document.removeEventListener('mouseup', mouseUp)
            }
        },
        getAlpha() {
            let that = this
            let alphaPanel = that.$refs.alphaPanel
            let alphaPanelSliderThumb = that.$refs.alphaPanelSliderThumb
            let { width } = alphaPanel.getBoundingClientRect()
            let alpha = (alphaPanelSliderThumb.offsetLeft / width).toFixed(2)
            that.alpha = alpha
            this.getRGBA();
        },
        // 获取RGBA色值
        getRGBA() {
            let color = convert.hsv.rgb(this.h, this.s, this.v)
            let rgba = `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${this.alpha})`
            this.colorPanelColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`
            this.$emit('change', rgba)
        },
        // 明值和透明度边界判断
        judgeBoundary(value, min, max) {
            if (value < min) {
                return min
            }
            if (value > max) {
                return max
            }
            return value
        },

    },
};
</script>
<style lang="scss" scoped>
.color-box {
    .top-part {
        display: flex;

        .color-panel {
            position: relative;
            border-radius: 50%;
            background: conic-gradient(red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red);

            &::before {
                content: '';
                position: absolute;
                inset: 0;
                border-radius: 50%;
                z-index: 10000;
                background: radial-gradient(#fff 0, transparent 80%);
            }

            .value-bg {
                position: absolute;
                inset: 0;
                z-index: 10010;
                border-radius: 50%;
            }

            .color-panel-slider-thumb {
                position: absolute;
                top: 50%;
                left: 50%;
                z-index: 10999;
                transform: translate(-50%, -50%);
                width: 6px;
                height: 6px;
                background: #fff;
                border: 1px solid #000;
                border-radius: 50%;
                pointer-events: none;
                box-sizing: border-box;
            }
        }

        .value-panel {
            position: relative;
            width: 12px;
            background: linear-gradient(to bottom, #fff 0, #000 100%);
            margin-left: 20px;

            .value-slider-thumb {
                position: absolute;
                top: 0;
                left: 50%;
                transform: translate(-50%, 0);
                width: 120%;
                height: 5px;
                border-radius: 4px;
                background-color: #fff;
                box-shadow: 0 0 2px #5a5a5a;
                pointer-events: none;
            }
        }

    }

    .alpha-panel {
        position: relative;
        height: 12px;
        background: url('../../assets/images/alpha.png');
        margin-top: 20px;

        .alpha-panel-cover {
            position: absolute;
            inset: 0;
        }

        .alpha-slider-thumb {
            position: absolute;
            left: 100%;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 5px;
            height: 140%;
            border-radius: 4px;
            background-color: #fff;
            box-shadow: 0 0 2px #5a5a5a;
            cursor: pointer;
            pointer-events: none;
        }
    }
}
</style>

uitls>index.js:

import convert from 'color-convert'
// color: 颜色,type: 需要转换的类型
export function colorTypeConversion(color, type = 'hsv') {
    let reg = /(d+(.d+)?)|(.d+)/g
    // 判断颜色类型 并转换
    if (color.startsWith('#')) {
        return {
            color: convert.hex[type](color),
            alpha: 1
        }
    } else if (color.startsWith('rgba')) {
        let arr = color.match(reg).map(item => Number(item))
        return {
            color: convert.rgb[type](arr[0], arr[1], arr[2]),
            alpha: arr[3]
        }
    } else if (color.startsWith('rgb')) {
        let arr = color.match(reg).map(item => Number(item))
        return {
            color: convert.rgb[type](arr[0], arr[1], arr[2]),
            alpha: 1
        }
    } else if (color.startsWith('hsl')) {
        let arr = color.match(reg)
        return {
            color: convert.hsl[type]([arr[0], arr[1], arr[2]]),
            alpha: 1
        }
    } else {
        return {
            color: convert.hex[type](color),
            alpha: 1
        }
    }
}

父组件示例:

<template>
    <div class="page1">
        <div class="box">
            <div style="margin-bottom: 25px;">
                <span>{{ color }}</span>
                <div class="show-color" :style="{ background: color }"></div>
            </div>
            <SquareColor ref="squareColor" :color="color" @change="changeColor1" />
            <button @click="setColor1">修改为 rgba(255, 82, 111, 0.5)</button>
        </div>
        <div class="box">
            <div style="margin-bottom: 25px;">
                <span>{{ color2 }}</span>
                <div class="show-color" :style="{ background: color2 }"></div>
            </div>
            <CircleColor ref="circleColor" :color="color2" @change="changeColor2" />
            <button @click="setColor2">修改为 #5fff45</button>
        </div>
    </div>
</template>

<script>
import SquareColor from '@/components/color/square.vue'
import CircleColor from '@/components/color/circle.vue'
export default {
    name: 'ComponentPage1',
    components: {
        SquareColor,
        CircleColor,
    },
    data() {
        return {
            color: 'hsl(107.74deg 88.62% 47.73%)',
            color2: 'rgba(255, 66, 237, 1)',
        };
    },

    mounted() { },

    methods: {
        setColor1() {
            this.color = 'rgba(255, 82, 111, 0.5)'
            this.$refs.squareColor.changeColor('rgba(255, 82, 111, 0.5)')
        },
        setColor2() {
            this.color2 = '#5fff45'
            this.$refs.circleColor.changeColor('#5fff45')
        },
        changeColor1(color) {
            this.color = color
        },
        changeColor2(color) {
            this.color2 = color
        }
    },
};
</script>

<style lang="scss" scoped>
.page1 {
    display: flex;
    flex-wrap: wrap;
    gap: 50px;
    padding: 100px;

    .box {
        padding: 20px;
        box-shadow: 0 0 8px #b8b7b7;
        border-radius: 10px;

        .show-color {
            display: inline-block;
            width: 100px;
            height: 25px;
            margin-left: 25px;
            vertical-align: middle;
            box-shadow: 0 0 8px #b8b7b7;
            border-radius: 4px;
        }
    }
}

button {
    background-color: #409eff;
    color: #fff;
    border: none;
    padding: 8px 15px;
    border-radius: 4px;
    margin: 20px 0;
    cursor: pointer;
}
</style>

完整项目代码压缩包:colorPicker

相关推荐
ai产品老杨29 分钟前
提前对风险进行预警并实施管控,运用AI技术将管理推向新时代的智慧地产开源了。
vue.js·人工智能·安全·开源·音视频
前端熊猫36 分钟前
组件十大传值
前端·javascript·vue.js
GISer_Jing1 小时前
React 工具和库面试题(一)
javascript·react.js·ecmascript
oumae-kumiko1 小时前
【JS/TS鼠标气泡跟随】文本提示 / 操作提示
前端·javascript·typescript
YG·玉方1 小时前
键盘常见键的keyCode和对应的键名
前端·javascript·计算机外设
我码玄黄2 小时前
在THREEJS中加载3dtile模型
前端·javascript·3d·threejs
悠悠华2 小时前
使用layui的table提示Could not parse as expression(踩坑记录)
前端·javascript·layui
谎言西西里2 小时前
JavaScript类型转换(下):掌握 Object 类型 与 隐性 的转换逻辑😎
javascript
licy__3 小时前
Vue 3 中页面跳转方式的详细介绍
前端·javascript·vue.js
前端热爱者3 小时前
vue-element-admin npm install 安装失败,tui-editor更名导致
前端·vue.js·npm·tui-editor