Skip to content

Commit e7893a6

Browse files
committed
update ColorPicker
1 parent dab3947 commit e7893a6

File tree

12 files changed

+994
-26
lines changed

12 files changed

+994
-26
lines changed

.eslintignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
src/directives
1+
src/directives
2+
src/utils/throttle.js

LICENSE

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,26 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
151151
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152152
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
153153
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
154-
THE SOFTWARE.
154+
THE SOFTWARE.
155+
156+
The MIT License (MIT)
157+
158+
Copyright (c) 2015 greyby
159+
160+
Permission is hereby granted, free of charge, to any person obtaining a copy
161+
of this software and associated documentation files (the "Software"), to deal
162+
in the Software without restriction, including without limitation the rights
163+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
164+
copies of the Software, and to permit persons to whom the Software is
165+
furnished to do so, subject to the following conditions:
166+
167+
The above copyright notice and this permission notice shall be included in all
168+
copies or substantial portions of the Software.
169+
170+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
172+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
173+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
174+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
175+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
176+
SOFTWARE.

examples/routers/color-picker.vue

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<template>
22
<div style="margin: 100px;">
3+
{{ color.rgba }}
34
<!--<Input placeholder="请输入..." size="large" style="width: 50px;"></Input>-->
45
<!--<color-picker placement="bottom-start" size="large"></color-picker>-->
56
<!--<Date-picker type="date" placeholder="选择日期" size="large" style="width: 200px"></Date-picker>-->
6-
<color-picker recommend alpha placement="bottom" size="default"></color-picker>
7+
<color-picker v-model="color" alpha :recommend="true" placement="bottom" size="default"></color-picker>
8+
<color-picker v-model="color" :alpha="false" :recommend="false" placement="bottom" size="default"></color-picker>
79
<!--<Date-picker type="date" placeholder="选择日期" style="width: 200px"></Date-picker>-->
810
<!--<color-picker placement="bottom-start" size="small"></color-picker>-->
911
<!--<Date-picker type="date" placeholder="选择日期" size="small" style="width: 200px"></Date-picker>-->
@@ -13,7 +15,30 @@
1315
export default {
1416
props: {},
1517
data () {
16-
return {};
18+
return {
19+
color: {
20+
hex: '#194d33',
21+
hsl: {
22+
h: 150,
23+
s: 0.5,
24+
l: 0.2,
25+
a: 1
26+
},
27+
hsv: {
28+
h: 150,
29+
s: 0.66,
30+
v: 0.30,
31+
a: 1
32+
},
33+
rgba: {
34+
r: 25,
35+
g: 77,
36+
b: 51,
37+
a: 1
38+
},
39+
a: 1
40+
}
41+
};
1742
},
1843
computed: {},
1944
methods: {}

package-lock.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
"async-validator": "^1.7.1",
4444
"core-js": "^2.4.1",
4545
"deepmerge": "^1.5.0",
46-
"popper.js": "^0.6.4"
46+
"popper.js": "^0.6.4",
47+
"tinycolor2": "^1.4.1"
4748
},
4849
"peerDependencies": {
4950
"vue": "^2.4.1"

src/components/color-picker/alpha.vue

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<template>
2+
<div class="ivu-color-picker-alpha">
3+
<div class="ivu-color-picker-alpha-checkboard-wrap">
4+
<div class="ivu-color-picker-alpha-checkerboard"></div>
5+
</div>
6+
<div class="ivu-color-picker-alpha-gradient" :style="{background: gradientColor}"></div>
7+
<div class="ivu-color-picker-alpha-container" ref="container"
8+
@mousedown="handleMouseDown"
9+
@touchmove="handleChange"
10+
@touchstart="handleChange">
11+
<div class="ivu-color-picker-alpha-pointer" :style="{left: colors.a * 100 + '%'}">
12+
<div class="ivu-color-picker-alpha-picker"></div>
13+
</div>
14+
</div>
15+
</div>
16+
</template>
17+
<script>
18+
export default {
19+
name: 'Alpha',
20+
props: {
21+
value: Object,
22+
onChange: Function
23+
},
24+
computed: {
25+
colors () {
26+
return this.value;
27+
},
28+
gradientColor () {
29+
const rgba = this.colors.rgba;
30+
const rgbStr = [rgba.r, rgba.g, rgba.b].join(',');
31+
return 'linear-gradient(to right, rgba(' + rgbStr + ', 0) 0%, rgba(' + rgbStr + ', 1) 100%)';
32+
}
33+
},
34+
methods: {
35+
handleChange (e, skip) {
36+
!skip && e.preventDefault();
37+
const container = this.$refs.container;
38+
const containerWidth = container.clientWidth;
39+
40+
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
41+
const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0);
42+
const left = pageX - xOffset;
43+
44+
let a;
45+
if (left < 0) {
46+
a = 0;
47+
} else if (left > containerWidth) {
48+
a = 1;
49+
} else {
50+
a = Math.round(left * 100 / containerWidth) / 100;
51+
}
52+
53+
if (this.colors.a !== a) {
54+
this.$emit('change', {
55+
h: this.colors.hsl.h,
56+
s: this.colors.hsl.s,
57+
l: this.colors.hsl.l,
58+
a: a,
59+
source: 'rgba'
60+
});
61+
}
62+
},
63+
handleMouseDown (e) {
64+
this.handleChange(e, true);
65+
window.addEventListener('mousemove', this.handleChange);
66+
window.addEventListener('mouseup', this.handleMouseUp);
67+
},
68+
handleMouseUp () {
69+
this.unbindEventListeners();
70+
},
71+
unbindEventListeners () {
72+
window.removeEventListener('mousemove', this.handleChange);
73+
window.removeEventListener('mouseup', this.handleMouseUp);
74+
}
75+
}
76+
};
77+
</script>

src/components/color-picker/color-picker.vue

Lines changed: 105 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
</div>
99
<Dropdown-menu slot="list">
1010
<div :class="[prefixCls + '-picker']">
11-
<div :class="[prefixCls + '-picker-panel']"></div>
11+
<div :class="[prefixCls + '-picker-panel']">
12+
<Saturation v-model="saturationColors" @change="childChange"></Saturation>
13+
</div>
1214
<div :class="[prefixCls + '-picker-hue-slider']">
13-
<Slider v-model="hueNumber" :min="0" :max="255"></Slider>
15+
<Hue v-model="saturationColors" @change="childChange"></Hue>
1416
</div>
1517
<div v-if="alpha" :class="[prefixCls + '-picker-alpha-slider']">
16-
<Slider v-model="alphaNumber" :min="0" :max="100"></Slider>
18+
<Alpha v-model="saturationColors" @change="childChange"></Alpha>
1719
</div>
1820
<recommend-colors v-if="colors.length" :list="colors" :class="[prefixCls + '-picker-colors']"></recommend-colors>
1921
<recommend-colors v-if="!colors.length && recommend" :list="recommendedColor" :class="[prefixCls + '-picker-colors']"></recommend-colors>
@@ -23,22 +25,76 @@
2325
</Dropdown>
2426
</template>
2527
<script>
28+
import tinycolor from 'tinycolor2';
29+
2630
import Dropdown from '../dropdown/dropdown.vue';
2731
import DropdownMenu from '../dropdown/dropdown-menu.vue';
28-
import Slider from '../slider/slider.vue';
2932
import RecommendColors from './recommend-colors.vue';
3033
import Confirm from '../date-picker/base/confirm.vue';
34+
35+
import Saturation from './saturation.vue';
36+
import Hue from './hue.vue';
37+
import Alpha from './alpha.vue';
38+
3139
import { oneOf } from '../../utils/assist';
3240
3341
const prefixCls = 'ivu-color-picker';
3442
const inputPrefixCls = 'ivu-input';
3543
44+
function _colorChange (data, oldHue) {
45+
const alpha = data && data.a;
46+
let color;
47+
48+
// hsl is better than hex between conversions
49+
if (data && data.hsl) {
50+
color = tinycolor(data.hsl);
51+
} else if (data && data.hex && data.hex.length > 0) {
52+
color = tinycolor(data.hex);
53+
} else {
54+
color = tinycolor(data);
55+
}
56+
57+
if (color && (color._a === undefined || color._a === null)) {
58+
color.setAlpha(alpha || 1);
59+
}
60+
61+
const hsl = color.toHsl();
62+
const hsv = color.toHsv();
63+
64+
if (hsl.s === 0) {
65+
hsv.h = hsl.h = data.h || (data.hsl && data.hsl.h) || oldHue || 0;
66+
}
67+
68+
// when the hsv.v is less than 0.0164 (base on test)
69+
// because of possible loss of precision
70+
// the result of hue and saturation would be miscalculated
71+
if (hsv.v < 0.0164) {
72+
hsv.h = data.h || (data.hsv && data.hsv.h) || 0;
73+
hsv.s = data.s || (data.hsv && data.hsv.s) || 0;
74+
}
75+
76+
if (hsl.l < 0.01) {
77+
hsl.h = data.h || (data.hsl && data.hsl.h) || 0;
78+
hsl.s = data.s || (data.hsl && data.hsl.s) || 0;
79+
}
80+
81+
return {
82+
hsl: hsl,
83+
hex: color.toHexString().toUpperCase(),
84+
rgba: color.toRgb(),
85+
hsv: hsv,
86+
oldHue: data.h || oldHue || hsl.h,
87+
source: data.source,
88+
a: data.a || color.getAlpha()
89+
};
90+
}
91+
3692
export default {
3793
name: 'ColorPicker',
38-
components: { Dropdown, DropdownMenu, Slider, Confirm, RecommendColors },
94+
components: { Dropdown, DropdownMenu, Confirm, RecommendColors, Saturation, Hue, Alpha },
3995
props: {
4096
value: {
41-
type: String
97+
type: Object
4298
},
4399
alpha: {
44100
type: Boolean,
@@ -81,10 +137,8 @@
81137
},
82138
data () {
83139
return {
140+
val: _colorChange(this.value),
84141
prefixCls: prefixCls,
85-
currentValue: this.value,
86-
hueNumber: 0,
87-
alphaNumber: 0,
88142
recommendedColor: [
89143
'#2d8cf0',
90144
'#19be6b',
@@ -110,6 +164,15 @@
110164
};
111165
},
112166
computed: {
167+
saturationColors: {
168+
get () {
169+
return this.val;
170+
},
171+
set (newVal) {
172+
this.val = newVal;
173+
this.$emit('input', newVal);
174+
}
175+
},
113176
wrapClasses () {
114177
return [
115178
`${prefixCls}-rel`,
@@ -129,8 +192,41 @@
129192
];
130193
}
131194
},
195+
watch: {
196+
value (newVal) {
197+
this.val = _colorChange(newVal);
198+
}
199+
},
132200
methods: {
201+
childChange (data) {
202+
this.colorChange(data);
203+
},
204+
colorChange (data, oldHue) {
205+
this.oldHue = this.saturationColors.hsl.h;
206+
this.saturationColors = _colorChange(data, oldHue || this.oldHue);
207+
},
208+
isValidHex (hex) {
209+
return tinycolor(hex).isValid();
210+
},
211+
simpleCheckForValidColor (data) {
212+
const keysToCheck = ['r', 'g', 'b', 'a', 'h', 's', 'l', 'v'];
213+
let checked = 0;
214+
let passed = 0;
133215
216+
for (let i = 0; i < keysToCheck.length; i++) {
217+
const letter = keysToCheck[i];
218+
if (data[letter]) {
219+
checked++;
220+
if (!isNaN(data[letter])) {
221+
passed++;
222+
}
223+
}
224+
}
225+
226+
if (checked === passed) {
227+
return data;
228+
}
229+
}
134230
}
135231
};
136232
</script>

src/components/color-picker/color.js

Whitespace-only changes.

0 commit comments

Comments
 (0)