在编辑器中,颜色选择器是最常见的组件,UI的设计大同小异,今天来以微信公众号后台为例
可以看到,微信公众平台编辑器中的颜色选择器大致分为四部分:
- 最近常用颜色
- 基本色
- 更多颜色
- 输入框和确定
常用颜色/基本色
这一部分不必多赘述,循环出方格,背景颜色设置为所需颜色即可
html
//最近常用颜色
<ul class="recentCo_ul">
<li class="recentCo_li recentCo_first" title="清除颜色" @click="handleClearColor"></li>
<li class="recentCo_li cursor" v-for="(item, index) in recentColorList" :key="index":style="`background:${item}`" :data-color="`${item}`" :title="`${item}`" @click="handleCheckColor">
</li>
</ul>
最近常用颜色的存储可以接口获取,或者存储在本地缓存中。
颜色模型
在开发之前,需要了解一些基础的颜色模型知识。颜色模型,是用来表示颜色的数学模型,比如常见的RGB
,CMYK
,HSL
,HSV
等。 目前前端比较常用的是RGB
和HSL
模型,而颜色选择器中大都使用的是HSV
模型,因此主要介绍这三种模型。
1、RGB模型
rgb
即红(red)、绿(green)、蓝(blue)三原色模型,前端赋值颜色时使用的rgb(0,0,0)
、rgba(0,0,0,0.5)
、#000000
、black
等表示方式都属于rgb
模型。
百度百科中显示:
RGB(Red, Green, Blue)颜色模型通常使用于彩色阴极射线管等彩色光栅图形显示设备中,彩色光栅图形的显示器都使用R、G、B数值来驱动R、G、B 电子枪发射电子,并分别激发荧光屏上的R、G、B三种颜色的荧光粉发出不同亮度的光线,并通过相加混合产生各种颜色
因此,颜色选择器中的颜色最终需要转化为rgb/rgba
格式或十六进制hex
格式供显示器显示出来。
2、HSL模型
HSL
是从人的视觉系统出发,用色相H(hue)
、饱和度S(saturation)
、亮度L(lightness)
来描述色彩。
- 色相(H): 色彩三要素之一,代表人眼能看到的不同颜色,
HSL
和HSV
中的H
都代表色相,色相是以60度的间隔排列在圆环上,分别是:360°/0°红、60°黄、120°绿、180°青、240°蓝、300°洋红,在前端处理时,会把圆环处理成长方形的色块,
- 饱和度(S): 指颜色的纯度,使用
0%~100%
来衡量,表示色相中颜色成分所占的比例,数值越大,颜色中的灰色越少,颜色越鲜艳,呈现是从灰色到色相颜色的变化。 - 亮度(L): 表现颜色的明暗程度,使用
0%~100%
的百分比来度量。反映色彩中混入黑白两色,0%------50%------100%表示黑色------色相------白色的过渡。
3、HSV模型
HSV
采用色相H(hue)
、饱和度S(saturation)
、明度V(value)
来描述色彩(比如 红色的hsv应该是hsv(0, 100%, 100%) ) 其中色相
和HSL
相同,饱和度和明度有所区别:
- HSV中的S饱和度,反映色相颜色中混入白色的值,呈现白色到色相(H)颜色的变化;
- HSL中的S饱和度,反映色相颜色中混入灰色的值,呈现的是一种从灰色到色相(H)颜色的变化。
- HSV中的V明度,体现的是从黑色到色相(H)颜色的过渡。
- HSL中的L亮度,体现的是从黑色到色相(H)颜色再到白色的过渡。
4、互相转换
在颜色选择器中,我们主要用到的是rgb
、十六进制hex
、HSV
的互相转化。
1、rgb
转hex
js
// rgb转十六进制
setRgbTo16(arr) {
let c = '#';
for (var i = 0; i < arr.length; i++) {
var t = Number(arr[i]).toString(16);
if (Number(arr[i]) < 16) {
t = '0' + t;
}
c += t;
}
return c;
}
2、hex
转rgb
js
//十六进制转rgb
set16ToRgb(str) {
let newStr = (str.toLowerCase()).replace(/\#/g, '')
let len = newStr.length;
if (len == 3) {
let t = ''
for (var i = 0; i < len; i++) {
t += newStr.slice(i, i + 1).concat(newStr.slice(i, i + 1))
}
newStr = t
}
let arr = [];
for (var i = 0; i < 6; i = i + 2) {
let s = newStr.slice(i, i + 2)
arr.push(parseInt("0x" + s))
}
return arr
}
3、rgb
转hsv
js
// rgb转hsv
rgbtohsv(arr) {
var h = 0, s = 0, v = 0;
var r = arr[0], g = arr[1], b = arr[2];
arr.sort(function (a, b) {
return a - b;
})
var max = arr[2]
var min = arr[0];
v = max / 255;
if (max === 0) {
s = 0;
} else {
s = 1 - (min / max);
}
if (max === min) {
h = 0;//事实上,max===min的时候,h无论为多少都无所谓
} else if (max === r && g >= b) {
h = 60 * ((g - b) / (max - min)) + 0;
} else if (max === r && g < b) {
h = 60 * ((g - b) / (max - min)) + 360
} else if (max === g) {
h = 60 * ((b - r) / (max - min)) + 120
} else if (max === b) {
h = 60 * ((r - g) / (max - min)) + 240
}
h = parseInt(h);
s = parseInt(s * 100);
v = parseInt(v * 100);
return [h, s, v]
}
4、hsv
转rgb
js
// hsv转rgb
hsvtorgb(h, s, v) {
s = s / 100;
v = v / 100;
var h1 = Math.floor(h / 60) % 6;
var f = h / 60 - h1;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
var r, g, b;
switch (h1) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
更多颜色------颜色选择面板区
颜色选择面板相信大家在各种编辑软件中经常使用,右侧是选择色相的滑块,左侧控制其饱和度和明度面板。
1、左侧面板
在各个编辑器中的颜色模型大都使用的HSV
模型,通过刚刚学习的颜色模型可知,饱和度S
是呈现白色到色相(H)颜色 的变化,明度V
是体现的是从黑色到色相(H)颜色 的过渡。这一部分可以使用svg
来实现,某个色值通过叠加两个渐变图层,一个是白色到色相的渐变,一个是黑色到色相的过渡。
图2为去掉黑色渐变,图3为去掉白色渐变 。可以看到:白色渐变是从左向右的(饱和度),黑色渐变是从下至上的(明度),两者重叠即为图1的效果。
html
<svg id="back_svg">
<rect x="0" y="0" width="100%" height="100%" :fill="`url(#gradient-white${pickId})`"></rect>
<rect x="0" y="0" width="100%" height="100%" :fill="`url(#gradient-black${pickId})`"></rect>
<defs>
<linearGradient :id="`gradient-black${pickId}`" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" stop-color="#000000" stop-opacity="1"></stop>
<stop offset="100%":stop-color="`rgb(${curSliderColor[0]},${curSliderColor[1]},${curSliderColor[2]})`" stop-opacity="0"></stop>
</linearGradient>
<linearGradient :id="`gradient-white${pickId}`" x1="0%" y1="100%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"></stop>
<stop offset="100%" :stop-color="`rgb(${curSliderColor[0]},${curSliderColor[1]},${curSliderColor[2]})`" stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
其中,我们在defs
中定义渐变颜色,通过url(# )
赋值到两个rect
中,<linearGradient>
标签可以用来定义渐变元素,x1/y1/x2/y2
来定义渐变的起始坐标,每个渐变的色值写在<stop>
中,其中stop-color
代表颜色,offset
表示该颜色的位置百分比。
鼠标点击位置色值
当鼠标点击某个位置时,可以获取到鼠标位置X
和Y
,因此,此时颜色的HSV
中H
为右侧选中的色相值,S
是鼠标位置在面板宽度所占的百分比,即s=x/面板宽度*100
,V
是鼠标位置在面板高度中所占的百分比,即v=y/面板高度*100
,可以得到当前鼠标点击位置颜色的hsv,再转为rgb格式即可。
html
<div class="colorBack" @mousedown="colorBarDown" @mousemove="colorBarMove" @mouseup="colorBarUp" @mouseleave="colorBarUp" :style="`background:rgb(${curSliderColor[0]},${curSliderColor[1]},${curSliderColor[2]})`">
...//上方svg面板
<div class="colorBar colorBarTarget" :class="`colorBarTarget_${pickId}`" :style="`top:${colorBarTop}px;left:${colorBarLeft}px`">
<div class="colorBarTarget" :class="`colorBarTarget_${pickId}`"></div>
</div>//鼠标滑块
</div>
js
//计算当前坐标点的hsv并转化为rgb格式
setColor(x, y) {
this.colorBarTop = y - 4;//由于定位原因,因此获取到的坐标需要减去外间距
this.colorBarLeft = x - 4;
this.Sval = x / 185 * 100;//计算s的值
this.Vval = (1 - y / 150) * 100;//计算v的值
this.curColor = this.hsvtorgb(this.Hval, this.Sval, this.Vval)//h是右侧滑块选中的色相
this.colorInput = this.setRgbTo16(this.curColor);
},
2、右侧滑块
这里的滑块就是色相环展开,因此只需要一条渐变即可
html
<svg id="hsv_svg">
<rect x="0" y="0" width="100%" height="100%" :fill="`url(#gradient-hsv${pickId})`"></rect>
<linearGradient :id="`gradient-hsv${pickId}`" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" stop-color="#FF0000" stop-opacity="1"></stop>
<stop offset="13%" stop-color="#FF00FF" stop-opacity="1"></stop>
<stop offset="25%" stop-color="#8000FF" stop-opacity="1"></stop>
<stop offset="38%" stop-color="#0040FF" stop-opacity="1"></stop>
<stop offset="50%" stop-color="#00FFFF" stop-opacity="1"></stop>
<stop offset="63%" stop-color="#00FF40" stop-opacity="1"></stop>
<stop offset="75%" stop-color="#0BED00" stop-opacity="1"></stop>
<stop offset="88%" stop-color="#FFFF00" stop-opacity="1"></stop>
<stop offset="100%" stop-color="#FF0000" stop-opacity="1"></stop>
</linearGradient>
</svg>
色相滑块
由上方颜色模型可知,色相条即是将色相环变为长方形,起始位置和结束位置都是红色,获取滑块选中位置的hsv
,依旧可以看成是鼠标点击位置的色值,此时饱和度S
和明度V
都为100,只需要考虑色相H
的值,h=鼠标Y/色相条高度*360
html
<div class="colorSilder" ref="slider" @mousedown="silderBarDown" @mousemove="silderBarMove" @mouseup="sliderBarUp" @mouseleave="sliderBarUp">
...//svg渐变
<div class="silderBar" :class="`silderBar_${pickId}`" :style="`top:${siderBarTop}px`"></div>//鼠标滑块
</div>
js
setSlilderColor(y) {
this.siderBarTop = y - 3;
this.offsetY = y / 150;
this.Hval = 360 * this.offsetY;//计算h的值
this.curColor = this.hsvtorgb(this.Hval, this.Sval, this.Vval)//s和v都是100
this.curSliderColor = this.curColor;
this.colorInput = this.setRgbTo16(this.curColor);
},
综上,我们可以取到所选颜色的hsv
值,并通过互转方法转化为rgb
或16进制
值,用于前端展示和输入框回显。
颜色回显
在输入框中输入的色值需要同步回显至面板中,只需要将获取到的十六进制色值转为hsv
,再反向计算出滑块位置即可
html
<el-input class v-model="colorInput" @input="handleInputChange"></el-input>
js
// input修改时回显色盘
handleInputChange(value){
var reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/
if (reg.test(value)) {
this.curColor = this.set16ToRgb(value);
this.colorInputHsv = this.rgbtohsv(this.curColor)
this.curSliderColor= this.curColor;
this.Hval = this.colorInputHsv[0];
this.Sval = this.colorInputHsv[1];
this.Vval = this.colorInputHsv[2];
this.siderBarTop=(this.Hval*15)/36-3;
this.colorBarLeft=(185*this.Sval)/100-4;
this.colorBarTop=(1-(this.Vval/100))*150-4;
}
},
封装组件
最后,我们将其封装为组件(以下代码以Vue为例)
html
<div class="colorPicker">
<el-popover placement="bottom" popperClass="colorPopper" :ref="`popoverRef_${pickId}`" width="240" trigger="click"
@show="popoverShow">
<div class="color_content">
<span class="color_title">最近使用颜色</span>
<ul class="recentCo_ul">
<li class="recentCo_li recentCo_first" title="清除颜色" @click="handleClearColor"></li>
<li class="recentCo_li cursor" v-for="(item, index) in recentColorList" :key="index"
:style="`background:${item}`" :data-color="`${item}`" :title="`${item}`" @click="handleCheckColor">
</li>
</ul>
<ul class="color_tab">
<li class="colorTab_li" :class="activeTab == index ? '-activeTab' : ''"
@click="handleActiveTabChange(index)" v-for="(item, index) in colorTabList" :key="index">{{ item
}}</li>
</ul>
<table v-show="activeTab == 0" class="edui-box ue_colortable edui-default colorTable"
style="border-collapse: collapse;" cellspacing="0" cellpadding="0">
<tbody class="edui-default">
<tr class="edui-default"
:class="{ 'edui-colorpicker-tablefirstrow': index == 0 || index == colorList.length - 1 }"
v-for="(item, index) in colorList" :key="index">
<td class="edui-default pr-4" v-for="(itemIn, indexIn) in item" :key="indexIn">
<a hidefocus="" :title="itemIn" onclick="return false;" href="javascript:" unselectable="on"
class="edui-box edui-colorpicker-colorcell edui-default"
:class="index == 0 || index == colorList.length - 1 || index == colorList.length - 2 ? 'isFirst' : 'noFirst'"
:data-color="`${itemIn}`" :style="`background:${itemIn};`" @click="handleCheckColor">
</a>
</td>
</tr>
<tr></tr>
</tbody>
</table>
<div class="picker_svg" v-show="activeTab == 1">
<div class="colorBack" @mousedown="colorBarDown" @mousemove="colorBarMove" @mouseup="colorBarUp"
@mouseleave="colorBarUp"
:style="`background:rgb(${curSliderColor[0]},${curSliderColor[1]},${curSliderColor[2]})`">
<svg id="back_svg">
<rect x="0" y="0" width="100%" height="100%" :fill="`url(#gradient-white${pickId})`"></rect>
<rect x="0" y="0" width="100%" height="100%" :fill="`url(#gradient-black${pickId})`"></rect>
<defs>
<linearGradient :id="`gradient-black${pickId}`" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" stop-color="#000000" stop-opacity="1"></stop>
<stop offset="100%"
:stop-color="`rgb(${curSliderColor[0]},${curSliderColor[1]},${curSliderColor[2]})`"
stop-opacity="0"></stop>
</linearGradient>
<linearGradient :id="`gradient-white${pickId}`" x1="0%" y1="100%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"></stop>
<stop offset="100%"
:stop-color="`rgb(${curSliderColor[0]},${curSliderColor[1]},${curSliderColor[2]})`"
stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
<div class="colorBar colorBarTarget" :class="`colorBarTarget_${pickId}`"
:style="`top:${colorBarTop}px;left:${colorBarLeft}px`">
<div class="colorBarTarget" :class="`colorBarTarget_${pickId}`"></div>
</div>
</div>
<div class="colorSilder" ref="slider" @mousedown="silderBarDown" @mousemove="silderBarMove"
@mouseup="sliderBarUp" @mouseleave="sliderBarUp">
<svg id="hsv_svg">
<rect x="0" y="0" width="100%" height="100%" :fill="`url(#gradient-hsv${pickId})`"></rect>
<linearGradient :id="`gradient-hsv${pickId}`" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" stop-color="#FF0000" stop-opacity="1"></stop>
<stop offset="13%" stop-color="#FF00FF" stop-opacity="1"></stop>
<stop offset="25%" stop-color="#8000FF" stop-opacity="1"></stop>
<stop offset="38%" stop-color="#0040FF" stop-opacity="1"></stop>
<stop offset="50%" stop-color="#00FFFF" stop-opacity="1"></stop>
<stop offset="63%" stop-color="#00FF40" stop-opacity="1"></stop>
<stop offset="75%" stop-color="#0BED00" stop-opacity="1"></stop>
<stop offset="88%" stop-color="#FFFF00" stop-opacity="1"></stop>
<stop offset="100%" stop-color="#FF0000" stop-opacity="1"></stop>
</linearGradient>
</svg>
<div class="silderBar" :class="`silderBar_${pickId}`" :style="`top:${siderBarTop}px`"></div>
</div>
</div>
<div class="colorPick_bottom">
<div class="color_div" :style="`background:${colorInput}`"></div>
<div class="color_input"><el-input class v-model="colorInput" @input="handleInputChange"></el-input></div>
<button class="color_btn" @click="handleConfirmColor">确定</button>
</div>
</div>
<div slot="reference">
<i class="iconfont iconStyle" :class="iconClass" :title="iconTitle"></i>
</div>
</el-popover>
</div>
js
var isFirst = true;
export default {
name: 'colorPicker',
data() {
return {
pickId: '',
colorTabList: ['基本颜色', '更多颜色'],
activeTab: 0,
recentColorList: ['#548dd4', '#366092', '#000'],
colorList: [
['#ffffff', '#000000', '#eeece1', '#1f497d', '#4f81bd', '#c0504d', '#9bbb59', '#8064a2', '#4bacc6', '#f79646'],
['#f2f2f2', '#7f7f7f', '#ddd9c3', '#c6d9f0', '#dbe5f1', '#f2dcdb', '#ebf1dd', '#e5e0ec', '#dbeef3', '#fdeada'],
['#d8d8d8', '#595959', '#c4bd97', '#8db3e2', '#b8cce4', '#e5b9b7', '#d7e3bc', '#ccc1d9', '#b7dde8', '#fbd5b5'],
['#bfbfbf', '#3f3f3f', '#938953', '#548dd4', '#95b3d7', '#d99694', '#c3d69b', '#b2a2c7', '#92cddc', '#fac08f'],
['#a5a5a5', '#262626', '#494429', '#17365d', '#366092', '#953734', '#76923c', '#5f497a', '#31859b', '#e36c09'],
['#7f7f7f', '#0c0c0c', '#1d1b10', '#0f243e', '#244061', '#632423', '#4f6128', '#3f3151', '#205867', '#974806'],
['#c00000', '#ff0000', '#ffc000', '#ffff00', '#92d050', '#00b050', '#00b0f0', '#0070c0', '#002060', '#7030a0'],
],
colorInput: '#555',
colorInputRgb: [85, 85, 85],
colorInputHsv: [],
colorBgState: false,
colorBarTop: 0,
colorBarLeft: 0,
sliderState: false,
startY: 0,
offsetY: 0,
Hval: 0,
Sval: 100,
Vval: 100,
siderBarTop: 0,
curColor: [255, 0, 0],
curSliderColor: [255, 0, 0],
}
},
methods: {
popoverShow() {
this.recentColorList = localStorage.getItem('recentColor').split(',');
},
handleActiveTabChange(index) {
this.activeTab = index;
},
debounce(fn, wait = 200) {
let timer = null;
return function (...args) {
if (isFirst) {
fn.apply(this, args)
isFirst = false
} else {
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(function () {
fn.apply(this, args)
}, wait)
}
}
},
// slider 事件
silderBarDown(e) {
this.sliderState = true;
this.Sval = 100;
this.Vval = 100;
if (e.target != $(`.silderBar_${this.pickId}`)[0]) {
this.setSlilderColor(e.offsetY)
}
},
silderBarMove(e) {
if (!this.sliderState) return;
this.debounce(() => {
if (e.target != $(`.silderBar_${this.pickId}`)[0]) {
this.setSlilderColor(e.offsetY)
}
}, 200)()
},
sliderBarUp() {
this.sliderState = false;
isFirst = true;
},
setSlilderColor(y) {
this.siderBarTop = y - 3;
this.offsetY = y / 150;
this.Hval = 360 * this.offsetY;
this.curColor = this.hsvtorgb(this.Hval, this.Sval, this.Vval)
this.curSliderColor = this.curColor;
this.colorInput = this.setRgbTo16(this.curColor);
},
colorBarDown(e) {
this.colorBgState = true;
if (e.target != $(`.colorBarTarget_${this.pickId}`)[0] && e.target != $(`.colorBarTarget_${this.pickId}`)[1]) {
this.setColor(e.offsetX, e.offsetY)
}
},
colorBarMove(e) {
if (!this.colorBgState) return;
this.debounce(() => {
if (e.target != $(`.colorBarTarget_${this.pickId}`)[0] && e.target != $(`.colorBarTarget_${this.pickId}`)[1]) {
this.setColor(e.offsetX, e.offsetY)
}
}, 200)()
},
colorBarUp() {
this.colorBgState = false;
isFirst = true;
},
setColor(x, y) {
this.colorBarTop = y - 4;
this.colorBarLeft = x - 4;
this.Sval = x / 185 * 100;
this.Vval = (1 - y / 150) * 100;
this.curColor = this.hsvtorgb(this.Hval, this.Sval, this.Vval)
this.colorInput = this.setRgbTo16(this.curColor);
},
// 清空color
handleClearColor() {
this.$emit('changeColor', '');
this.$refs[`popoverRef_${this.pickId}`].doClose();
},
// 选择color
handleCheckColor(e) {
let color = e.currentTarget.dataset.color
this.handleSubmitColor(color)
},
handleConfirmColor() {
var reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/
if (reg.test(this.colorInput)) {
this.handleSubmitColor(this.colorInput)
}
},
// 修改颜色
handleSubmitColor(val) {
this.recentColorList.unshift(val);
this.recentColorList = Array.from(new Set(this.recentColorList));
if (this.recentColorList.length > 8) {
this.recentColorList = this.recentColorList.slice(0, 8)
}
localStorage.setItem('recentColor', this.recentColorList)
this.$emit('changeColor', val);
this.$refs[`popoverRef_${this.pickId}`].doClose();
},
// input修改时回显色盘
handleInputChange(value){
console.log(value)
var reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/
if (reg.test(value)) {
this.curColor = this.set16ToRgb(value);
this.colorInputHsv = this.rgbtohsv(this.curColor)
this.curSliderColor= this.curColor;
this.Hval = this.colorInputHsv[0];
this.Sval = this.colorInputHsv[1];
this.Vval = this.colorInputHsv[2];
this.siderBarTop=(this.Hval*15)/36-3;
this.colorBarLeft=(185*this.Sval)/100-4;
this.colorBarTop=(1-(this.Vval/100))*150-4;
}
},
// hsv转rgb
hsvtorgb(h, s, v) {
s = s / 100;
v = v / 100;
var h1 = Math.floor(h / 60) % 6;
var f = h / 60 - h1;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
var r, g, b;
switch (h1) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
},
// rgb转hsv
rgbtohsv(arr) {
var h = 0, s = 0, v = 0;
var r = arr[0], g = arr[1], b = arr[2];
arr.sort(function (a, b) {
return a - b;
})
var max = arr[2]
var min = arr[0];
v = max / 255;
if (max === 0) {
s = 0;
} else {
s = 1 - (min / max);
}
if (max === min) {
h = 0;//事实上,max===min的时候,h无论为多少都无所谓
} else if (max === r && g >= b) {
h = 60 * ((g - b) / (max - min)) + 0;
} else if (max === r && g < b) {
h = 60 * ((g - b) / (max - min)) + 360
} else if (max === g) {
h = 60 * ((b - r) / (max - min)) + 120
} else if (max === b) {
h = 60 * ((r - g) / (max - min)) + 240
}
h = parseInt(h);
s = parseInt(s * 100);
v = parseInt(v * 100);
return [h, s, v]
},
//十六进制转rgb
set16ToRgb(str) {
// var reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/
// if (!reg.test(str)) { return; }
let newStr = (str.toLowerCase()).replace(/\#/g, '')
let len = newStr.length;
if (len == 3) {
let t = ''
for (var i = 0; i < len; i++) {
t += newStr.slice(i, i + 1).concat(newStr.slice(i, i + 1))
}
newStr = t
}
let arr = [];
for (var i = 0; i < 6; i = i + 2) {
let s = newStr.slice(i, i + 2)
arr.push(parseInt("0x" + s))
}
return arr
},
// rgb转十六进制
setRgbTo16(arr) {
let c = '#';
for (var i = 0; i < arr.length; i++) {
var t = Number(arr[i]).toString(16);
if (Number(arr[i]) < 16) {
t = '0' + t;
}
c += t;
}
return c;
},
},
computed: {},
created() {
this.pickId = Math.random().toString(36).slice(-10);
},
watch: {},
mounted() {
},
props: {
iconClass: {
type: String,
default: 'iconzitiyanse'
},
iconTitle:{
type:String,
default:'颜色'
}
},
}
css