I. Component introduction
Website links: ColorPicker color picker | Element (gitee. IO).
ColorPicker ColorPicker component, used for color selection, supports a variety of color formats.
1.1 attributes
- ModelValue/V-model: string, binding color value;
- Color-format: String format of the color value, for example
hsl / hsv / hex / rgb
; - Show-alpha: Boolean whether transparency is supported. If true, a transparency slider is displayed. Default is false.
- Predefine: array type, predefined color list, default empty;
- Size: Indicates the string type. This parameter is optional
medium/small/mini
; - Disabled: Boolean. The default value is false.
- Popper-class: string, the class name of the dropdown box.
1.2 event
- “Change” : triggered when the color value changes
Second, source code analysis
2.1 the template
<template>
<! -- Use the el-popper component to display popup content -->
<el-popper
ref="popper"
v-model:visible="showPicker"
effect="light"
manual-mode
trigger="click"
:show-arrow="false"
:fallback-placements="['bottom', 'top', 'right', 'left']"
:offset="0"
transition="el-zoom-in-top"
:gpu-acceleration="false"
:popper-class="`el-color-picker__panel el-color-dropdown ${popperClass}`"
:stop-popper-mouse-event="false"
>
<! -- Popup content -->
<template #default>
<! -- click-outside command, close pop-up content when clicking on external area -->
<div v-click-outside="hide">
<div class="el-color-dropdown__main-wrapper">
<! -- Color slider, vertical -->
<! Note that the color attribute is not a color value, but an instance of color.
<hue-slider ref="hue" class="hue-slider" :color="color" vertical />
<! -- Color palette, Rectangle -->
<sv-panel ref="svPanel" :color="color" />
</div>
<! -- Transparency slider, Landscape -->
<alpha-slider v-if="showAlpha" ref="alpha" :color="color" />
<! -- Predefined color blocks -->
<predefine v-if="predefine" ref="predefine" :color="color" :colors="predefine" />
<! Color value input box, confirm/clear button -->
<div class="el-color-dropdown__btns">
<span class="el-color-dropdown__value">
<el-input
v-model="customInput"
:validate-event="false"
size="mini"
@keyup.enter="handleConfirm"
@blur="handleConfirm"
/>
</span>
<el-button
size="mini"
type="text"
class="el-color-dropdown__link-btn"
@click="clear"
>{{ t('el.colorpicker.clear') }}</el-button>
<el-button
plain
size="mini"
class="el-color-dropdown__btn"
@click="confirmValue"
>{{ t('el.colorpicker.confirm') }}</el-button>
</div>
</div>
</template>
<! -- Trigger content, permanent display -->
<template #trigger>
<div
:class="[ 'el-color-picker', colorDisabled ? 'is-disabled' : '', colorSize ? `el-color-picker--${colorSize}` : '' ]"
>
<! -- Disabled mask to disable clicks -->
<div v-if="colorDisabled" class="el-color-picker__mask"></div>
<div class="el-color-picker__trigger" @click="handleTrigger">
<! -- Current color display -->
<span class="el-color-picker__color" :class="{ 'is-alpha': showAlpha }">
<span
class="el-color-picker__color-inner"
:style="{ backgroundColor: displayedColor }"
></span>
<! -- if no value is selected, display as X -->
<span
v-if=! "" modelValue && ! showPanelColor"
class="el-color-picker__empty el-icon-close"
></span>
</span>
<! -- Down arrow -->
<span
v-show="modelValue || showPanelColor"
class="el-color-picker__icon el-icon-arrow-down"
></span>
</div>
</div>
</template>
</el-popper>
</template>
Copy the code
2.2 the script part
setup(props, { emit }) {
const ELEMENT = useGlobalConfig()
const elForm = inject(elFormKey, {} as ElFormContext)
const elFormItem = inject(elFormItemKey, {} as ElFormItemContext)
// The ref of the child component
const hue = ref(null)
const svPanel = ref(null)
const alpha = ref(null)
const popper = ref(null)
// data
// Color is a Class that defines some Color related properties and methods
const color = reactive(new Color({
enableAlpha: props.showAlpha,
format: props.colorFormat,
}))
const showPicker = ref(false)
const showPanelColor = ref(false)
const customInput = ref(' ')
// computed
// Calculate the property, the currently displayed color
const displayedColor = computed(() = > {
// If no value is passed and no color is selected, the display is transparent
if(! props.modelValue && ! showPanelColor.value) {return 'transparent'
}
// Otherwise, convert to RGB/rGBA form
return displayedRgb(color, props.showAlpha)
})
// Trigger size: the size passed in > the size of the form-item > the size of the global setting
const colorSize = computed(() = > {
return props.size || elFormItem.size || ELEMENT.size
})
// Whether to disable
const colorDisabled = computed(() = > {
return props.disabled || elForm.disabled
})
// The current color
const currentColor = computed(() = > {
return! props.modelValue && ! showPanelColor.value ?' ' : color.value
})
// watch
// Monitor changes in incoming values
watch(() = > props.modelValue, newVal= > {
// If the new value is null, trigger displays as X
if(! newVal) { showPanelColor.value =false
} else if(newVal && newVal ! == color.value) {// Call Color's fromString method to calculate the new Color
color.fromString(newVal)
}
})
// The current color changes
watch(() = > currentColor.value, val= > {
// The value of the color input box changes synchronously
customInput.value = val
// Emit events up
emit('active-change', val)
// showPanelColor.value = true
})
// Monitor color.value changes
watch(() = > color.value, () = > {
if(! props.modelValue && ! showPanelColor.value) { showPanelColor.value =true}})// methods
// Convert to RGB format that can be used as background-color
function displayedRgb(color, showAlpha) {
if(! (colorinstanceof Color)) {
throw Error('color should be instance of _color Class')}// Call Color's toRgb method
const { r, g, b } = color.toRgb()
return showAlpha
? `rgba(${r}.${g}.${b}.${color.get('alpha') / 100}) `
: `rgb(${r}.${g}.${b}) `
}
function setShowPicker(value) {
showPicker.value = value
}
/ / image stabilization
const debounceSetShowPicker = debounce(setShowPicker, 100)
// the v-click-outside response function closes the color selection box and resets the color value
function hide() {
debounceSetShowPicker(false)
resetColor()
}
// Reset the color value
function resetColor() {
nextTick(() = > {
if (props.modelValue) {
color.fromString(props.modelValue)
} else {
showPanelColor.value = false}})}// trigger click events
function handleTrigger() {
if (colorDisabled.value) return
// Show/do not show toggledebounceSetShowPicker(! showPicker.value) }// The blur/change event of the color value input box
function handleConfirm() {
// This triggers a color.value change, which triggers the watch method above
color.fromString(customInput.value)
}
// "OK" button event
function confirmValue() {
// The value is the current color.value
const value = color.value
/ / v - model
emit(UPDATE_MODEL_EVENT, value)
/ / change event
emit('change', value)
// When in form, the el.form.change event is emittedelFormItem.formItemMitt? .emit('el.form.change', value)
// Close the dialog box
debounceSetShowPicker(false)
// check if modelValue change, if not change, then reset color.
nextTick(() = > {
const newColor = new Color({
enableAlpha: props.showAlpha,
format: props.colorFormat,
})
newColor.fromString(props.modelValue)
if(! color.compare(newColor)) { resetColor() } }) }// Clear the color event
function clear() {
// Close the dialog box
debounceSetShowPicker(false)
// V-model change event
emit(UPDATE_MODEL_EVENT, null)
emit('change'.null)
if(props.modelValue ! = =null) { elFormItem.formItemMitt? .emit('el.form.change'.null)}// reset the color
resetColor()
}
onMounted(() = > {
// If there is an incoming value, it is initialized with the incoming value
if (props.modelValue) {
color.fromString(props.modelValue)
customInput.value = currentColor.value
}
})
// When displaying/hiding the popbox, call the update method of the subcomponent to set the data of the subcomponent
watch(() = > showPicker.value, () = > {
nextTick(() = >{ hue.value? .update() svPanel.value? .update() alpha.value? .update() }) })// Provide the current color value to the child component
provide<IUseOptions>(OPTIONS_KEY, {
currentColor,
})
},
Copy the code
2.3 conclusion:
- Color has a variety of formats, involving mutual conversion and other calculation methods used in the code
Color class
, defines the related properties and transformation calculation methods, instantiated in the parent componentColor
And pass the instantiation object as a parameter to the child component, which can call the instance’s method for calculation; The parent component listens to color.value and so on, forming linkage;