完成取色器的重构
parent
eca1a50619
commit
d111e67efc
|
@ -12,7 +12,6 @@ import {
|
||||||
Component,
|
Component,
|
||||||
outsideClick,
|
outsideClick,
|
||||||
clearOutsideClick,
|
clearOutsideClick,
|
||||||
nextTick,
|
|
||||||
offset,
|
offset,
|
||||||
styleMap
|
styleMap
|
||||||
} from 'wkit'
|
} from 'wkit'
|
||||||
|
@ -23,19 +22,19 @@ const ROOT = document.documentElement
|
||||||
|
|
||||||
// H: 色相, S: 饱和度, B/V: 亮度
|
// H: 色相, S: 饱和度, B/V: 亮度
|
||||||
export function hsb2rgb(hsb) {
|
export function hsb2rgb(hsb) {
|
||||||
var h = hsb.h
|
let h = hsb.h
|
||||||
var s = Math.round((hsb.s * 255) / 100)
|
let s = Math.round((hsb.s * 255) / 100)
|
||||||
var v = Math.round((hsb.b * 255) / 100)
|
let v = Math.round((hsb.b * 255) / 100)
|
||||||
var r = 0
|
let r = 0
|
||||||
var g = 0
|
let g = 0
|
||||||
var b = 0
|
let b = 0
|
||||||
|
|
||||||
if (s === 0) {
|
if (s === 0) {
|
||||||
r = g = b = v
|
r = g = b = v
|
||||||
} else {
|
} else {
|
||||||
var t1 = v
|
let t1 = v
|
||||||
var t2 = ((255 - s) * v) / 255
|
let t2 = ((255 - s) * v) / 255
|
||||||
var t3 = ((t1 - t2) * (h % 60)) / 60
|
let t3 = ((t1 - t2) * (h % 60)) / 60
|
||||||
|
|
||||||
//
|
//
|
||||||
if (h === 360) {
|
if (h === 360) {
|
||||||
|
@ -75,33 +74,51 @@ export function hsb2rgb(hsb) {
|
||||||
return { r, g, b }
|
return { r, g, b }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rgb2hex({ r, g, b }) {
|
export function rgb2hex({ r, g, b }, a) {
|
||||||
return [r, g, b].map(it => it.toString(16).padStart(2, '0')).join('')
|
let hex = [r, g, b].map(it => it.toString(16).padStart(2, '0')).join('')
|
||||||
|
if (a !== void 0) {
|
||||||
|
hex += (~~((a / 100) * 255)).toString(16)
|
||||||
|
}
|
||||||
|
return hex
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hex2rgb(hex) {
|
export function hex2rgb(hex) {
|
||||||
var r, g, b
|
let r, g, b, a
|
||||||
|
|
||||||
hex = hex.replace(/^#/, '').split('')
|
hex = hex.replace(/^#/, '')
|
||||||
|
|
||||||
if (hex.length === 3) {
|
switch (hex.length) {
|
||||||
r = parseInt(hex[0] + hex[0], 16)
|
case 3:
|
||||||
g = parseInt(hex[1] + hex[1], 16)
|
case 4:
|
||||||
b = parseInt(hex[2] + hex[2], 16)
|
r = hex[0].repeat(2)
|
||||||
} else {
|
g = hex[1].repeat(2)
|
||||||
r = parseInt(hex[0] + hex[1], 16)
|
b = hex[2].repeat(2)
|
||||||
g = parseInt(hex[2] + hex[3], 16)
|
a = (hex[3] || 'f').repeat(2)
|
||||||
b = parseInt(hex[4] + hex[5], 16)
|
|
||||||
|
break
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
case 8:
|
||||||
|
r = hex.slice(0, 2)
|
||||||
|
g = hex.slice(2, 4)
|
||||||
|
b = hex.slice(4, 6)
|
||||||
|
a = hex.slice(6, 8) || 'ff'
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return { r, g, b }
|
r = parseInt(r, 16)
|
||||||
|
g = parseInt(g, 16)
|
||||||
|
b = parseInt(b, 16)
|
||||||
|
a = ~~((parseInt(a, 16) * 100) / 255)
|
||||||
|
|
||||||
|
return { r, g, b, a }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rgb2hsb({ r, g, b }) {
|
export function rgb2hsb({ r, g, b }) {
|
||||||
var hsb = { h: 0, s: 0, b: 0 }
|
let hsb = { h: 0, s: 0, b: 0 }
|
||||||
var max = Math.max(r, g, b)
|
let max = Math.max(r, g, b)
|
||||||
var min = Math.min(r, g, b)
|
let min = Math.min(r, g, b)
|
||||||
var delta = max - min
|
let delta = max - min
|
||||||
|
|
||||||
hsb.b = max
|
hsb.b = max
|
||||||
hsb.s = max === 0 ? 0 : (delta * 255) / max
|
hsb.s = max === 0 ? 0 : (delta * 255) / max
|
||||||
|
@ -139,9 +156,7 @@ class Color extends Component {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
observer(val) {
|
observer(val) {
|
||||||
if (this.#show) {
|
this.#calc(val)
|
||||||
this.#calc(val)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
disabled: false
|
disabled: false
|
||||||
|
@ -154,8 +169,8 @@ class Color extends Component {
|
||||||
}
|
}
|
||||||
.container {
|
.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 32px;
|
width: var(--wc-color-size, 32px);
|
||||||
height: 32px;
|
height: var(--wc-color-size, 32px);
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +230,7 @@ class Color extends Component {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 38px;
|
top: var(--wc-color-size, 32px);
|
||||||
width: 310px;
|
width: 310px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background: var(--color-plain-1);
|
background: var(--color-plain-1);
|
||||||
|
@ -378,7 +393,17 @@ class Color extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
css`
|
||||||
|
:host([size='small']) {
|
||||||
|
.container {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
.color-panel {
|
||||||
|
top: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
css`
|
css`
|
||||||
:host([disabled]) {
|
:host([disabled]) {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
|
@ -402,41 +427,38 @@ class Color extends Component {
|
||||||
#y = 0 // 场景触点的Y坐标
|
#y = 0 // 场景触点的Y坐标
|
||||||
#ht = 0 // 颜色池的触点坐标
|
#ht = 0 // 颜色池的触点坐标
|
||||||
#at = 100 // 透明度条的触点坐标
|
#at = 100 // 透明度条的触点坐标
|
||||||
#sceneBg = '#ff0000'
|
#sceneBg = '#000000'
|
||||||
#alphaBg = '#ff0000'
|
#alphaBg = '#000000'
|
||||||
|
|
||||||
#cache = {
|
#rgba = { r: 0, g: 0, b: 0, a: 100 }
|
||||||
hsb: { h: 0, s: 100, b: 100 },
|
#hsb = { h: 0, s: 100, b: 100 }
|
||||||
rgba: { r: 255, g: 0, b: 0, a: 100 }
|
|
||||||
}
|
|
||||||
|
|
||||||
#calc(val) {
|
#calc(val) {
|
||||||
var isHex
|
let isHex
|
||||||
var rgb
|
|
||||||
|
|
||||||
val = val.toLowerCase()
|
val = val.toLowerCase()
|
||||||
|
|
||||||
if (!val) {
|
if (!val || val === this.#value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isHex = /^#[0-9a-f]{3,6}$/.test(val)
|
isHex = /^#[0-9a-f]{3,8}$/.test(val)
|
||||||
|
|
||||||
if (isHex) {
|
if (isHex) {
|
||||||
Object.assign(this.#cache.rgba, hex2rgb(val), { a: 100 })
|
Object.assign(this.#rgba, hex2rgb(val))
|
||||||
} else {
|
} else {
|
||||||
var res = val.match(/rgba?\((\d+),\s*?(\d+),\s*?(\d+)[,\s]*?([\d\.]+)?\)/)
|
let res = val.match(/rgba?\((\d+),\s*?(\d+),\s*?(\d+)[,\s]*?([\d\.]+)?\)/)
|
||||||
if (res) {
|
if (res) {
|
||||||
this.#cache.rgba = { r: +res[1], g: +res[2], b: +res[3], a: 100 }
|
this.#rgba = { r: +res[1], g: +res[2], b: +res[3], a: 100 }
|
||||||
if (res[4] !== undefined) {
|
if (res[4] !== undefined) {
|
||||||
this.#cache.rgba.a = ~~(res[4] * 100)
|
this.#rgba.a = ~~(res[4] * 100)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#cache.hsb = rgb2hsb(this.#cache.rgba)
|
this.#hsb = rgb2hsb(this.#rgba)
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleColorPanel() {
|
toggleColorPanel() {
|
||||||
|
@ -449,35 +471,31 @@ class Color extends Component {
|
||||||
|
|
||||||
// 透明度变化
|
// 透明度变化
|
||||||
#changeAlpha(ev) {
|
#changeAlpha(ev) {
|
||||||
let a = +ev.target.value
|
this.#rgba.a = +ev.target.value
|
||||||
let { r, g, b } = this.#cache.rgba
|
|
||||||
|
|
||||||
this.#cache.rgba.a = a
|
|
||||||
this.#updateView()
|
this.#updateView()
|
||||||
}
|
}
|
||||||
// 色彩池变化
|
// 色彩池变化
|
||||||
#changeHue(h) {
|
#changeHue(h) {
|
||||||
h = h < 0 ? 0 : h > 360 ? 360 : h
|
h = h < 0 ? 0 : h > 360 ? 360 : h
|
||||||
let { s, b } = this.#cache.hsb
|
let { s, b } = this.#hsb
|
||||||
let rgba = this.#cache.rgba
|
let rgba = this.#rgba
|
||||||
let hsb = { h, s, b }
|
let hsb = { h, s, b }
|
||||||
|
|
||||||
Object.assign(rgba, hsb2rgb(hsb))
|
Object.assign(rgba, hsb2rgb(hsb))
|
||||||
|
|
||||||
this.#cache.hsb = hsb
|
this.#hsb = hsb
|
||||||
this.#cache.rgba = rgba
|
this.#rgba = rgba
|
||||||
|
|
||||||
this.#updateView()
|
this.#updateView()
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
#changeColor(x, y) {
|
#changeColor(x, y) {
|
||||||
let { hsb, rgba } = this.#cache
|
let hsb = this.#hsb
|
||||||
|
let rgba = this.#rgba
|
||||||
hsb.s = ~~((100 * x) / 280)
|
hsb.s = ~~((100 * x) / 280)
|
||||||
hsb.b = ~~((100 * (180 - y)) / 180)
|
hsb.b = ~~((100 * (180 - y)) / 180)
|
||||||
Object.assign(rgba, hsb2rgb(hsb))
|
Object.assign(rgba, hsb2rgb(hsb))
|
||||||
|
|
||||||
this.#cache.hsb = hsb
|
|
||||||
this.#cache.rgba = rgba
|
|
||||||
this.#updateView()
|
this.#updateView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +538,7 @@ class Color extends Component {
|
||||||
bind(DOC, 'mouseup', _ => unbind(DOC, 'mousemove', callback), EV_OPTION)
|
bind(DOC, 'mouseup', _ => unbind(DOC, 'mousemove', callback), EV_OPTION)
|
||||||
}
|
}
|
||||||
|
|
||||||
#close(clear) {
|
#close() {
|
||||||
if (this.#show) {
|
if (this.#show) {
|
||||||
this.#show = false
|
this.#show = false
|
||||||
this.#calc(this.value)
|
this.#calc(this.value)
|
||||||
|
@ -531,13 +549,15 @@ class Color extends Component {
|
||||||
#submit() {
|
#submit() {
|
||||||
this.value = this.#value
|
this.value = this.#value
|
||||||
this.#close()
|
this.#close()
|
||||||
this.$emit('change', { data: this.#value })
|
this.$emit('input')
|
||||||
|
this.$emit('change')
|
||||||
}
|
}
|
||||||
|
|
||||||
#updateView() {
|
#updateView() {
|
||||||
var { hsb, rgba } = this.#cache
|
let hsb = this.#hsb
|
||||||
var sceneBg, color, alphaBg
|
let rgba = this.#rgba
|
||||||
var x, y
|
let sceneBg, color, alphaBg
|
||||||
|
let x, y
|
||||||
|
|
||||||
x = Math.ceil((hsb.s * 280) / 100)
|
x = Math.ceil((hsb.s * 280) / 100)
|
||||||
y = 180 - Math.ceil((hsb.b * 180) / 100)
|
y = 180 - Math.ceil((hsb.b * 180) / 100)
|
||||||
|
@ -618,7 +638,7 @@ class Color extends Component {
|
||||||
|
|
||||||
<section class="input-box">
|
<section class="input-box">
|
||||||
<input class="input focus" :value=${this.#value} maxlength="25" />
|
<input class="input focus" :value=${this.#value} maxlength="25" />
|
||||||
<a class="clear" @click=${_ => this.#close(true)}>清除</a>
|
<a class="clear" @click=${this.#close}>取消</a>
|
||||||
<a tabindex="0" class="submit focus" @click=${this.#submit}>确定</a>
|
<a tabindex="0" class="submit focus" @click=${this.#submit}>确定</a>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue