فهرست منبع

取色器bug fix

pipipi-pikachu 5 سال پیش
والد
کامیت
071c2b30fb

+ 3 - 3
src/components/ColorPicker/Alpha.vue

@@ -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,

+ 4 - 4
src/components/ColorPicker/EditableInput.vue

@@ -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 {

+ 15 - 9
src/components/ColorPicker/Hue.vue

@@ -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)
+        })
       }
     }
 

+ 13 - 7
src/components/ColorPicker/Saturation.vue

@@ -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)
+      })
     }
 
     

+ 24 - 6
src/components/ColorPicker/index.vue

@@ -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,
     }
   },