likes
comments
collection
share

实现一个颜色选择器

作者站长头像
站长
· 阅读数 22

颜色选取器要怎么做?最粗暴的就是3重循环覆盖所有色值。试试?

双重循环 + 滑块

<template>
    <view class="content">
        <view>色块:</view>
        <view :style="`width: 100px;height:100px;background-color: ${rgb};`"></view>
        <view>色值:</view>
        <view>{{rgb}}</view>
        <view class="picker">
            <view v-for="(x, r) in 256" :key="r">
                <view v-for="(y, g) in 256" :key="g"
                    :style="`width: 1px; height: 1px; background-color: rgb(${r}, ${g}, ${b})`" @click="getColor(r, g)">
                </view>
            </view>
            <view class="spin" :style="`left: ${r-10}px;top:${g-10}px;background-color: rgb(${r}, ${g}, ${b})`"></view>
        </view>
        <slider style="width: 90%" value="0" @change="sliderChange" min="0" max="255" show-value />
    </view>
</template>

<script>
    export default {
        data() {
            return {
                r: 0,
                g: 0,
                b: 0,
                rgb: ''
            }
        },
        methods: {
            sliderChange(e) {
                this.b = e.target.value;
                this.rgb = `rgb(${this.r}, ${this.g}, ${this.b})`
                this.$forceUpdate()
            },
            getColor(r, g) {
                this.r = r;
                this.g = g;
                this.rgb = `rgb(${r}, ${g}, ${this.b})`;
            }
        }
    }
</script>

<style>
    .content {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .picker {
        position: relative;
        width: 256px;
        height: 256px;
        display: flex;
        flex-wrap: wrap;
    }

    .spin {
        width: 20px;
        height: 20px;
        border-radius: 10px;
        position: absolute;
        border: 2px solid #fff;
        box-sizing: border-box;
    }
</style>

效果如下:

实现一个颜色选择器

貌似是完成了,但是!细心的同学一定发现了猫腻,双重循环下,页面渲染div就是256 * 256 = 65536 个div

实现一个颜色选择器

这样页面必然卡成狗。那怎么办呢,欸,我们可以用css3的渐变色,将一行256个div变成一个div。这样页面元素就大大减少了,说干就干!

渐变 + 一重循环

<template>
    <view class="content">
        <view>色块:</view>
        <view :style="`width: 100px;height:100px;background-color: ${rgb};`"></view>
        <view>色值:</view>
        <view>{{rgb}}</view>
        <view class="picker" id="picker">
            <view v-for="(x, g) in 256" :key="g"
                @click="getColor"
                :style="`width: 256px;height: 1px;background: linear-gradient(to right, rgb(0,${g},${b}) , rgb(255,${g},${b} ));`">
            </view>
            <view class="spin" :style="`left: ${r-10}px;top:${g-10}px;background-color: rgb(${r}, ${g}, ${b})`"></view>
        </view>
        <slider style="width: 90%" value="0" @change="sliderChange" min="0" max="255" show-value />
    </view>
</template>

<script>
    export default {
        data() {
            return {
                r: 0,
                g: 0,
                b: 0,
                rgb: ''
            }
        },
        methods: {
            sliderChange(e) {
                this.b = e.target.value;
                this.rgb = `rgb(${this.r}, ${this.g}, ${this.b})`
                this.$forceUpdate()
            },
            getColor(e) {
                this.g = e.target.offsetTop;
                this.r = e.target.x - document.getElementById('picker').offsetLeft
                this.rgb = `rgb(${this.r}, ${this.g}, ${this.b})`;
            }
        }
    }
</script>

<style>
    .content {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .picker {
        position: relative;
        width: 256px;
        height: 256px;
        display: flex;
        flex-wrap: wrap;
    }

    .spin {
        width: 20px;
        height: 20px;
        border-radius: 10px;
        position: absolute;
        border: 2px solid #fff;
        box-sizing: border-box;
    }
</style>

由于是渐变的,所以需要通过鼠标点击的位置来确定点的是什么色值。这样改进之后,页面顺畅了100倍。

实现一个颜色选择器

业界做法

业界的color-picker是怎么实现的,我还没去研究过,应该比上述的方法要优雅得多,有兴趣的同学可以去学习学习,然后评论区教我啊,哈哈哈,今天就到这里了,晚安!

转载自:https://juejin.cn/post/7102422599988150279
评论
请登录