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
126
127
128
| <template>
| <div class="ant-color-hue-slider">
| <div ref="bar" class="ant-color-hue-slider__bar" @click="handleClick"></div>
| <div
| ref="thumb"
| class="ant-color-hue-slider__thumb"
| :style="{ left: thumbLeft + 'px' }"
| ></div>
| </div>
| </template>
|
| <script>
| import draggable from '../lib/draggable';
|
| export default {
| name: 'HueSlider',
| props: {
| color: {
| type: Object,
| required: true,
| },
| },
| data() {
| return {
| thumbLeft: 0,
| sliderWidth: 0,
| thumbWidth: 0,
| };
| },
| computed: {
| hueValue() {
| return this.color?.get('hue');
| },
| },
| watch: {
| hueValue: {
| immediate: true,
| handler() {
| this.$nextTick(() => {
| this.update();
| });
| },
| },
| },
| methods: {
| handleClick(event) {
| if (event.target !== this.$refs.thumb) {
| this.handleDrag(event);
| }
| },
| handleDrag(event) {
| const rect = this.$el.getBoundingClientRect();
| let left = event.clientX - rect.left;
| left = Math.min(left, rect.width - this.thumbWidth / 2);
| left = Math.max(this.thumbWidth / 2, left);
|
| const hue = Math.round(
| ((left - this.thumbWidth / 2) / (rect.width - this.thumbWidth)) * 360
| );
| this.color.set('hue', hue);
| },
| getThumbLeft() {
| const sliderWidth = this.sliderWidth || this.$el.clientWidth;
| const thumbWidth = this.thumbWidth || this.$refs.thumb.offsetWidth;
| const hue = this.color.get('hue');
| return Math.round((hue * (sliderWidth - thumbWidth / 2)) / 360);
| },
| update() {
| this.thumbLeft = this.getThumbLeft();
| },
| },
| mounted() {
| const dragConfig = {
| drag: (event) => {
| this.handleDrag(event);
| },
| end: (event) => {
| this.handleDrag(event);
| },
| };
|
| draggable(this.$refs.bar, dragConfig);
| draggable(this.$refs.thumb, dragConfig);
| this.sliderWidth = this.$el.clientWidth;
| this.thumbWidth = this.$refs.thumb.offsetWidth;
| },
| };
| </script>
|
| <style scoped>
| .ant-color-hue-slider {
| box-sizing: border-box;
| position: relative;
| height: 12px;
| margin-top: 8px;
| margin-bottom: 12px;
| }
| .ant-color-hue-slider__bar {
| height: 100%;
| border-radius: 12px;
| position: relative;
| background: linear-gradient(
| to right,
| #f00 0%,
| #ff0 17%,
| #0f0 33%,
| #0ff 50%,
| #00f 67%,
| #f0f 83%,
| #f00 100%
| );
| }
| .ant-color-hue-slider__thumb {
| cursor: pointer;
| position: absolute;
| box-sizing: border-box;
| z-index: 1;
| left: 0;
| top: 50%;
| width: 18px;
| height: 18px;
| transform: translate(-9px, -50%);
| border-radius: 100%;
| background: #ffffff;
| border: 1px solid #f0f0f0;
| box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
| }
| </style>
|
|