取色器bug fix

This commit is contained in:
pipipi-pikachu 2021-01-03 13:47:52 +08:00
parent 66da683c0f
commit 071c2b30fb
5 changed files with 59 additions and 29 deletions

View File

@ -28,13 +28,13 @@ export default defineComponent({
Checkboard,
},
props: {
modelValue: {
value: {
type: Object as PropType<ColorFormats.RGBA>,
required: true,
},
},
setup(props, { emit }) {
const color = computed(() => props.modelValue)
const color = computed(() => props.value)
const gradientColor = computed(() => {
const rgbaStr = [color.value.r, color.value.g, color.value.b].join(',')
return `linear-gradient(to right, rgba(${rgbaStr}, 0) 0%, rgba(${rgbaStr}, 1) 100%)`
@ -54,7 +54,7 @@ export default defineComponent({
else a = Math.round(left * 100 / containerWidth) / 100
if(color.value.a !== a) {
emit('update:modelValue', {
emit('change', {
r: color.value.r,
g: color.value.g,
b: color.value.b,

View File

@ -15,7 +15,7 @@ import tinycolor, { ColorFormats } from 'tinycolor2'
export default defineComponent({
name: 'editable-input',
props: {
modelValue: {
value: {
type: Object as PropType<ColorFormats.RGBA>,
required: true,
},
@ -23,14 +23,14 @@ export default defineComponent({
setup(props, { emit }) {
const val = computed(() => {
let _hex = ''
if(props.modelValue.a < 1) _hex = tinycolor(props.modelValue).toHex8String().toUpperCase()
else _hex = tinycolor(props.modelValue).toHexString().toUpperCase()
if(props.value.a < 1) _hex = tinycolor(props.value).toHex8String().toUpperCase()
else _hex = tinycolor(props.value).toHexString().toUpperCase()
return _hex.replace('#', '')
})
const handleInput = (e: InputEvent) => {
const value = (e.target as HTMLInputElement).value
if(value.length >= 6) emit('update:modelValue', tinycolor(value).toRgb())
if(value.length >= 6) emit('change', tinycolor(value).toRgb())
}
return {

View File

@ -22,25 +22,33 @@ import tinycolor, { ColorFormats } from 'tinycolor2'
export default defineComponent({
name: 'hue',
props: {
modelValue: {
value: {
type: Object as PropType<ColorFormats.RGBA>,
required: true,
},
hue: {
type: Number,
required: true,
},
},
setup(props, { emit }) {
const oldHue = ref(0)
const pullDirection = ref('')
const color = computed(() => tinycolor(props.modelValue).toHsl())
const color = computed(() => {
const hsla = tinycolor(props.value).toHsl()
if(hsla.s === 0) hsla.h = props.hue
return hsla
})
const pointerLeft = computed(() => {
if(color.value.h === 0 && pullDirection.value === 'right') return '100%'
return color.value.h * 100 / 360 + '%'
})
watch(() => props.modelValue, () => {
const hsl = tinycolor(props.modelValue).toHsl()
const h = hsl.h
watch(() => props.value, () => {
const hsla = tinycolor(props.value).toHsl()
const h = hsla.s === 0 ? props.hue : hsla.h
if(h !== 0 && h - oldHue.value > 0) pullDirection.value = 'right'
if(h !== 0 && h - oldHue.value < 0) pullDirection.value = 'left'
oldHue.value = h
@ -63,14 +71,12 @@ export default defineComponent({
h = (360 * percent / 100)
}
if(color.value.h !== h) {
const rgba = tinycolor({
emit('change', {
h,
l: color.value.l,
s: color.value.s,
a: color.value.a,
}).toRgb()
emit('update:modelValue', rgba)
})
}
}

View File

@ -27,20 +27,28 @@ import clamp from 'lodash/clamp'
export default defineComponent({
name: 'saturation',
props: {
modelValue: {
value: {
type: Object as PropType<ColorFormats.RGBA>,
required: true,
},
hue: {
type: Number,
required: true,
},
},
setup(props, { emit }) {
const color = computed(() => tinycolor(props.modelValue).toHsv())
const color = computed(() => {
const hsva = tinycolor(props.value).toHsv()
if(hsva.s === 0) hsva.h = props.hue
return hsva
})
const bgColor = computed(() => `hsl(${color.value.h}, 100%, 50%)`)
const pointerTop = computed(() => (-(color.value.v * 100) + 1) + 100 + '%')
const pointerLeft = computed(() => color.value.s * 100 + '%')
const emitChangeEvent = throttle(function(param) {
emit('update:modelValue', param)
emit('change', param)
}, 20, { leading: true, trailing: false })
const saturationRef = ref<HTMLElement | null>(null)
@ -57,14 +65,12 @@ export default defineComponent({
const saturation = left / containerWidth
const bright = clamp(-(top / containerHeight) + 1, 0, 1)
const rgba = tinycolor({
emitChangeEvent({
h: color.value.h,
s: saturation,
v: bright,
a: color.value.a,
}).toRgb()
emitChangeEvent(rgba)
})
}

View File

@ -1,7 +1,7 @@
<template>
<div class="color-picker" @contextmenu.prevent>
<div class="picker-saturation-wrap">
<Saturation v-model="color" />
<Saturation :value="color" :hue="hue" @change="value => changeColor(value)" />
</div>
<div class="picker-controls">
<div class="picker-color-wrap">
@ -9,12 +9,18 @@
<Checkboard />
</div>
<div class="picker-sliders">
<div class="picker-hue-wrap"><Hue v-model="color" /></div>
<div class="picker-alpha-wrap"><Alpha v-model="color" /></div>
<div class="picker-hue-wrap">
<Hue :value="color" :hue="hue" @change="value => changeColor(value)" />
</div>
<div class="picker-alpha-wrap">
<Alpha :value="color" @change="value => changeColor(value)" />
</div>
</div>
</div>
</div>
<div class="picker-field"><EditableInput v-model="color" /></div>
<div class="picker-field">
<EditableInput :value="color" @change="value => changeColor(value)" />
</div>
<div class="picker-presets">
<div
@ -54,7 +60,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, defineComponent, ref } from 'vue'
import tinycolor, { ColorFormats } from 'tinycolor2'
import Alpha from './Alpha.vue'
@ -120,6 +126,8 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const hue = ref(0)
const color = computed({
get() {
return tinycolor(props.modelValue).toRgb()
@ -142,12 +150,22 @@ export default defineComponent({
emit('update:modelValue', colorString)
}
const changeColor = (value: ColorFormats.RGBA | ColorFormats.HSLA | ColorFormats.HSVA) => {
if('h' in value) {
hue.value = value.h
color.value = tinycolor(value).toRgb()
}
else color.value = value
}
return {
themeColors,
standardColors,
presetColors,
color,
hue,
currentColor,
changeColor,
selectPresetColor,
}
},