自定义样式
示例
从零开始简易实现一个类 TDesign 的颜色选择器面板
vue
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import {
ColorFormats,
HSVA,
HSVColorAlphaSlider,
HSVColorBlock,
HSVColorGradientSlider,
HSVColorPalette,
tinyColor,
} from '@vrx/color-picker-kit'
const props = withDefaults(
defineProps<{
/**
* 结果值格式化
*/
format?: ColorFormats
/**
* 默认值
*/
defaultValue?: string
/**
* 是否禁用
*/
disabled?: boolean
}>(),
{
format: 'hex',
defaultValue: '#43E97B',
disabled: false,
}
)
/**
* 双向绑定的值
*/
const modelValue = defineModel<string>()
const controlValue = computed(() => modelValue.value ?? props.defaultValue)
const hsvValue = computed(() => {
const v = tinyColor(controlValue.value, {
format: props.format,
}).toHsv()
return {
...v,
s: v.s * 100,
v: v.v * 100,
}
})
/**
* 由于 hex 转 hsv 会丢失部分信息,导致拖拽时,色盘闪烁
* 这边实现的不是完全的 双向绑定
*/
const color = ref<HSVA>({
h: hsvValue.value.h,
s: hsvValue.value.s,
v: hsvValue.value.v,
a: hsvValue.value.a,
})
const handleChange = (e: HSVA) => {
color.value = e
}
const formatValue = computed(() => {
return tinyColor(color.value).toString(props.format)
})
watch(formatValue, (v) => {
modelValue.value = v
})
</script>
<template>
<div class="t-color-picker">
<HSVColorPalette prefix="t-color-picker" :color :disabled @change="handleChange" />
<div class="t-color-picker-control-wrapper">
<div class="t-color-picker-slider-group">
<HSVColorGradientSlider prefix="t-color-picker" :color :disabled @change="handleChange" />
<HSVColorAlphaSlider prefix="t-color-picker" :color :disabled @change="handleChange" />
</div>
<HSVColorBlock prefix="t-color-picker" :color :disabled />
</div>
</div>
</template>
scss
// 样式前缀
$prefix: t-color-picker;
// 拖拽组件颜色
$t-color-picker-dot: var(--vp-c-bg);
// 拖拽组件大小
$t-color-picker-dot-size: 18px;
// 颜色选择器横向选择器高度
$t-color-picker-slider-size: 8px;
// 颜色展示组件的圆角
$t-color-picker-block-rounded: 3px;
// 默认阴影颜色
$t-color-picker-shadow: 0 2px 8px #00000026;
.#{$prefix} {
width: 223px;
padding: 12px;
box-shadow: $t-color-picker-shadow;
border-radius: $t-color-picker-block-rounded;
// 用于展示选择颜色的方块
// 这层主要为了在具有透明度的颜色时,显示透明度网格
.#{$prefix}-block {
border-radius: $t-color-picker-block-rounded;
background-image: conic-gradient(
#0000000f 0 25%,
transparent 0 50%,
#0000000f 0 75%,
transparent 0
);
box-sizing: border-box;
background-size: 50% 50%;
width: 28px;
height: 28px;
}
// 用于展示选择颜色的方块
.#{$prefix}-block-inner {
border-radius: $t-color-picker-block-rounded;
width: 100%;
height: 100%;
}
// 颜色选择器可拖拽操作部分组件的样式
.#{$prefix}-dot {
box-sizing: border-box;
cursor: pointer;
z-index: 2;
border-radius: $t-color-picker-dot-size;
width: $t-color-picker-dot-size;
height: $t-color-picker-dot-size;
position: absolute;
left: 0;
box-shadow: $t-color-picker-shadow;
border: 2px solid $t-color-picker-dot;
}
// 颜色透明度调节组件的样式
.#{$prefix}-alpha-slider {
background-image: conic-gradient(
#0000000f 0 25%,
transparent 0 50%,
#0000000f 0 75%,
transparent 0
);
background-size: calc($t-color-picker-dot-size / 2) calc($t-color-picker-dot-size / 2);
border-radius: calc($t-color-picker-dot-size / 2);
}
// 横向百分比调节组件
.#{$prefix}-slider {
box-sizing: border-box;
border-radius: $t-color-picker-slider-size;
height: $t-color-picker-slider-size;
position: relative;
}
// 横向百分比调节组件拖拽部分
.#{$prefix}-slider-dot {
margin-left: calc(0px - ($t-color-picker-dot-size / 2));
top: calc(-1px - (($t-color-picker-dot-size - $t-color-picker-slider-size) / 2));
}
// hsv 颜色调节中 h 的调节组件
.#{$prefix}-gradient-slider {
background-image: linear-gradient(to right, red, #ff0, #0f0, #0ff, #00f, #f0f, red);
margin-bottom: 10px;
}
// hsv 颜色选择中 sv 颜色调节背景
.#{$prefix}-palette {
box-sizing: border-box;
position: relative;
overflow: hidden;
background-image: linear-gradient(0deg, #000, transparent), linear-gradient(90deg, #fff, #fff0);
border-radius: $t-color-picker-block-rounded;
height: 160px;
}
// hsv 颜色选择中 sv 颜色调节拖拽组件
.#{$prefix}-palette-dot {
margin-top: calc(0px - ($t-color-picker-dot-size / 2));
margin-left: calc(0px - ($t-color-picker-dot-size / 2));
top: 0;
}
.#{$prefix}-control-wrapper {
display: flex;
padding-top: 12px;
}
.#{$prefix}-slider-group {
flex: 1;
min-width: 0;
margin-right: 12px;
}
}