mirror of https://github.com/ElemeFE/element
ColorPicker: add predefine colors (#10170)
* ColorPicker: add predefine colors(#8702) * Add selected state of predefine color and test cases * Fix the bugs mentioned in reviewpull/10236/head
parent
3377cd0847
commit
441669f081
|
@ -5,7 +5,19 @@
|
|||
color1: '#409EFF',
|
||||
color2: null,
|
||||
color3: 'rgba(19, 206, 102, 0.8)',
|
||||
color4: '#409EFF'
|
||||
color4: '#409EFF',
|
||||
color5: 'hsva(180, 65, 20, 0.5)',
|
||||
predefineColors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
@ -88,6 +100,36 @@ ColorPicker is a color selector supporting multiple color formats.
|
|||
```
|
||||
:::
|
||||
|
||||
### Predefine colors
|
||||
|
||||
:::demo ColorPicker supports predefine colors
|
||||
```html
|
||||
<el-color-picker v-model="color5" show-alpha :predefine="predefineColors"></el-color-picker>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color5: 'hsva(180, 65, 20, 0.5)',
|
||||
predefineColors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
### Sizes
|
||||
|
||||
:::demo
|
||||
|
@ -117,6 +159,7 @@ ColorPicker is a color selector supporting multiple color formats.
|
|||
| show-alpha | whether to display the alpha slider | boolean | — | false |
|
||||
| color-format | color format of v-model | string | hsl / hsv / hex / rgb | hex (when show-alpha is false)/ rgb (when show-alpha is true) |
|
||||
| popper-class | custom class name for ColorPicker's dropdown | string | — | — |
|
||||
| predefine | predefine some colors | array | — | — |
|
||||
|
||||
### Events
|
||||
| Event Name | Description | Parameters |
|
||||
|
|
|
@ -5,7 +5,19 @@
|
|||
color1: '#409EFF',
|
||||
color2: null,
|
||||
color3: 'rgba(19, 206, 102, 0.8)',
|
||||
color4: '#409EFF'
|
||||
color4: '#409EFF',
|
||||
color5: 'hsva(180, 65, 20, 0.5)',
|
||||
predefineColors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
@ -88,6 +100,35 @@ ColorPicker es un selector de color que soporta varios formatos de color.
|
|||
```
|
||||
:::
|
||||
|
||||
### Colores predefinidos
|
||||
|
||||
:::demo ColorPicker admite colores predefinidos
|
||||
```html
|
||||
<el-color-picker v-model="color5" show-alpha :predefine="predefineColors"></el-color-picker>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color5: 'hsva(180, 65, 20, 0.5)',
|
||||
predefineColors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Sizes
|
||||
|
||||
:::demo
|
||||
|
@ -117,6 +158,7 @@ ColorPicker es un selector de color que soporta varios formatos de color.
|
|||
| show-alpha | especifica si se muestra el control deslizante para el valor alpha | boolean | — | false |
|
||||
| color-format | formato de color del `v-model` | string | hsl / hsv / hex / rgb | hex (si show-alpha es false)/ rgb (si show-alpha es true) |
|
||||
| popper-class | nombre de clase para el dropdown del ColorPicker | string | — | — |
|
||||
| predefine | colores predefinidos | array | — | — |
|
||||
|
||||
### Eventos
|
||||
| Nombre de Evento | Descripción | Parametros |
|
||||
|
|
|
@ -5,7 +5,19 @@
|
|||
color1: '#409EFF',
|
||||
color2: null,
|
||||
color3: 'rgba(19, 206, 102, 0.8)',
|
||||
color4: '#409EFF'
|
||||
color4: '#409EFF',
|
||||
color5: 'hsva(180, 65, 20, 0.5)',
|
||||
predefineColors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
@ -88,6 +100,35 @@
|
|||
```
|
||||
:::
|
||||
|
||||
### 预定义颜色
|
||||
|
||||
:::demo ColorPicker 支持预定义颜色
|
||||
```html
|
||||
<el-color-picker v-model="color5" show-alpha :predefine="predefineColors"></el-color-picker>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color5: 'hsva(180, 65, 20, 0.5)',
|
||||
predefineColors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 不同尺寸
|
||||
|
||||
:::demo
|
||||
|
@ -117,6 +158,7 @@
|
|||
| show-alpha | 是否支持透明度选择 | boolean | — | false |
|
||||
| color-format | 写入 v-model 的颜色的格式 | string | hsl / hsv / hex / rgb | hex(show-alpha 为 false)/ rgb(show-alpha 为 true) |
|
||||
| popper-class | ColorPicker 下拉框的类名 | string | — | — |
|
||||
| predefine | 预定义颜色 | array | — | — |
|
||||
|
||||
### Events
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
|
|
|
@ -215,6 +215,8 @@ export default class Color {
|
|||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
} else if (parts.length === 3) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
if (parts.length >= 3) {
|
||||
const { h, s, v } = hsl2hsv(parts[0], parts[1], parts[2]);
|
||||
|
@ -226,6 +228,8 @@ export default class Color {
|
|||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
} else if (parts.length === 3) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
if (parts.length >= 3) {
|
||||
fromHSV(parts[0], parts[1], parts[2]);
|
||||
|
@ -236,6 +240,8 @@ export default class Color {
|
|||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
} else if (parts.length === 3) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
if (parts.length >= 3) {
|
||||
const { h, s, v } = rgb2hsv(parts[0], parts[1], parts[2]);
|
||||
|
@ -249,10 +255,16 @@ export default class Color {
|
|||
r = parseHexChannel(hex[0] + hex[0]);
|
||||
g = parseHexChannel(hex[1] + hex[1]);
|
||||
b = parseHexChannel(hex[2] + hex[2]);
|
||||
} else if (hex.length === 6) {
|
||||
} else if (hex.length === 6 || hex.length === 8) {
|
||||
r = parseHexChannel(hex.substring(0, 2));
|
||||
g = parseHexChannel(hex.substring(2, 4));
|
||||
b = parseHexChannel(hex.substring(4));
|
||||
b = parseHexChannel(hex.substring(4, 6));
|
||||
}
|
||||
|
||||
if (hex.length === 8) {
|
||||
this._alpha = Math.floor(parseHexChannel(hex.substring(6)) / 255 * 100);
|
||||
} else if (hex.length === 3 || hex.length === 6) {
|
||||
this._alpha = 100;
|
||||
}
|
||||
|
||||
const { h, s, v } = rgb2hsv(r, g, b);
|
||||
|
@ -260,6 +272,13 @@ export default class Color {
|
|||
}
|
||||
}
|
||||
|
||||
compare(color) {
|
||||
return Math.abs(color._hue - this._hue) < 2 &&
|
||||
Math.abs(color._saturation - this._saturation) < 1 &&
|
||||
Math.abs(color._value - this._value) < 1 &&
|
||||
Math.abs(color._alpha - this._alpha) < 1;
|
||||
}
|
||||
|
||||
doOnChange() {
|
||||
const { _hue, _saturation, _value, _alpha, format } = this;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<sv-panel ref="sl" :color="color"></sv-panel>
|
||||
</div>
|
||||
<alpha-slider v-if="showAlpha" ref="alpha" :color="color"></alpha-slider>
|
||||
<predefine v-if="predefine" :color="color" :colors="predefine"></predefine>
|
||||
<div class="el-color-dropdown__btns">
|
||||
<span class="el-color-dropdown__value">
|
||||
<el-input
|
||||
|
@ -40,6 +41,7 @@
|
|||
import SvPanel from './sv-panel';
|
||||
import HueSlider from './hue-slider';
|
||||
import AlphaSlider from './alpha-slider';
|
||||
import Predefine from './predefine';
|
||||
import Popper from 'element-ui/src/utils/vue-popper';
|
||||
import Locale from 'element-ui/src/mixins/locale';
|
||||
import ElInput from 'element-ui/packages/input';
|
||||
|
@ -55,14 +57,16 @@
|
|||
HueSlider,
|
||||
AlphaSlider,
|
||||
ElInput,
|
||||
ElButton
|
||||
ElButton,
|
||||
Predefine
|
||||
},
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
},
|
||||
showAlpha: Boolean
|
||||
showAlpha: Boolean,
|
||||
predefine: Array
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<div class="el-color-predefine">
|
||||
预设:
|
||||
<div class="el-color-predefine__colors">
|
||||
<div class="el-color-predefine__color-selector"
|
||||
:class="{selected: item.selected, 'is-alpha': item._alpha < 100}"
|
||||
v-for="(item, index) in rgbaColors"
|
||||
:key="colors[index]"
|
||||
@click="handleSelect(index)">
|
||||
<div :style="{'background-color': item.value}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Color from '../color';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
colors: { type: Array, required: true },
|
||||
color: { required: true }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rgbaColors: this.parseColors(this.colors, this.color),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSelect(index) {
|
||||
this.color.fromString(this.colors[index]);
|
||||
},
|
||||
parseColors(colors, color) {
|
||||
return colors.map(value => {
|
||||
const c = new Color();
|
||||
c.enableAlpha = true;
|
||||
c.format = 'rgba';
|
||||
c.fromString(value);
|
||||
c.selected = c.value === color.value;
|
||||
return c;
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$parent.currentColor'(val) {
|
||||
const color = new Color();
|
||||
color.fromString(val);
|
||||
|
||||
this.rgbaColors.forEach(item => {
|
||||
item.selected = color.compare(item);
|
||||
});
|
||||
},
|
||||
colors(newVal) {
|
||||
this.rgbaColors = this.parseColors(newVal, this.color);
|
||||
},
|
||||
color(newVal) {
|
||||
this.rgbaColors = this.parseColors(this.colors, newVal);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -24,7 +24,8 @@
|
|||
@pick="confirmValue"
|
||||
@clear="clearValue"
|
||||
:color="color"
|
||||
:show-alpha="showAlpha">
|
||||
:show-alpha="showAlpha"
|
||||
:predefine="predefine">
|
||||
</picker-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -43,7 +44,8 @@
|
|||
colorFormat: String,
|
||||
disabled: Boolean,
|
||||
size: String,
|
||||
popperClass: String
|
||||
popperClass: String,
|
||||
predefine: Array
|
||||
},
|
||||
|
||||
inject: {
|
||||
|
|
|
@ -1,6 +1,40 @@
|
|||
@import "mixins/mixins";
|
||||
@import "common/var";
|
||||
|
||||
@include b(color-predefine) {
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
|
||||
@include e(colors) {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@include e(color-selector) {
|
||||
margin: 0 0 6px 6px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 1px #8c939d solid;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected {
|
||||
border: 3px $--color-primary solid;
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@include when(alpha) {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include b(color-hue-slider) {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
|
|
|
@ -265,4 +265,98 @@ describe('ColorPicker', () => {
|
|||
});
|
||||
}, ANIMATION_TIME);
|
||||
});
|
||||
|
||||
it('should change color to the selected color', done => {
|
||||
const vm = createVue({
|
||||
template: `
|
||||
<el-color-picker v-model="color" show-alpha :predefine="colors"></el-color-picker>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
color: 'hsva(180, 65, 20, 0.5)',
|
||||
colors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
|
||||
const trigger = vm.$el.querySelector('.el-color-picker__trigger');
|
||||
trigger.click();
|
||||
|
||||
setTimeout(() => {
|
||||
expect(document.querySelectorAll('.el-color-predefine__color-selector').length === 9).to.be.true;
|
||||
const selector = document.querySelector('.el-color-predefine__color-selector:nth-child(4)');
|
||||
selector.click();
|
||||
vm.$nextTick(() => {
|
||||
const picker = vm.$children[0];
|
||||
expect(picker.color._hue === 180).to.be.true;
|
||||
expect(picker.color._saturation === 65).to.be.true;
|
||||
expect(picker.color._value === 20).to.be.true;
|
||||
expect(picker.color._alpha === 50).to.be.true;
|
||||
|
||||
const selector2 = document.querySelector('.el-color-predefine__color-selector:nth-child(3)');
|
||||
selector2.click();
|
||||
|
||||
vm.$nextTick(() => {
|
||||
expect(picker.color._hue === 250).to.be.true;
|
||||
expect(picker.color._saturation === 54).to.be.true;
|
||||
expect(picker.color._value === 98).to.be.true;
|
||||
expect(picker.color._alpha === 100).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should change selected state of predefined color', done => {
|
||||
const vm = createVue({
|
||||
template: `
|
||||
<el-color-picker v-model="color" show-alpha :predefine="colors"></el-color-picker>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
color: 'hsva(180, 65, 20, 0.5)',
|
||||
colors: [
|
||||
'rgba(19, 206, 102, 0.18)',
|
||||
'rgb(25, 159, 147)',
|
||||
'hsv(250, 54, 98)',
|
||||
'hsva(180, 65, 20, 0.5)',
|
||||
'hsl(170, 32%, 87%)',
|
||||
'hsla(45, 62%, 47%, 0.13)',
|
||||
'#7486de',
|
||||
'#45aa9477',
|
||||
'#892345'
|
||||
]
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
|
||||
const trigger = vm.$el.querySelector('.el-color-picker__trigger');
|
||||
trigger.click();
|
||||
|
||||
setTimeout(() => {
|
||||
const selector = document.querySelector('.el-color-predefine__color-selector:nth-child(4)');
|
||||
selector.click();
|
||||
vm.$nextTick(() => {
|
||||
expect(selector.classList.contains('selected')).to.be.true;
|
||||
|
||||
const hueBar = document.querySelector('.el-color-hue-slider');
|
||||
hueBar.__vue__.handleClick({ target: null, clientX: 0, clientY: 1000 });
|
||||
|
||||
vm.$nextTick(() => {
|
||||
expect(selector.classList.contains('selected')).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue