Color keyboard control
This commit is contained in:
parent
b924d14da3
commit
f2bcd4adaf
13 changed files with 1314 additions and 653 deletions
|
@ -1,46 +1,157 @@
|
||||||
<template>
|
<template>
|
||||||
<div style="margin: 100px;">
|
<div style="margin: 100px;">
|
||||||
{{ color }}
|
{{color}}
|
||||||
<!--<Input placeholder="请输入..." size="large" style="width: 50px;"></Input>-->
|
<!--<Input placeholder="请输入..." size="large" style="width: 50px;"></Input>-->
|
||||||
<color-picker @on-change="c1" @on-active-change="c2" v-model="color" placement="bottom-start" size="large"></color-picker>
|
<color-picker
|
||||||
<Date-picker transfer type="date" placeholder="选择日期" style="width: 200px"></Date-picker>
|
v-model="color"
|
||||||
<color-picker :transfer="true" ref="xxx" v-model="color" format="rgb" alpha :recommend="true"></color-picker>
|
placement="bottom-start"
|
||||||
<color-picker v-model="color2" format="hsv" :alpha="true" :recommend="false"></color-picker>
|
size="large"
|
||||||
|
@on-change="c1"
|
||||||
|
@on-active-change="c2"></color-picker>
|
||||||
|
<Date-picker
|
||||||
|
transfer
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
style="width: 200px"></Date-picker>
|
||||||
|
<color-picker
|
||||||
|
ref="xxx"
|
||||||
|
:transfer="true"
|
||||||
|
v-model="color"
|
||||||
|
:recommend="true"
|
||||||
|
format="rgb"
|
||||||
|
alpha
|
||||||
|
@on-change="onChange"
|
||||||
|
@on-active-change="onActiveChange"></color-picker>
|
||||||
|
<color-picker
|
||||||
|
v-model="color2"
|
||||||
|
:alpha="true"
|
||||||
|
:recommend="false"
|
||||||
|
format="hsv"></color-picker>
|
||||||
<!--<Date-picker type="date" placeholder="选择日期" style="width: 200px"></Date-picker>-->
|
<!--<Date-picker type="date" placeholder="选择日期" style="width: 200px"></Date-picker>-->
|
||||||
<color-picker v-model="color" placement="bottom-start" size="small"></color-picker>
|
<color-picker
|
||||||
<Date-picker type="date" placeholder="选择日期" size="small" style="width: 200px"></Date-picker>
|
v-model="color"
|
||||||
|
placement="bottom-start"
|
||||||
|
size="small"></color-picker>
|
||||||
|
<Date-picker
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
size="small"
|
||||||
|
style="width: 200px"></Date-picker>
|
||||||
|
<color-picker
|
||||||
|
ref="yyy"
|
||||||
|
:colors="colors"
|
||||||
|
v-model="color"
|
||||||
|
transfer
|
||||||
|
format="rgb"
|
||||||
|
alpha></color-picker>
|
||||||
<Button @click="setColor">set color</Button>
|
<Button @click="setColor">set color</Button>
|
||||||
|
|
||||||
<br><br><br><br>
|
<br><br><br><br>
|
||||||
{{openState}}
|
{{openState}}
|
||||||
<ColorPicker v-model="color7" :hue="false" @on-open-change="onOpenChange"></ColorPicker>
|
<ColorPicker
|
||||||
|
v-model="color7"
|
||||||
|
:hue="false"
|
||||||
|
@on-open-change="onOpenChange"></ColorPicker>
|
||||||
|
<ColorPicker
|
||||||
|
v-model="color7"
|
||||||
|
:hue="false"
|
||||||
|
:hide-drop-down="hideDropDown"
|
||||||
|
transfer
|
||||||
|
@on-open-change="onOpenChange"></ColorPicker>
|
||||||
|
|
||||||
|
<br><br><br><br>
|
||||||
|
<ColorPicker
|
||||||
|
v-model="color7"
|
||||||
|
disabled></ColorPicker>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {},
|
props: {},
|
||||||
data () {
|
|
||||||
return {
|
data() {
|
||||||
color: 'rgba(12,34,255,.85)',
|
return {
|
||||||
color2: '',
|
color: 'rgba(12,34,255,.85)',
|
||||||
color7: '#19be6b',
|
color2: '',
|
||||||
openState: false,
|
color7: '#19be6b',
|
||||||
};
|
openState: false,
|
||||||
|
colors: [
|
||||||
|
'#2d8cf0',
|
||||||
|
'#19be6b',
|
||||||
|
'#ff9900',
|
||||||
|
'#ed3f14',
|
||||||
|
'#00b5ff',
|
||||||
|
'#19c919',
|
||||||
|
'#f9e31c',
|
||||||
|
'#ea1a1a',
|
||||||
|
'#9b1dea',
|
||||||
|
'#00c2b1',
|
||||||
|
'#ac7a33',
|
||||||
|
'#1d35ea',
|
||||||
|
'#8bc34a',
|
||||||
|
'#f16b62',
|
||||||
|
'#ea4ca3',
|
||||||
|
'#0d94aa',
|
||||||
|
'#febd79',
|
||||||
|
'#5d4037',
|
||||||
|
'#00bcd4',
|
||||||
|
'#f06292',
|
||||||
|
'#cddc39',
|
||||||
|
'#607d8b',
|
||||||
|
'#000000',
|
||||||
|
'#ffffff',
|
||||||
|
'#2d8cf0',
|
||||||
|
'#19be6b',
|
||||||
|
'#ff9900',
|
||||||
|
'#ed3f14',
|
||||||
|
'#00b5ff',
|
||||||
|
'#19c919',
|
||||||
|
'#f9e31c',
|
||||||
|
'#ea1a1a',
|
||||||
|
'#9b1dea',
|
||||||
|
'#00c2b1',
|
||||||
|
'#ac7a33',
|
||||||
|
'#1d35ea',
|
||||||
|
'#8bc34a',
|
||||||
|
'#f16b62',
|
||||||
|
'#ea4ca3',
|
||||||
|
'#0d94aa',
|
||||||
|
'#febd79',
|
||||||
|
'#5d4037',
|
||||||
|
],
|
||||||
|
hideDropDown: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
setInterval(this.toggleShowHide, 2000);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
setColor() {
|
||||||
|
this.color = '#26bc77';
|
||||||
},
|
},
|
||||||
computed: {},
|
c1(d) {
|
||||||
methods: {
|
console.log(d);
|
||||||
setColor () {
|
},
|
||||||
this.color = '#26bc77';
|
c2(d) {
|
||||||
},
|
console.log(d);
|
||||||
c1 (d) {
|
},
|
||||||
console.log(d);
|
onOpenChange(state) {
|
||||||
},
|
this.openState = state;
|
||||||
c2 (d) {
|
},
|
||||||
console.log(d);
|
onChange(d) {
|
||||||
},
|
console.log(d);
|
||||||
onOpenChange(state){
|
},
|
||||||
this.openState = state;
|
onActiveChange(d) {
|
||||||
}
|
console.log(d);
|
||||||
}
|
},
|
||||||
};
|
toggleShowHide() {
|
||||||
|
this.hideDropDown = !this.hideDropDown;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,77 +1,103 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ivu-color-picker-alpha">
|
<div
|
||||||
<div class="ivu-color-picker-alpha-checkboard-wrap">
|
:class="[prefixCls + '-alpha']"
|
||||||
<div class="ivu-color-picker-alpha-checkerboard"></div>
|
tabindex="0"
|
||||||
|
@click="$el.focus()"
|
||||||
|
@keydown.esc="handleEscape"
|
||||||
|
@keydown.left="handleLeft"
|
||||||
|
@keydown.right="handleRight"
|
||||||
|
@keydown.up="handleUp"
|
||||||
|
@keydown.down="handleDown"
|
||||||
|
>
|
||||||
|
<div :class="[prefixCls + '-alpha-checkboard-wrap']">
|
||||||
|
<div :class="[prefixCls + '-alpha-checkerboard']"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ivu-color-picker-alpha-gradient" :style="{background: gradientColor}"></div>
|
<div
|
||||||
<div class="ivu-color-picker-alpha-container" ref="container"
|
:style="gradientStyle"
|
||||||
@mousedown="handleMouseDown"
|
:class="[prefixCls + '-alpha-gradient']"></div>
|
||||||
@touchmove="handleChange"
|
<div
|
||||||
@touchstart="handleChange">
|
ref="container"
|
||||||
<div class="ivu-color-picker-alpha-pointer" :style="{left: colors.a * 100 + '%'}">
|
:class="[prefixCls + '-alpha-container']"
|
||||||
<div class="ivu-color-picker-alpha-picker"></div>
|
@mousedown="handleMouseDown"
|
||||||
|
@touchmove="handleChange"
|
||||||
|
@touchstart="handleChange">
|
||||||
|
<div
|
||||||
|
:style="{top: 0, left: `${value.a * 100}%`}"
|
||||||
|
:class="[prefixCls + '-alpha-pointer']">
|
||||||
|
<div :class="[prefixCls + '-alpha-picker']"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import HSAMixin from './hsaMixin';
|
||||||
name: 'Alpha',
|
import Prefixes from './prefixMixin';
|
||||||
props: {
|
import {clamp, toRGBAString} from './utils';
|
||||||
value: Object,
|
|
||||||
onChange: Function
|
export default {
|
||||||
|
name: 'Alpha',
|
||||||
|
|
||||||
|
mixins: [HSAMixin, Prefixes],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
const normalStep = 1;
|
||||||
|
const jumpStep = 10;
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: -normalStep,
|
||||||
|
right: normalStep,
|
||||||
|
up: jumpStep,
|
||||||
|
down: -jumpStep,
|
||||||
|
powerKey: 'shiftKey',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
gradientStyle() {
|
||||||
|
const {r, g, b} = this.value.rgba;
|
||||||
|
const start = toRGBAString({r, g, b, a: 0});
|
||||||
|
const finish = toRGBAString({r, g, b, a: 1});
|
||||||
|
|
||||||
|
return {background: `linear-gradient(to right, ${start} 0%, ${finish} 100%)`};
|
||||||
},
|
},
|
||||||
computed: {
|
},
|
||||||
colors () {
|
|
||||||
return this.value;
|
methods: {
|
||||||
},
|
change(newAlpha) {
|
||||||
gradientColor () {
|
const {h, s, l} = this.value.hsl;
|
||||||
const rgba = this.colors.rgba;
|
const {a} = this.value;
|
||||||
const rgbStr = [rgba.r, rgba.g, rgba.b].join(',');
|
|
||||||
return 'linear-gradient(to right, rgba(' + rgbStr + ', 0) 0%, rgba(' + rgbStr + ', 1) 100%)';
|
if (a !== newAlpha) {
|
||||||
|
this.$emit('change', {h, s, l, a: newAlpha, source: 'rgba'});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
handleSlide(e, direction) {
|
||||||
handleChange (e, skip) {
|
e.preventDefault();
|
||||||
!skip && e.preventDefault();
|
e.stopPropagation();
|
||||||
const container = this.$refs.container;
|
|
||||||
const containerWidth = container.clientWidth;
|
|
||||||
|
|
||||||
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
this.change(clamp(e[this.powerKey] ? direction : Math.round(this.value.hsl.a * 100 + direction) / 100, 0, 1));
|
||||||
const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0);
|
},
|
||||||
const left = pageX - xOffset;
|
handleChange(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
let a;
|
const left = this.getLeft(e);
|
||||||
if (left < 0) {
|
|
||||||
a = 0;
|
|
||||||
} else if (left > containerWidth) {
|
|
||||||
a = 1;
|
|
||||||
} else {
|
|
||||||
a = Math.round(left * 100 / containerWidth) / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.colors.a !== a) {
|
if (left < 0) {
|
||||||
this.$emit('change', {
|
this.change(0);
|
||||||
h: this.colors.hsl.h,
|
return;
|
||||||
s: this.colors.hsl.s,
|
|
||||||
l: this.colors.hsl.l,
|
|
||||||
a: a,
|
|
||||||
source: 'rgba'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleMouseDown (e) {
|
|
||||||
this.handleChange(e, true);
|
|
||||||
window.addEventListener('mousemove', this.handleChange);
|
|
||||||
window.addEventListener('mouseup', this.handleMouseUp);
|
|
||||||
},
|
|
||||||
handleMouseUp () {
|
|
||||||
this.unbindEventListeners();
|
|
||||||
},
|
|
||||||
unbindEventListeners () {
|
|
||||||
window.removeEventListener('mousemove', this.handleChange);
|
|
||||||
window.removeEventListener('mouseup', this.handleMouseUp);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
const {clientWidth} = this.$refs.container;
|
||||||
</script>
|
|
||||||
|
if (left > clientWidth) {
|
||||||
|
this.change(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.change(Math.round(left * 100 / clientWidth) / 100);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
|
@ -1,375 +1,453 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="classes" v-clickoutside="handleClose">
|
<div
|
||||||
<div ref="reference" @click="toggleVisible" :class="wrapClasses">
|
v-click-outside.capture="handleClose"
|
||||||
<input type="hidden" :name="name" :value="currentValue">
|
v-click-outside:mousedown.capture="handleClose"
|
||||||
<i class="ivu-icon ivu-icon-arrow-down-b ivu-input-icon ivu-input-icon-normal"></i>
|
:class="classes">
|
||||||
<div :class="inputClasses">
|
<div
|
||||||
|
ref="reference"
|
||||||
|
:class="wrapClasses"
|
||||||
|
@click="toggleVisible">
|
||||||
|
<input
|
||||||
|
:name="name"
|
||||||
|
:value="currentValue"
|
||||||
|
type="hidden">
|
||||||
|
<i :class="arrowClasses"></i>
|
||||||
|
<div
|
||||||
|
ref="input"
|
||||||
|
:tabindex="disabled ? undefined : 0"
|
||||||
|
:class="inputClasses"
|
||||||
|
@keydown.tab="onTab"
|
||||||
|
@keydown.esc="onEscape"
|
||||||
|
@keydown.up="onArrow"
|
||||||
|
@keydown.down="onArrow"
|
||||||
|
>
|
||||||
<div :class="[prefixCls + '-color']">
|
<div :class="[prefixCls + '-color']">
|
||||||
<div :class="[prefixCls + '-color-empty']" v-show="value === '' && !visible">
|
<div
|
||||||
<i class="ivu-icon ivu-icon-ios-close-empty"></i>
|
v-show="value === '' && !visible"
|
||||||
|
:class="[prefixCls + '-color-empty']">
|
||||||
|
<i :class="[iconPrefixCls, iconPrefixCls + '-ios-close-empty']"></i>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="value || visible" :style="{backgroundColor: displayedColor}"></div>
|
<div
|
||||||
|
v-show="value || visible"
|
||||||
|
:style="displayedColorStyle"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<transition name="transition-drop">
|
<transition name="transition-drop">
|
||||||
<Drop
|
<Drop
|
||||||
|
v-transfer-dom
|
||||||
v-show="visible"
|
v-show="visible"
|
||||||
@click.native="handleTransferClick"
|
|
||||||
:class="{ [prefixCls + '-transfer']: transfer }"
|
|
||||||
class-name="ivu-transfer-no-max-height"
|
|
||||||
:placement="placement"
|
|
||||||
ref="drop"
|
ref="drop"
|
||||||
|
:placement="placement"
|
||||||
:data-transfer="transfer"
|
:data-transfer="transfer"
|
||||||
v-transfer-dom>
|
:class="dropClasses"
|
||||||
<div :class="[prefixCls + '-picker']">
|
>
|
||||||
<div :class="[prefixCls + '-picker-wrapper']">
|
<transition name="fade">
|
||||||
<div :class="[prefixCls + '-picker-panel']">
|
<div
|
||||||
<Saturation v-model="saturationColors" @change="childChange"></Saturation>
|
v-if="visible"
|
||||||
|
:class="[prefixCls + '-picker']">
|
||||||
|
<div :class="[prefixCls + '-picker-wrapper']">
|
||||||
|
<div :class="[prefixCls + '-picker-panel']">
|
||||||
|
<Saturation
|
||||||
|
ref="saturation"
|
||||||
|
v-model="saturationColors"
|
||||||
|
:focused="visible"
|
||||||
|
@change="childChange"
|
||||||
|
@keydown.native.tab="handleFirstTab"
|
||||||
|
></Saturation>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="hue"
|
||||||
|
:class="[prefixCls + '-picker-hue-slider']">
|
||||||
|
<Hue
|
||||||
|
v-model="saturationColors"
|
||||||
|
@change="childChange"></Hue>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="alpha"
|
||||||
|
:class="[prefixCls + '-picker-alpha-slider']">
|
||||||
|
<Alpha
|
||||||
|
v-model="saturationColors"
|
||||||
|
@change="childChange"></Alpha>
|
||||||
|
</div>
|
||||||
|
<recommend-colors
|
||||||
|
v-if="colors.length"
|
||||||
|
:list="colors"
|
||||||
|
:class="[prefixCls + '-picker-colors']"
|
||||||
|
@picker-color="handleSelectColor"></recommend-colors>
|
||||||
|
<recommend-colors
|
||||||
|
v-if="!colors.length && recommend"
|
||||||
|
:list="recommendedColor"
|
||||||
|
:class="[prefixCls + '-picker-colors']"
|
||||||
|
@picker-color="handleSelectColor"></recommend-colors>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="hue" :class="[prefixCls + '-picker-hue-slider']">
|
<div :class="[prefixCls + '-confirm']">
|
||||||
<Hue v-model="saturationColors" @change="childChange"></Hue>
|
<span :class="[prefixCls + '-confirm-color']">{{formatColor}}</span>
|
||||||
|
<i-button
|
||||||
|
ref="clear"
|
||||||
|
:tabindex="0"
|
||||||
|
size="small"
|
||||||
|
type="ghost"
|
||||||
|
@click.native="handleClear"
|
||||||
|
@keydown.enter="handleClear"
|
||||||
|
@keydown.native.esc="closer"
|
||||||
|
>{{t('i.datepicker.clear')}}</i-button>
|
||||||
|
<i-button
|
||||||
|
ref="ok"
|
||||||
|
:tabindex="0"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
@click.native="handleSuccess"
|
||||||
|
@keydown.native.tab="handleLastTab"
|
||||||
|
@keydown.enter="handleSuccess"
|
||||||
|
@keydown.native.esc="closer"
|
||||||
|
>{{t('i.datepicker.ok')}}</i-button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="alpha" :class="[prefixCls + '-picker-alpha-slider']">
|
|
||||||
<Alpha v-model="saturationColors" @change="childChange"></Alpha>
|
|
||||||
</div>
|
|
||||||
<recommend-colors
|
|
||||||
v-if="colors.length"
|
|
||||||
:list="colors"
|
|
||||||
:class="[prefixCls + '-picker-colors']"
|
|
||||||
@picker-color="handleSelectColor"></recommend-colors>
|
|
||||||
<recommend-colors
|
|
||||||
v-if="!colors.length && recommend"
|
|
||||||
:list="recommendedColor"
|
|
||||||
:class="[prefixCls + '-picker-colors']"
|
|
||||||
@picker-color="handleSelectColor"></recommend-colors>
|
|
||||||
</div>
|
</div>
|
||||||
<div :class="[prefixCls + '-confirm']">
|
</transition>
|
||||||
<span :class="[prefixCls + '-confirm-color']">{{ formatColor }}</span>
|
|
||||||
<Confirm @on-pick-success="handleSuccess" @on-pick-clear="handleClear"></Confirm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Drop>
|
</Drop>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import tinycolor from 'tinycolor2';
|
import tinycolor from 'tinycolor2';
|
||||||
|
import vClickOutside from 'v-click-outside-x/index';
|
||||||
|
import TransferDom from '../../directives/transfer-dom';
|
||||||
|
import Drop from '../../components/select/dropdown.vue';
|
||||||
|
import RecommendColors from './recommend-colors.vue';
|
||||||
|
import Saturation from './saturation.vue';
|
||||||
|
import Hue from './hue.vue';
|
||||||
|
import Alpha from './alpha.vue';
|
||||||
|
import Locale from '../../mixins/locale';
|
||||||
|
import {oneOf} from '../../utils/assist';
|
||||||
|
import Emitter from '../../mixins/emitter';
|
||||||
|
import Prefixes from './prefixMixin';
|
||||||
|
import {changeColor, toRGBAString} from './utils';
|
||||||
|
|
||||||
import clickoutside from '../../directives/clickoutside';
|
export default {
|
||||||
import TransferDom from '../../directives/transfer-dom';
|
name: 'ColorPicker',
|
||||||
|
|
||||||
import Drop from '../../components/select/dropdown.vue';
|
components: {Drop, RecommendColors, Saturation, Hue, Alpha},
|
||||||
import RecommendColors from './recommend-colors.vue';
|
|
||||||
import Confirm from '../date-picker/base/confirm.vue';
|
|
||||||
import Saturation from './saturation.vue';
|
|
||||||
import Hue from './hue.vue';
|
|
||||||
import Alpha from './alpha.vue';
|
|
||||||
|
|
||||||
import { oneOf } from '../../utils/assist';
|
directives: {clickOutside: vClickOutside.directive, TransferDom},
|
||||||
import Emitter from '../../mixins/emitter';
|
|
||||||
|
|
||||||
const prefixCls = 'ivu-color-picker';
|
mixins: [Emitter, Locale, Prefixes],
|
||||||
const inputPrefixCls = 'ivu-input';
|
|
||||||
|
|
||||||
function _colorChange (data, oldHue) {
|
props: {
|
||||||
data = data === '' ? '#2d8cf0' : data;
|
value: {
|
||||||
const alpha = data && data.a;
|
type: String,
|
||||||
let color;
|
default: undefined,
|
||||||
|
},
|
||||||
// hsl is better than hex between conversions
|
hue: {
|
||||||
if (data && data.hsl) {
|
type: Boolean,
|
||||||
color = tinycolor(data.hsl);
|
default: true,
|
||||||
} else if (data && data.hex && data.hex.length > 0) {
|
},
|
||||||
color = tinycolor(data.hex);
|
alpha: {
|
||||||
} else {
|
type: Boolean,
|
||||||
color = tinycolor(data);
|
default: false,
|
||||||
}
|
},
|
||||||
|
recommend: {
|
||||||
if (color && (color._a === undefined || color._a === null)) {
|
type: Boolean,
|
||||||
color.setAlpha(alpha || 1);
|
default: false,
|
||||||
}
|
},
|
||||||
|
format: {
|
||||||
const hsl = color.toHsl();
|
type: String,
|
||||||
const hsv = color.toHsv();
|
validator(value) {
|
||||||
|
return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']);
|
||||||
if (hsl.s === 0) {
|
},
|
||||||
hsv.h = hsl.h = data.h || (data.hsl && data.hsl.h) || oldHue || 0;
|
default: undefined,
|
||||||
}
|
},
|
||||||
|
colors: {
|
||||||
// when the hsv.v is less than 0.0164 (base on test)
|
type: Array,
|
||||||
// because of possible loss of precision
|
default() {
|
||||||
// the result of hue and saturation would be miscalculated
|
return [];
|
||||||
if (hsv.v < 0.0164) {
|
},
|
||||||
hsv.h = data.h || (data.hsv && data.hsv.h) || 0;
|
},
|
||||||
hsv.s = data.s || (data.hsv && data.hsv.s) || 0;
|
disabled: {
|
||||||
}
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
if (hsl.l < 0.01) {
|
},
|
||||||
hsl.h = data.h || (data.hsl && data.hsl.h) || 0;
|
size: {
|
||||||
hsl.s = data.s || (data.hsl && data.hsl.s) || 0;
|
type: String,
|
||||||
}
|
validator(value) {
|
||||||
|
return oneOf(value, ['small', 'large', 'default']);
|
||||||
|
},
|
||||||
|
default: 'default',
|
||||||
|
},
|
||||||
|
hideDropDown: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
placement: {
|
||||||
|
type: String,
|
||||||
|
validator(value) {
|
||||||
|
return oneOf(value, [
|
||||||
|
'top',
|
||||||
|
'top-start',
|
||||||
|
'top-end',
|
||||||
|
'bottom',
|
||||||
|
'bottom-start',
|
||||||
|
'bottom-end',
|
||||||
|
'left',
|
||||||
|
'left-start',
|
||||||
|
'left-end',
|
||||||
|
'right',
|
||||||
|
'right-start',
|
||||||
|
'right-end',
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
default: 'bottom',
|
||||||
|
},
|
||||||
|
transfer: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
return {
|
return {
|
||||||
hsl: hsl,
|
val: changeColor(this.value),
|
||||||
hex: color.toHexString().toUpperCase(),
|
currentValue: this.value,
|
||||||
rgba: color.toRgb(),
|
dragging: false,
|
||||||
hsv: hsv,
|
visible: false,
|
||||||
oldHue: data.h || oldHue || hsl.h,
|
recommendedColor: [
|
||||||
source: data.source,
|
'#2d8cf0',
|
||||||
a: data.a || color.getAlpha()
|
'#19be6b',
|
||||||
|
'#ff9900',
|
||||||
|
'#ed3f14',
|
||||||
|
'#00b5ff',
|
||||||
|
'#19c919',
|
||||||
|
'#f9e31c',
|
||||||
|
'#ea1a1a',
|
||||||
|
'#9b1dea',
|
||||||
|
'#00c2b1',
|
||||||
|
'#ac7a33',
|
||||||
|
'#1d35ea',
|
||||||
|
'#8bc34a',
|
||||||
|
'#f16b62',
|
||||||
|
'#ea4ca3',
|
||||||
|
'#0d94aa',
|
||||||
|
'#febd79',
|
||||||
|
'#5d4037',
|
||||||
|
'#00bcd4',
|
||||||
|
'#f06292',
|
||||||
|
'#cddc39',
|
||||||
|
'#607d8b',
|
||||||
|
'#000000',
|
||||||
|
'#ffffff',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
|
|
||||||
export default {
|
computed: {
|
||||||
name: 'ColorPicker',
|
arrowClasses() {
|
||||||
mixins: [ Emitter ],
|
return [
|
||||||
components: { Drop, Confirm, RecommendColors, Saturation, Hue, Alpha },
|
this.iconPrefixCls,
|
||||||
directives: { clickoutside, TransferDom },
|
`${this.iconPrefixCls}-arrow-down-b`,
|
||||||
props: {
|
`${this.inputPrefixCls}-icon`,
|
||||||
value: {
|
`${this.inputPrefixCls}-icon-normal`,
|
||||||
type: String
|
];
|
||||||
|
},
|
||||||
|
transition() {
|
||||||
|
return oneOf(this.placement, ['bottom-start', 'bottom', 'bottom-end']) ? 'slide-up' : 'fade';
|
||||||
|
},
|
||||||
|
saturationColors: {
|
||||||
|
get() {
|
||||||
|
return this.val;
|
||||||
},
|
},
|
||||||
hue: {
|
set(newVal) {
|
||||||
type: Boolean,
|
this.val = newVal;
|
||||||
default: true
|
this.$emit('on-active-change', this.formatColor);
|
||||||
},
|
},
|
||||||
alpha: {
|
},
|
||||||
type: Boolean,
|
classes() {
|
||||||
default: false
|
return [
|
||||||
},
|
`${this.prefixCls}`,
|
||||||
recommend: {
|
{
|
||||||
type: Boolean,
|
[`${this.prefixCls}-transfer`]: this.transfer,
|
||||||
default: false
|
|
||||||
},
|
|
||||||
format: {
|
|
||||||
validator (value) {
|
|
||||||
return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors: {
|
|
||||||
type: Array,
|
|
||||||
default () {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
validator (value) {
|
|
||||||
return oneOf(value, ['small', 'large', 'default']);
|
|
||||||
},
|
},
|
||||||
default: 'default'
|
];
|
||||||
},
|
},
|
||||||
placement: {
|
wrapClasses() {
|
||||||
validator (value) {
|
return [
|
||||||
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
|
`${this.prefixCls}-rel`,
|
||||||
|
`${this.prefixCls}-${this.size}`,
|
||||||
|
`${this.inputPrefixCls}-wrapper`,
|
||||||
|
`${this.inputPrefixCls}-wrapper-${this.size}`,
|
||||||
|
{
|
||||||
|
[`${this.prefixCls}-disabled`]: this.disabled,
|
||||||
},
|
},
|
||||||
default: 'bottom'
|
];
|
||||||
},
|
|
||||||
transfer: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: String
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data () {
|
inputClasses() {
|
||||||
return {
|
return [
|
||||||
val: _colorChange(this.value),
|
`${this.prefixCls}-input`,
|
||||||
currentValue: this.value,
|
`${this.inputPrefixCls}`,
|
||||||
prefixCls: prefixCls,
|
`${this.inputPrefixCls}-${this.size}`,
|
||||||
visible: false,
|
{
|
||||||
disableCloseUnderTransfer: false, // transfer 模式下,点击Drop也会触发关闭
|
[`${this.prefixCls}-focused`]: this.visible,
|
||||||
recommendedColor: [
|
[`${this.prefixCls}-disabled`]: this.disabled,
|
||||||
'#2d8cf0',
|
|
||||||
'#19be6b',
|
|
||||||
'#ff9900',
|
|
||||||
'#ed3f14',
|
|
||||||
'#00b5ff',
|
|
||||||
'#19c919',
|
|
||||||
'#f9e31c',
|
|
||||||
'#ea1a1a',
|
|
||||||
'#9b1dea',
|
|
||||||
'#00c2b1',
|
|
||||||
'#ac7a33',
|
|
||||||
'#1d35ea',
|
|
||||||
'#8bc34a',
|
|
||||||
'#f16b62',
|
|
||||||
'#ea4ca3',
|
|
||||||
'#0d94aa',
|
|
||||||
'#febd79',
|
|
||||||
'#5d4037',
|
|
||||||
'#00bcd4',
|
|
||||||
'#f06292',
|
|
||||||
'#cddc39',
|
|
||||||
'#607d8b',
|
|
||||||
'#000000',
|
|
||||||
'#ffffff'
|
|
||||||
]
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
transition () {
|
|
||||||
if (this.placement === 'bottom-start' || this.placement === 'bottom' || this.placement === 'bottom-end') {
|
|
||||||
return 'slide-up';
|
|
||||||
} else {
|
|
||||||
return 'fade';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
saturationColors: {
|
|
||||||
get () {
|
|
||||||
return this.val;
|
|
||||||
},
|
},
|
||||||
set (newVal) {
|
];
|
||||||
this.val = newVal;
|
},
|
||||||
this.$emit('on-active-change', this.formatColor);
|
dropClasses() {
|
||||||
}
|
return [
|
||||||
},
|
`${this.transferPrefixCls}-no-max-height`,
|
||||||
classes () {
|
{
|
||||||
return [
|
[`${this.prefixCls}-transfer`]: this.transfer,
|
||||||
`${prefixCls}`,
|
[`${this.prefixCls}-hide-drop`]: this.hideDropDown,
|
||||||
{
|
},
|
||||||
[`${prefixCls}-transfer`]: this.transfer
|
];
|
||||||
}
|
},
|
||||||
];
|
displayedColorStyle() {
|
||||||
},
|
return {backgroundColor: toRGBAString(this.visible ? this.saturationColors.rgba : tinycolor(this.value).toRgb())};
|
||||||
wrapClasses () {
|
},
|
||||||
return [
|
formatColor() {
|
||||||
`${prefixCls}-rel`,
|
const {format, saturationColors} = this;
|
||||||
`${prefixCls}-${this.size}`,
|
|
||||||
`${inputPrefixCls}-wrapper`,
|
|
||||||
`${inputPrefixCls}-wrapper-${this.size}`
|
|
||||||
];
|
|
||||||
},
|
|
||||||
inputClasses () {
|
|
||||||
return [
|
|
||||||
`${prefixCls}-input`,
|
|
||||||
`${inputPrefixCls}`,
|
|
||||||
`${inputPrefixCls}-${this.size}`,
|
|
||||||
{
|
|
||||||
[`${inputPrefixCls}-disabled`]: this.disabled
|
|
||||||
}
|
|
||||||
];
|
|
||||||
},
|
|
||||||
displayedColor () {
|
|
||||||
let color;
|
|
||||||
if (this.visible) {
|
|
||||||
const rgba = this.saturationColors.rgba;
|
|
||||||
color = {
|
|
||||||
r: rgba.r,
|
|
||||||
g: rgba.g,
|
|
||||||
b: rgba.b,
|
|
||||||
a: rgba.a
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
color = tinycolor(this.value).toRgb();
|
|
||||||
}
|
|
||||||
return `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`;
|
|
||||||
},
|
|
||||||
formatColor () {
|
|
||||||
const value = this.saturationColors;
|
|
||||||
const format = this.format;
|
|
||||||
let color;
|
|
||||||
|
|
||||||
const rgba = `rgba(${value.rgba.r}, ${value.rgba.g}, ${value.rgba.b}, ${value.rgba.a})`;
|
if (format) {
|
||||||
if (format) {
|
if (format === 'hsl') {
|
||||||
if (format === 'hsl') {
|
return tinycolor(saturationColors.hsl).toHslString();
|
||||||
color = tinycolor(value.hsl).toHslString();
|
|
||||||
} else if (format === 'hsv') {
|
|
||||||
color = tinycolor(value.hsv).toHsvString();
|
|
||||||
} else if (format === 'hex') {
|
|
||||||
color = value.hex;
|
|
||||||
} else if (format === 'rgb') {
|
|
||||||
color = rgba;
|
|
||||||
}
|
|
||||||
} else if (this.alpha) {
|
|
||||||
color = rgba;
|
|
||||||
} else {
|
|
||||||
color = value.hex;
|
|
||||||
}
|
}
|
||||||
return color;
|
|
||||||
|
if (format === 'hsv') {
|
||||||
|
return tinycolor(saturationColors.hsv).toHsvString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'hex') {
|
||||||
|
return saturationColors.hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'rgb') {
|
||||||
|
return toRGBAString(saturationColors.rgba);
|
||||||
|
}
|
||||||
|
} else if (this.alpha) {
|
||||||
|
return toRGBAString(saturationColors.rgba);
|
||||||
|
}
|
||||||
|
|
||||||
|
return saturationColors.hex;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value(newVal) {
|
||||||
|
this.val = changeColor(newVal);
|
||||||
|
},
|
||||||
|
visible(val) {
|
||||||
|
this.val = changeColor(this.value);
|
||||||
|
this.$refs.drop[val ? 'update' : 'destroy']();
|
||||||
|
this.$emit('on-open-change', Boolean(val));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$on('on-escape-keydown', this.closer);
|
||||||
|
this.$on('on-dragging', this.setDragging);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
setDragging(value) {
|
||||||
|
this.dragging = value;
|
||||||
|
},
|
||||||
|
handleClose(event) {
|
||||||
|
if (this.visible) {
|
||||||
|
if (this.dragging || event.type === 'mousedown') {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.transfer) {
|
||||||
|
const {$el} = this.$refs.drop;
|
||||||
|
if ($el === event.target || $el.contains(event.target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.closer(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.visible = false;
|
||||||
|
},
|
||||||
|
toggleVisible() {
|
||||||
|
if (this.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.visible = !this.visible;
|
||||||
|
this.$refs.input.focus();
|
||||||
|
},
|
||||||
|
childChange(data) {
|
||||||
|
this.colorChange(data);
|
||||||
|
},
|
||||||
|
colorChange(data, oldHue) {
|
||||||
|
this.oldHue = this.saturationColors.hsl.h;
|
||||||
|
this.saturationColors = changeColor(data, oldHue || this.oldHue);
|
||||||
|
},
|
||||||
|
closer(event) {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.visible = false;
|
||||||
|
this.$refs.input.focus();
|
||||||
|
},
|
||||||
|
handleButtons(event, value) {
|
||||||
|
this.currentValue = value;
|
||||||
|
this.$emit('input', value);
|
||||||
|
this.$emit('on-change', value);
|
||||||
|
this.dispatch('FormItem', 'on-form-change', value);
|
||||||
|
this.closer(event);
|
||||||
|
},
|
||||||
|
handleSuccess(event) {
|
||||||
|
this.handleButtons(event, this.formatColor);
|
||||||
|
this.$emit('on-pick-success');
|
||||||
|
},
|
||||||
|
handleClear(event) {
|
||||||
|
this.handleButtons(event, '');
|
||||||
|
this.$emit('on-pick-clear');
|
||||||
|
},
|
||||||
|
handleSelectColor(color) {
|
||||||
|
this.val = changeColor(color);
|
||||||
|
this.$emit('on-active-change', this.formatColor);
|
||||||
|
},
|
||||||
|
handleFirstTab(event) {
|
||||||
|
if (event.shiftKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
this.$refs.ok.$el.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
handleLastTab(event) {
|
||||||
value (newVal) {
|
if (!event.shiftKey) {
|
||||||
this.val = _colorChange(newVal);
|
event.preventDefault();
|
||||||
},
|
event.stopPropagation();
|
||||||
visible (val) {
|
this.$refs.saturation.$el.focus();
|
||||||
this.val = _colorChange(this.value);
|
|
||||||
if (val) {
|
|
||||||
this.$refs.drop.update();
|
|
||||||
} else {
|
|
||||||
this.$refs.drop.destroy();
|
|
||||||
}
|
|
||||||
this.$emit('on-open-change', Boolean(val));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
onTab(event) {
|
||||||
// 开启 transfer 时,点击 Drop 即会关闭,这里不让其关闭
|
if (this.visible) {
|
||||||
handleTransferClick () {
|
event.preventDefault();
|
||||||
if (this.transfer) this.disableCloseUnderTransfer = true;
|
|
||||||
},
|
|
||||||
handleClose () {
|
|
||||||
if (this.disableCloseUnderTransfer) {
|
|
||||||
this.disableCloseUnderTransfer = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.visible = false;
|
|
||||||
},
|
|
||||||
toggleVisible () {
|
|
||||||
this.visible = !this.visible;
|
|
||||||
},
|
|
||||||
childChange (data) {
|
|
||||||
this.colorChange(data);
|
|
||||||
},
|
|
||||||
colorChange (data, oldHue) {
|
|
||||||
this.oldHue = this.saturationColors.hsl.h;
|
|
||||||
this.saturationColors = _colorChange(data, oldHue || this.oldHue);
|
|
||||||
},
|
|
||||||
isValidHex (hex) {
|
|
||||||
return tinycolor(hex).isValid();
|
|
||||||
},
|
|
||||||
simpleCheckForValidColor (data) {
|
|
||||||
const keysToCheck = ['r', 'g', 'b', 'a', 'h', 's', 'l', 'v'];
|
|
||||||
let checked = 0;
|
|
||||||
let passed = 0;
|
|
||||||
|
|
||||||
for (let i = 0; i < keysToCheck.length; i++) {
|
|
||||||
const letter = keysToCheck[i];
|
|
||||||
if (data[letter]) {
|
|
||||||
checked++;
|
|
||||||
if (!isNaN(data[letter])) {
|
|
||||||
passed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checked === passed) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleSuccess () {
|
|
||||||
const color = this.formatColor;
|
|
||||||
this.currentValue = color;
|
|
||||||
this.$emit('input', color);
|
|
||||||
this.$emit('on-change', color);
|
|
||||||
this.dispatch('FormItem', 'on-form-change', color);
|
|
||||||
this.handleClose();
|
|
||||||
},
|
|
||||||
handleClear () {
|
|
||||||
this.currentValue = '';
|
|
||||||
this.$emit('input', '');
|
|
||||||
this.$emit('on-change', '');
|
|
||||||
this.dispatch('FormItem', 'on-form-change', '');
|
|
||||||
this.handleClose();
|
|
||||||
},
|
|
||||||
handleSelectColor (color) {
|
|
||||||
this.val = _colorChange(color);
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
onEscape(event) {
|
||||||
|
if (this.visible) {
|
||||||
|
this.closer(event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onArrow(event) {
|
||||||
|
if (!this.visible) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
this.visible = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
7
src/components/color-picker/handleEscapeMixin.js
Normal file
7
src/components/color-picker/handleEscapeMixin.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleEscape(e) {
|
||||||
|
this.dispatch('ColorPicker', 'on-escape-keydown', e);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
73
src/components/color-picker/hsaMixin.js
Normal file
73
src/components/color-picker/hsaMixin.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import Emitter from '../../mixins/emitter';
|
||||||
|
import handleEscapeMixin from './handleEscapeMixin';
|
||||||
|
import {getTouches} from './utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [Emitter, handleEscapeMixin],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
focused: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.unbindEventListeners();
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
if (this.focused) {
|
||||||
|
setTimeout(() => this.$el.focus(), 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleLeft(e) {
|
||||||
|
this.handleSlide(e, this.left, 'left');
|
||||||
|
},
|
||||||
|
handleRight(e) {
|
||||||
|
this.handleSlide(e, this.right, 'right');
|
||||||
|
},
|
||||||
|
handleUp(e) {
|
||||||
|
this.handleSlide(e, this.up, 'up');
|
||||||
|
},
|
||||||
|
handleDown(e) {
|
||||||
|
this.handleSlide(e, this.down, 'down');
|
||||||
|
},
|
||||||
|
handleMouseDown(e) {
|
||||||
|
this.dispatch('ColorPicker', 'on-dragging', true);
|
||||||
|
this.handleChange(e, true);
|
||||||
|
window.addEventListener('mousemove', this.handleChange, false);
|
||||||
|
window.addEventListener('mouseup', this.handleMouseUp, false);
|
||||||
|
},
|
||||||
|
handleMouseUp() {
|
||||||
|
this.unbindEventListeners();
|
||||||
|
},
|
||||||
|
unbindEventListeners() {
|
||||||
|
window.removeEventListener('mousemove', this.handleChange);
|
||||||
|
window.removeEventListener('mouseup', this.handleMouseUp);
|
||||||
|
// This timeout is required so that the click handler for click-outside
|
||||||
|
// has the chance to run before the mouseup removes the dragging flag.
|
||||||
|
setTimeout(() => this.dispatch('ColorPicker', 'on-dragging', false), 1);
|
||||||
|
},
|
||||||
|
getLeft(e) {
|
||||||
|
const {container} = this.$refs;
|
||||||
|
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
||||||
|
const pageX = e.pageX || getTouches(e, 'PageX');
|
||||||
|
|
||||||
|
return pageX - xOffset;
|
||||||
|
},
|
||||||
|
getTop(e) {
|
||||||
|
const {container} = this.$refs;
|
||||||
|
const yOffset = container.getBoundingClientRect().top + window.pageYOffset;
|
||||||
|
const pageY = e.pageY || getTouches(e, 'PageY');
|
||||||
|
|
||||||
|
return pageY - yOffset;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,86 +1,95 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ivu-color-picker-hue">
|
<div
|
||||||
<div class="ivu-color-picker-hue-container" ref="container"
|
:class="[prefixCls + '-hue']"
|
||||||
@mousedown="handleMouseDown"
|
tabindex="0"
|
||||||
@touchmove="handleChange"
|
@click="$el.focus()"
|
||||||
@touchstart="handleChange">
|
@keydown.esc="handleEscape"
|
||||||
<div class="ivu-color-picker-hue-pointer" :style="{top: 0, left: pointerLeft}">
|
@keydown.left="handleLeft"
|
||||||
<div class="ivu-color-picker-hue-picker"></div>
|
@keydown.right="handleRight"
|
||||||
|
@keydown.up="handleUp"
|
||||||
|
@keydown.down="handleDown"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
ref="container"
|
||||||
|
:class="[prefixCls + '-hue-container']"
|
||||||
|
@mousedown="handleMouseDown"
|
||||||
|
@touchmove="handleChange"
|
||||||
|
@touchstart="handleChange">
|
||||||
|
<div
|
||||||
|
:style="{top: 0, left: `${percent}%`}"
|
||||||
|
:class="[prefixCls + '-hue-pointer']">
|
||||||
|
<div :class="[prefixCls + '-hue-picker']"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import HASMixin from './hsaMixin';
|
||||||
name: 'Hue',
|
import Prefixes from './prefixMixin';
|
||||||
props: {
|
import {clamp} from './utils';
|
||||||
value: Object
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
oldHue: 0,
|
|
||||||
pullDirection: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
colors () {
|
|
||||||
const h = this.value.hsl.h;
|
|
||||||
if (h !== 0 && h - this.oldHue > 0) this.pullDirection = 'right';
|
|
||||||
if (h !== 0 && h - this.oldHue < 0) this.pullDirection = 'left';
|
|
||||||
this.oldHue = h;
|
|
||||||
|
|
||||||
return this.value;
|
export default {
|
||||||
},
|
name: 'Hue',
|
||||||
pointerLeft () {
|
|
||||||
if (this.colors.hsl.h === 0 && this.pullDirection === 'right') return '100%';
|
mixins: [HASMixin, Prefixes],
|
||||||
return (this.colors.hsl.h * 100) / 360 + '%';
|
|
||||||
|
data() {
|
||||||
|
const normalStep = 1 / 360 * 25;
|
||||||
|
const jumpStep = 20 * normalStep;
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: -normalStep,
|
||||||
|
right: normalStep,
|
||||||
|
up: jumpStep,
|
||||||
|
down: -jumpStep,
|
||||||
|
powerKey: 'shiftKey',
|
||||||
|
percent: clamp(this.value.hsl.h * 100 / 360, 0, 100),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
change(percent) {
|
||||||
|
this.percent = clamp(percent, 0, 100);
|
||||||
|
|
||||||
|
const {h, s, l, a} = this.value.hsl;
|
||||||
|
const newHue = clamp(percent / 100 * 360, 0, 360);
|
||||||
|
|
||||||
|
if (h !== newHue) {
|
||||||
|
this.$emit('change', {h: newHue, s, l, a, source: 'hsl'});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
handleSlide(e, direction) {
|
||||||
handleChange (e, skip) {
|
e.preventDefault();
|
||||||
!skip && e.preventDefault();
|
e.stopPropagation();
|
||||||
|
|
||||||
const container = this.$refs.container;
|
if (e[this.powerKey]) {
|
||||||
const containerWidth = container.clientWidth;
|
this.change(direction < 0 ? 0 : 100);
|
||||||
|
return;
|
||||||
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
|
||||||
const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0);
|
|
||||||
const left = pageX - xOffset;
|
|
||||||
|
|
||||||
let h;
|
|
||||||
let percent;
|
|
||||||
|
|
||||||
if (left < 0) {
|
|
||||||
h = 0;
|
|
||||||
} else if (left > containerWidth) {
|
|
||||||
h = 360;
|
|
||||||
} else {
|
|
||||||
percent = left * 100 / containerWidth;
|
|
||||||
h = (360 * percent / 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.colors.hsl.h !== h) {
|
|
||||||
this.$emit('change', {
|
|
||||||
h: h,
|
|
||||||
s: this.colors.hsl.s,
|
|
||||||
l: this.colors.hsl.l,
|
|
||||||
a: this.colors.hsl.a,
|
|
||||||
source: 'hsl'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleMouseDown (e) {
|
|
||||||
this.handleChange(e, true);
|
|
||||||
window.addEventListener('mousemove', this.handleChange);
|
|
||||||
window.addEventListener('mouseup', this.handleMouseUp);
|
|
||||||
},
|
|
||||||
handleMouseUp () {
|
|
||||||
this.unbindEventListeners();
|
|
||||||
},
|
|
||||||
unbindEventListeners () {
|
|
||||||
window.removeEventListener('mousemove', this.handleChange);
|
|
||||||
window.removeEventListener('mouseup', this.handleMouseUp);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
this.change(this.percent + direction);
|
||||||
</script>
|
},
|
||||||
|
handleChange(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const left = this.getLeft(e);
|
||||||
|
|
||||||
|
if (left < 0) {
|
||||||
|
this.change(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {clientWidth} = this.$refs.container;
|
||||||
|
|
||||||
|
if (left > clientWidth) {
|
||||||
|
this.change(100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.change(left * 100 / clientWidth);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
import ColorPicker from './color-picker.vue';
|
import ColorPicker from './color-picker.vue';
|
||||||
export default ColorPicker;
|
|
||||||
|
export default ColorPicker;
|
||||||
|
|
10
src/components/color-picker/prefixMixin.js
Normal file
10
src/components/color-picker/prefixMixin.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
prefixCls: 'ivu-color-picker',
|
||||||
|
inputPrefixCls: 'ivu-input',
|
||||||
|
iconPrefixCls: 'ivu-icon',
|
||||||
|
transferPrefixCls: 'ivu-transfer',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,20 +1,153 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div
|
||||||
|
ref="reference"
|
||||||
|
tabindex="0"
|
||||||
|
@click="handleClick"
|
||||||
|
@keydown.esc="handleEscape"
|
||||||
|
@keydown.enter="handleEnter"
|
||||||
|
@keydown.left="handleArrow($event, 'x', left)"
|
||||||
|
@keydown.right="handleArrow($event, 'x', right)"
|
||||||
|
@keydown.up="handleArrow($event, 'y', up)"
|
||||||
|
@keydown.down="handleArrow($event, 'y', down)"
|
||||||
|
@blur="blurColor"
|
||||||
|
@focus="focusColor"
|
||||||
|
>
|
||||||
<template v-for="(item, index) in list">
|
<template v-for="(item, index) in list">
|
||||||
<span @click="handleClick(index)"><em :style="{'background': item}"></em></span>
|
<div
|
||||||
<br v-if="(index + 1) % 12 === 0 && index !== 0 && (index + 1) !== list.length">
|
:key="item + ':' + index"
|
||||||
|
:class="[prefixCls + '-picker-colors-wrapper']">
|
||||||
|
<div :data-color-id="index">
|
||||||
|
<div
|
||||||
|
:style="{background: item}"
|
||||||
|
:class="[prefixCls + '-picker-colors-wrapper-color']"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
:ref="'color-circle-' + index"
|
||||||
|
:class="[prefixCls + '-picker-colors-wrapper-circle', hideClass]"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br v-if="lineBreak(list, index)">
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import Emitter from '../../mixins/emitter';
|
||||||
props: {
|
import HandleEscapeMixin from './handleEscapeMixin';
|
||||||
list: Array
|
import Prefixes from './prefixMixin';
|
||||||
|
import {clamp} from './utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'RecommendedColors',
|
||||||
|
|
||||||
|
mixins: [Emitter, HandleEscapeMixin, Prefixes],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: undefined,
|
||||||
},
|
},
|
||||||
methods: {
|
},
|
||||||
handleClick (index) {
|
|
||||||
this.$emit('picker-color', this.list[index]);
|
data() {
|
||||||
|
const columns = 12;
|
||||||
|
const rows = Math.ceil(this.list.length / columns);
|
||||||
|
const normalStep = 1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: -normalStep,
|
||||||
|
right: normalStep,
|
||||||
|
up: -normalStep,
|
||||||
|
down: normalStep,
|
||||||
|
powerKey: 'shiftKey',
|
||||||
|
grid: {x: 1, y: 1},
|
||||||
|
rows,
|
||||||
|
columns,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hideClass() {
|
||||||
|
return `${this.prefixCls}-hide`;
|
||||||
|
},
|
||||||
|
linearIndex() {
|
||||||
|
return this.getLinearIndex(this.grid);
|
||||||
|
},
|
||||||
|
currentCircle() {
|
||||||
|
return this.$refs[`color-circle-${this.linearIndex}`][0];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getLinearIndex(grid) {
|
||||||
|
return this.columns * (grid.y - 1) + grid.x - 1;
|
||||||
|
},
|
||||||
|
getMaxLimit(axis) {
|
||||||
|
return axis === 'x' ? this.columns : this.rows;
|
||||||
|
},
|
||||||
|
handleArrow(e, axis, direction) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.blurColor();
|
||||||
|
|
||||||
|
const grid = {...this.grid};
|
||||||
|
|
||||||
|
if (e[this.powerKey]) {
|
||||||
|
if (direction < 0) {
|
||||||
|
grid[axis] = 1;
|
||||||
|
} else {
|
||||||
|
grid[axis] = this.getMaxLimit(axis);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
grid[axis] += direction;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
const index = this.getLinearIndex(grid);
|
||||||
</script>
|
|
||||||
|
if (index >= 0 && index < this.list.length) {
|
||||||
|
this.grid[axis] = clamp(grid[axis], 1, this.getMaxLimit(axis));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.focusColor();
|
||||||
|
},
|
||||||
|
blurColor() {
|
||||||
|
this.currentCircle.classList.add(this.hideClass);
|
||||||
|
},
|
||||||
|
focusColor() {
|
||||||
|
this.currentCircle.classList.remove(this.hideClass);
|
||||||
|
},
|
||||||
|
handleEnter(e) {
|
||||||
|
this.handleClick(e, this.currentCircle);
|
||||||
|
},
|
||||||
|
handleClick(e, circle) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.$refs.reference.focus();
|
||||||
|
|
||||||
|
const target = circle || e.target;
|
||||||
|
const colorId = target.dataset.colorId || target.parentElement.dataset.colorId;
|
||||||
|
|
||||||
|
if (colorId) {
|
||||||
|
this.blurColor();
|
||||||
|
const id = Number(colorId) + 1;
|
||||||
|
this.grid.x = id % this.columns || this.columns;
|
||||||
|
this.grid.y = Math.ceil(id / this.columns);
|
||||||
|
this.focusColor();
|
||||||
|
this.$emit('picker-color', this.list[colorId]);
|
||||||
|
this.$emit('change', {hex: this.list[colorId], source: 'hex'});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lineBreak(list, index) {
|
||||||
|
if (!index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextIndex = index + 1;
|
||||||
|
|
||||||
|
return nextIndex < list.length && nextIndex % this.columns === 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
|
@ -1,98 +1,98 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ivu-color-picker-saturation-wrapper">
|
<div
|
||||||
|
:class="[prefixCls + '-saturation-wrapper']"
|
||||||
|
tabindex="0"
|
||||||
|
@keydown.esc="handleEscape"
|
||||||
|
@click="$el.focus()"
|
||||||
|
@keydown.left="handleLeft"
|
||||||
|
@keydown.right="handleRight"
|
||||||
|
@keydown.up="handleUp"
|
||||||
|
@keydown.down="handleDown"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="ivu-color-picker-saturation"
|
|
||||||
:style="{background: bgColor}"
|
|
||||||
ref="container"
|
ref="container"
|
||||||
|
:style="bgColorStyle"
|
||||||
|
:class="[prefixCls + '-saturation']"
|
||||||
@mousedown="handleMouseDown">
|
@mousedown="handleMouseDown">
|
||||||
<div class="ivu-color-picker-saturation--white"></div>
|
<div :class="[prefixCls + '-saturation--white']"></div>
|
||||||
<div class="ivu-color-picker-saturation--black"></div>
|
<div :class="[prefixCls + '-saturation--black']"></div>
|
||||||
<div class="ivu-color-picker-saturation-pointer" :style="{top: pointerTop, left: pointerLeft}">
|
<div
|
||||||
<div class="ivu-color-picker-saturation-circle"></div>
|
:style="pointerStyle"
|
||||||
|
:class="[prefixCls + '-saturation-pointer']">
|
||||||
|
<div :class="[prefixCls + '-saturation-circle']"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
import throttle from 'lodash.throttle';
|
|
||||||
|
|
||||||
export default {
|
<script>
|
||||||
name: 'Saturation',
|
import HSAMixin from './hsaMixin';
|
||||||
props: {
|
import Prefixes from './prefixMixin';
|
||||||
value: Object
|
import {clamp, getIncrement} from './utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Saturation',
|
||||||
|
|
||||||
|
mixins: [HSAMixin, Prefixes],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
const normalStep = 0.01;
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: -normalStep,
|
||||||
|
right: normalStep,
|
||||||
|
up: normalStep,
|
||||||
|
down: -normalStep,
|
||||||
|
multiplier: 10,
|
||||||
|
powerKey: 'shiftKey',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
bgColorStyle() {
|
||||||
|
return {background: `hsl(${this.value.hsv.h}, 100%, 50%)`};
|
||||||
},
|
},
|
||||||
data () {
|
pointerStyle() {
|
||||||
return {};
|
return {top: `${-(this.value.hsv.v * 100) + 1 + 100}%`, left: `${this.value.hsv.s * 100}%`};
|
||||||
},
|
},
|
||||||
computed: {
|
},
|
||||||
colors () {
|
|
||||||
return this.value;
|
methods: {
|
||||||
},
|
change(h, s, v, a) {
|
||||||
bgColor () {
|
this.$emit('change', {h, s, v, a, source: 'hsva'});
|
||||||
return `hsl(${this.colors.hsv.h}, 100%, 50%)`;
|
|
||||||
},
|
|
||||||
pointerTop () {
|
|
||||||
return (-(this.colors.hsv.v * 100) + 1) + 100 + '%';
|
|
||||||
},
|
|
||||||
pointerLeft () {
|
|
||||||
return this.colors.hsv.s * 100 + '%';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
handleSlide(e, direction, key) {
|
||||||
throttle: throttle((fn, data) => {fn(data);}, 20,
|
e.preventDefault();
|
||||||
{
|
e.stopPropagation();
|
||||||
'leading': true,
|
|
||||||
'trailing': false
|
const isPowerKey = e[this.powerKey];
|
||||||
}),
|
const increment = isPowerKey ? direction * this.multiplier : direction;
|
||||||
handleChange (e, skip) {
|
const {h, s, v, a} = this.value.hsv;
|
||||||
!skip && e.preventDefault();
|
const saturation = clamp(s + getIncrement(key, ['left', 'right'], increment), 0, 1);
|
||||||
const container = this.$refs.container;
|
const bright = clamp(v + getIncrement(key, ['up', 'down'], increment), 0, 1);
|
||||||
const containerWidth = container.clientWidth;
|
|
||||||
const containerHeight = container.clientHeight;
|
this.change(h, saturation, bright, a);
|
||||||
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
},
|
||||||
const yOffset = container.getBoundingClientRect().top + window.pageYOffset;
|
handleChange(e) {
|
||||||
const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0);
|
e.preventDefault();
|
||||||
const pageY = e.pageY || (e.touches ? e.touches[0].pageY : 0);
|
e.stopPropagation();
|
||||||
let left = pageX - xOffset;
|
|
||||||
let top = pageY - yOffset;
|
const {clientWidth, clientHeight} = this.$refs.container;
|
||||||
if (left < 0) {
|
const left = clamp(this.getLeft(e), 0, clientWidth);
|
||||||
left = 0;
|
const top = clamp(this.getTop(e), 0, clientHeight);
|
||||||
} else if (left > containerWidth) {
|
const saturation = left / clientWidth;
|
||||||
left = containerWidth;
|
const bright = clamp(1 - top / clientHeight, 0, 1);
|
||||||
} else if (top < 0) {
|
|
||||||
top = 0;
|
this.change(this.value.hsv.h, saturation, bright, this.value.hsv.a);
|
||||||
} else if (top > containerHeight) {
|
},
|
||||||
top = containerHeight;
|
handleMouseDown(e) {
|
||||||
}
|
HSAMixin.methods.handleMouseDown.call(this, e);
|
||||||
const saturation = left / containerWidth;
|
window.addEventListener('mouseup', this.handleChange, false);
|
||||||
let bright = -(top / containerHeight) + 1;
|
},
|
||||||
bright = bright > 0 ? bright : 0;
|
unbindEventListeners(e) {
|
||||||
bright = bright > 1 ? 1 : bright;
|
HSAMixin.methods.unbindEventListeners.call(this, e);
|
||||||
this.throttle(this.onChange, {
|
window.removeEventListener('mouseup', this.handleChange);
|
||||||
h: this.colors.hsv.h,
|
},
|
||||||
s: saturation,
|
},
|
||||||
v: bright,
|
};
|
||||||
a: this.colors.hsv.a,
|
</script>
|
||||||
source: 'hsva'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onChange (param) {
|
|
||||||
this.$emit('change', param);
|
|
||||||
},
|
|
||||||
handleMouseDown () {
|
|
||||||
// this.handleChange(e, true)
|
|
||||||
window.addEventListener('mousemove', this.handleChange);
|
|
||||||
window.addEventListener('mouseup', this.handleChange);
|
|
||||||
window.addEventListener('mouseup', this.handleMouseUp);
|
|
||||||
},
|
|
||||||
handleMouseUp () {
|
|
||||||
this.unbindEventListeners();
|
|
||||||
},
|
|
||||||
unbindEventListeners () {
|
|
||||||
window.removeEventListener('mousemove', this.handleChange);
|
|
||||||
window.removeEventListener('mouseup', this.handleChange);
|
|
||||||
window.removeEventListener('mouseup', this.handleMouseUp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
118
src/components/color-picker/utils.js
Normal file
118
src/components/color-picker/utils.js
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import tinycolor from 'tinycolor2';
|
||||||
|
import {oneOf} from '../../utils/assist';
|
||||||
|
|
||||||
|
function setAlpha(data, alpha) {
|
||||||
|
const color = tinycolor(data);
|
||||||
|
const {_a} = color;
|
||||||
|
|
||||||
|
if (_a === undefined || _a === null) {
|
||||||
|
color.setAlpha(alpha || 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColor(data, colorData) {
|
||||||
|
const alpha = colorData && colorData.a;
|
||||||
|
|
||||||
|
if (colorData) {
|
||||||
|
// hsl is better than hex between conversions
|
||||||
|
if (colorData.hsl) {
|
||||||
|
return setAlpha(colorData.hsl, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorData.hex && colorData.hex.length > 0) {
|
||||||
|
return setAlpha(colorData.hex, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return setAlpha(colorData, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function changeColor(data, oldHue) {
|
||||||
|
const colorData = data === '' ? '#2d8cf0' : data;
|
||||||
|
const color = getColor(data, colorData);
|
||||||
|
const hsl = color.toHsl();
|
||||||
|
const hsv = color.toHsv();
|
||||||
|
|
||||||
|
if (hsl.s === 0) {
|
||||||
|
hsl.h = colorData.h || (colorData.hsl && colorData.hsl.h) || oldHue || 0;
|
||||||
|
hsv.h = hsl.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when the hsv.v is less than 0.0164 (base on test)
|
||||||
|
// because of possible loss of precision
|
||||||
|
// the result of hue and saturation would be miscalculated
|
||||||
|
if (hsv.v < 0.0164) {
|
||||||
|
hsv.h = colorData.h || (colorData.hsv && colorData.hsv.h) || 0;
|
||||||
|
hsv.s = colorData.s || (colorData.hsv && colorData.hsv.s) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hsl.l < 0.01) {
|
||||||
|
hsl.h = colorData.h || (colorData.hsl && colorData.hsl.h) || 0;
|
||||||
|
hsl.s = colorData.s || (colorData.hsl && colorData.hsl.s) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hsl,
|
||||||
|
hex: color.toHexString().toUpperCase(),
|
||||||
|
rgba: color.toRgb(),
|
||||||
|
hsv,
|
||||||
|
oldHue: colorData.h || oldHue || hsl.h,
|
||||||
|
source: colorData.source,
|
||||||
|
a: colorData.a || color.getAlpha(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clamp(value, min, max) {
|
||||||
|
if (value < min) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > max) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getIncrement(key, keys, increment) {
|
||||||
|
return oneOf(key, keys) ? increment : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTouches(e, prop) {
|
||||||
|
return e.touches ? e.touches[0][prop] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toRGBAString(rgba) {
|
||||||
|
const {r, g, b, a} = rgba;
|
||||||
|
|
||||||
|
return `rgba(${[r, g, b, a].join(',')})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isValidHex(hex) {
|
||||||
|
return tinycolor(hex).isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkIteratee(data, counts, letter) {
|
||||||
|
let {checked, passed} = counts;
|
||||||
|
const value = data[letter];
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
checked += 1;
|
||||||
|
|
||||||
|
if (Number.isFinite(value)) {
|
||||||
|
passed += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {checked, passed};
|
||||||
|
}
|
||||||
|
|
||||||
|
const keysToCheck = ['r', 'g', 'b', 'a', 'h', 's', 'l', 'v'];
|
||||||
|
|
||||||
|
export function simpleCheckForValidColor(data) {
|
||||||
|
const results = keysToCheck.reduce(checkIteratee.bind(null, data), {checked: 0, passed: 0});
|
||||||
|
|
||||||
|
return results.checked === results.passed ? data : undefined;
|
||||||
|
}
|
|
@ -1,103 +1,174 @@
|
||||||
@color-picker-prefix-cls: ~"@{css-prefix}color-picker";
|
@color-picker-prefix-cls: ~'@{css-prefix}color-picker';
|
||||||
|
|
||||||
.@{color-picker-prefix-cls} {
|
.@{color-picker-prefix-cls} {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
&-hide {
|
||||||
|
display: none;
|
||||||
|
&-drop {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-disabled {
|
||||||
|
background-color: @input-disabled-bg;
|
||||||
|
opacity: 1;
|
||||||
|
cursor: @cursor-disabled;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
& > div:first-child:hover {
|
||||||
|
.ivu-input {
|
||||||
|
border-color: @input-hover-border-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > div:first-child.@{color-picker-prefix-cls}-disabled:hover {
|
||||||
|
.ivu-input {
|
||||||
|
border-color: tint(@input-border-color, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
& .@{select-dropdown-prefix-cls} {
|
& .@{select-dropdown-prefix-cls} {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
&-rel{
|
&-focused {
|
||||||
|
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||||
|
}
|
||||||
|
&-rel {
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
}
|
}
|
||||||
&-color{
|
&-color {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
div{
|
div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
|
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
&-empty{
|
&-empty {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
i{
|
i {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&-focused {
|
||||||
|
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&-large &-color{
|
&-large &-color {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
&-empty{
|
&-empty {
|
||||||
i{
|
i {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&-small &-color{
|
&-small &-color {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
top: 3px;
|
top: 3px;
|
||||||
&-empty{
|
&-empty {
|
||||||
i{
|
i {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-picker{
|
&-picker {
|
||||||
&-wrapper{
|
&-wrapper {
|
||||||
padding: 8px 8px 0;
|
padding: 8px 8px 0;
|
||||||
}
|
}
|
||||||
&-panel{
|
&-panel {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
box-sizing: initial;
|
box-sizing: initial;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
&-hue-slider, &-alpha-slider{
|
&-hue-slider,
|
||||||
|
&-alpha-slider {
|
||||||
height: 10px;
|
height: 10px;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
&-colors{
|
&-colors {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
span{
|
outline: 0;
|
||||||
display: inline-block;
|
border: 1px solid @input-border-color;
|
||||||
|
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid @input-hover-border-color;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||||
|
}
|
||||||
|
&-wrapper {
|
||||||
|
display: inline;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
float: left;
|
float: left;
|
||||||
em{
|
position: relative;
|
||||||
|
&-color {
|
||||||
|
outline: 0;
|
||||||
display: block;
|
display: block;
|
||||||
|
position: absolute;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
|
border: 1px solid @input-border-color;
|
||||||
|
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid @input-hover-border-color;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-circle {
|
||||||
|
cursor: pointer;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
position: absolute;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
box-shadow: 0 0 0 1.5px #fff, inset 0 0 1px 1px rgba(0, 0, 0, 0.3), 0 0 1px 2px rgba(0, 0, 0, 0.4);
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translate(-2px, -2px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.@{picker-prefix-cls}-confirm{
|
.@{picker-prefix-cls}-confirm {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-saturation{
|
&-saturation {
|
||||||
&-wrapper{
|
&-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-bottom: 75%;
|
padding-bottom: 75%;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
outline: 0;
|
||||||
|
border: 1px solid @input-border-color;
|
||||||
|
box-shadow: @shadow-base;
|
||||||
|
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid @input-hover-border-color;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&, &--white, &--black{
|
&,
|
||||||
|
&--white,
|
||||||
|
&--black {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -105,26 +176,26 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
&--white{
|
&--white {
|
||||||
background: linear-gradient(to right, #fff, rgba(255,255,255,0));
|
background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
|
||||||
}
|
}
|
||||||
&--black{
|
&--black {
|
||||||
background: linear-gradient(to top, #000, rgba(0,0,0,0));
|
background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
&-pointer{
|
&-pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
&-circle{
|
&-circle {
|
||||||
width: 4px;
|
width: 4px;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
box-shadow: 0 0 0 1.5px #fff, inset 0 0 1px 1px rgba(0,0,0,.3), 0 0 1px 2px rgba(0,0,0,.4);
|
box-shadow: 0 0 0 1.5px #fff, inset 0 0 1px 1px rgba(0, 0, 0, 0.3), 0 0 1px 2px rgba(0, 0, 0, 0.4);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transform: translate(-2px, -2px);
|
transform: translate(-2px, -2px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-hue{
|
&-hue {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -132,35 +203,55 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
|
background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
|
||||||
&-container{
|
outline: 0;
|
||||||
|
border: 1px solid @input-border-color;
|
||||||
|
box-shadow: @shadow-base;
|
||||||
|
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid @input-hover-border-color;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||||
|
}
|
||||||
|
&-container {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
&-pointer{
|
&-pointer {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
&-picker{
|
&-picker {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
width: 4px;
|
width: 4px;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, .6);
|
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
transform: translateX(-2px);
|
transform: translateX(-2px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-alpha{
|
&-alpha {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
&-checkboard-wrap{
|
outline: 0;
|
||||||
|
border: 1px solid @input-border-color;
|
||||||
|
box-shadow: @shadow-base;
|
||||||
|
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid @input-hover-border-color;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||||
|
}
|
||||||
|
&-checkboard-wrap {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -169,7 +260,7 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
&-checkerboard{
|
&-checkerboard {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -177,7 +268,7 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||||
}
|
}
|
||||||
&-gradient{
|
&-gradient {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -185,32 +276,37 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
&-container{
|
&-container {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0 3px;
|
margin: 0 3px;
|
||||||
}
|
}
|
||||||
&-pointer{
|
&-pointer {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
&-picker{
|
&-picker {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 4px;
|
width: 4px;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, .6);
|
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
transform: translateX(-2px);
|
transform: translateX(-2px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-confirm{
|
&-confirm {
|
||||||
|
margin-top: 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
&-color{
|
border-top: 1px solid @border-color-split;
|
||||||
|
text-align: right;
|
||||||
|
padding: 8px;
|
||||||
|
clear: both;
|
||||||
|
&-color {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 11px;
|
top: 11px;
|
||||||
left: 8px;
|
left: 8px;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.active(@color: @input-hover-border-color) {
|
.active(@color: @input-hover-border-color) {
|
||||||
border-color: tint(@color, 20%);
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: 0 0 0 2px fade(@color, 20%);
|
box-shadow: 0 0 0 2px fade(@color, 20%);
|
||||||
}
|
}
|
||||||
|
@ -266,4 +265,4 @@
|
||||||
&-append {
|
&-append {
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue