/
sv-panel.vue
125 lines (111 loc) 路 2.62 KB
/
sv-panel.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<template>
<div
class="el-color-svpanel"
:style="{
backgroundColor: background,
}"
>
<div class="el-color-svpanel__white" />
<div class="el-color-svpanel__black" />
<div
class="el-color-svpanel__cursor"
:style="{
top: cursorTop + 'px',
left: cursorLeft + 'px',
}"
>
<div />
</div>
</div>
</template>
<script lang="ts">
// @ts-nocheck
import {
computed,
defineComponent,
getCurrentInstance,
onMounted,
ref,
watch,
} from 'vue'
import { getClientXY } from '@element-plus/utils'
import draggable from '../draggable'
import type { PropType } from 'vue'
import type Color from '../color'
export default defineComponent({
name: 'ElSlPanel',
props: {
color: {
type: Object as PropType<Color>,
required: true,
},
},
setup(props) {
// instance
const instance = getCurrentInstance()
// data
const cursorTop = ref(0)
const cursorLeft = ref(0)
const background = ref('hsl(0, 100%, 50%)')
const colorValue = computed(() => {
const hue = props.color.get('hue')
const value = props.color.get('value')
return { hue, value }
})
// methods
function update() {
const saturation = props.color.get('saturation')
const value = props.color.get('value')
const el = instance.vnode.el
const { clientWidth: width, clientHeight: height } = el
cursorLeft.value = (saturation * width) / 100
cursorTop.value = ((100 - value) * height) / 100
background.value = `hsl(${props.color.get('hue')}, 100%, 50%)`
}
function handleDrag(event) {
const el = instance.vnode.el
const rect = el.getBoundingClientRect()
const { clientX, clientY } = getClientXY(event)
let left = clientX - rect.left
let top = clientY - rect.top
left = Math.max(0, left)
left = Math.min(left, rect.width)
top = Math.max(0, top)
top = Math.min(top, rect.height)
cursorLeft.value = left
cursorTop.value = top
props.color.set({
saturation: (left / rect.width) * 100,
value: 100 - (top / rect.height) * 100,
})
}
// watch
watch(
() => colorValue.value,
() => {
update()
}
)
// mounted
onMounted(() => {
draggable(instance.vnode.el as HTMLElement, {
drag: (event) => {
handleDrag(event)
},
end: (event) => {
handleDrag(event)
},
})
update()
})
return {
cursorTop,
cursorLeft,
background,
colorValue,
handleDrag,
update,
}
},
})
</script>