111
jihongshun
8 天以前 0c741cdda7ef9935a20d3090dfea97e1ce8ae754
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>