Skip to content

颜色选择器 ColorPicker ​

赞助

用于选择和展示颜色

何时使用 ​

  • 当需要选择颜色或展示颜色时

基本使用 ​

Show Code
vue
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
const colorValue = ref('rgba(0, 0, 0, 1)')
watchEffect(() => {
  console.log('colorValue', colorValue.value)
})
</script>
<template>
  <ColorPicker :width="240" v-model:value="colorValue" />
</template>

不透明度 ​

showAlpha 控制是否可调节 alpha 通道


showAlpha:
Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const showAlpha = ref(false)
</script>
<template>
  <Space vertical>
    <Space align="center"> showAlpha: <Switch v-model:value="showAlpha"></Switch> </Space>
    <ColorPicker :width="240" default-value="#ff6900" :show-alpha="showAlpha" />
  </Space>
</template>

尺寸 ​

Show Code
vue
<template>
  <Space vertical>
    <ColorPicker :width="240" size="small" />
    <ColorPicker :width="240" />
    <ColorPicker :width="240" size="large" />
  </Space>
</template>

禁用 ​

Show Code
vue
<template>
  <ColorPicker :width="240" default-value="#ff6900" disabled />
</template>

设定模式 ​

使用 modes 设定可选的颜色格式


modes:
Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { CheckboxGroupOption } from 'vue-amazing-ui'
const modeOptions: CheckboxGroupOption[] = [
  {
    label: 'rgb',
    value: 'rgb'
  },
  {
    label: 'hex',
    value: 'hex'
  },
  {
    label: 'hsl',
    value: 'hsl'
  },
  {
    label: 'hsv',
    value: 'hsv'
  }
]
const modes = ref(['rgb', 'hex'])
</script>
<template>
  <Space vertical>
    <Space align="center"> modes: <CheckboxGroup :options="modeOptions" v-model:value="modes" /> </Space>
    <ColorPicker :width="240" default-value="#ff6900" :modes="modes" />
  </Space>
</template>

显示按钮 ​

在 actions 属性中添加 confirm / clear,即可显示对应的确认 / 清除按钮


actions:
Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { CheckboxGroupOption } from 'vue-amazing-ui'
const actionOptions: CheckboxGroupOption[] = [
  {
    label: 'confirm',
    value: 'confirm'
  },
  {
    label: 'clear',
    value: 'clear'
  }
]
const actions = ref(['confirm', 'clear'])
function handleComplete(color: string) {
  console.log('complete', color)
}
function handleConfirm(color: string) {
  console.log('confirm', color)
}
function handleClear() {
  console.log('clear')
}
</script>
<template>
  <Space vertical>
    <Space align="center"> actions: <CheckboxGroup :options="actionOptions" v-model:value="actions" /> </Space>
    <ColorPicker
      :width="240"
      default-value="#ff6900"
      :actions="actions"
      @complete="handleComplete"
      @confirm="handleConfirm"
      @clear="handleClear"
    />
  </Space>
</template>

预设色板 ​

使用 swatches 设置预设色板,色板支持鼠标点击与键盘 Enter 选色


Show Code
vue
<script setup lang="ts">
const swatches = [
  '#FFFFFF',
  '#F0A020',
  '#1677ff',
  '#ff6900',
  '#722ed1',
  '#13c2c2',
  'rgba(0, 0, 0, 0.88)',
  'rgba(208, 48, 80, 1)'
]
function handleUpdateValue(color: string) {
  console.log('update:value', color)
}
</script>
<template>
  <ColorPicker :width="240" default-value="#ff6900" :swatches="swatches" @update:value="handleUpdateValue" />
</template>

自定义触发器 ​

使用 trigger 插槽自定义触发器(点击开合、面板定位与外点判定均由组件接管,程序化开合请用 v-model:open)


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import { BgColorsOutlined } from '@ant-design/icons-vue'
const triggerColor1 = ref('#ff6900')
const triggerColor2 = ref('#1677ff')
const triggerColor3 = ref('#722ed1')
function handleComplete(color: string) {
  console.log('complete', color)
}
</script>
<template>
  <Space align="center">
    <ColorPicker v-model:value="triggerColor1" @complete="handleComplete">
      <template #trigger="{ value }">
        <Button shape="circle" type="text">
          <template #icon>
            <BgColorsOutlined :style="{ color: value }" />
          </template>
        </Button>
      </template>
    </ColorPicker>
    <ColorPicker v-model:value="triggerColor2" @complete="handleComplete">
      <template #trigger="{ value }">
        <span
          class="trigger-dot"
          :style="`background-color: ${value || '#000000'}`"
        ></span>
      </template>
    </ColorPicker>
    <ColorPicker v-model:value="triggerColor3" @complete="handleComplete">
      <template #trigger="{ value }">
        <span class="trigger-text" :style="`color: ${value}`">{{ value }}</span>
      </template>
    </ColorPicker>
  </Space>
</template>

颜色预览块 ​

使用 showPreview 控制预览块显隐;点击预览块可唤起浏览器原生取色器


showPreview:
Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const showPreview = ref(true)
function handleUpdateValue(color: string) {
  console.log('update:value', color)
}
</script>
<template>
  <Space vertical>
    <Space align="center"> showPreview: <Switch v-model:value="showPreview"></Switch> </Space>
    <ColorPicker :width="240" default-value="#ff6900" :show-preview="showPreview" @update:value="handleUpdateValue" />
  </Space>
</template>

弹出位置 ​

使用 placement 设置面板的弹出位置(默认 bottomLeft);offset 控制面板与触发器的主轴间距,默认 6


placement:
bottomLeft
bottom
bottomRight
right
topRight
top
topLeft
left
offset:
Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { ColorPickerProps } from 'vue-amazing-ui'
type Placement = NonNullable<ColorPickerProps['placement']>
const placement = ref<Placement>('bottomLeft')
const offset = ref(6)
// 8 档顺时针(四角 + 四边):覆盖主要方位;标签用真实枚举值,便于直接照抄
const placementOptions: { label: string; value: Placement }[] = [
  { label: 'bottomLeft', value: 'bottomLeft' },
  { label: 'bottom', value: 'bottom' },
  { label: 'bottomRight', value: 'bottomRight' },
  { label: 'right', value: 'right' },
  { label: 'topRight', value: 'topRight' },
  { label: 'top', value: 'top' },
  { label: 'topLeft', value: 'topLeft' },
  { label: 'left', value: 'left' }
]
</script>
<template>
  <Space vertical>
    <Space align="center"> placement: <Segmented v-model:value="placement" :options="placementOptions" /> </Space>
    <Space align="center"> offset: <InputNumber v-model:value="offset" :min="0" :max="40" /> </Space>
    <ColorPicker :width="240" default-value="#ff6900" :placement="placement" :offset="offset" />
  </Space>
</template>

自定义展示内容 ​

通过 label 属性(可返回字符串或 VNode)或 label 插槽自定义展示内容


Show Code
vue
<script setup lang="ts">
import { ref, h } from 'vue'
const labelValue = ref('#ff6900')
function labelFormat(color: string) {
  return `hello ${color}`
}
function labelRender(color: string) {
  return h('span', { style: 'font-weight: 600' }, `HELLO ${color}`)
}
</script>
<template>
  <Space vertical>
    <ColorPicker :width="240" v-model:value="labelValue" :label="labelFormat" />
    <ColorPicker :width="240" v-model:value="labelValue" :label="labelRender" />
    <ColorPicker :width="240" v-model:value="labelValue">
      <template #label="{ color }">
        I'm {{ color }}
      </template>
    </ColorPicker>
  </Space>
</template>

自定义面板样式 ​

通过 panelStyle 设置面板样式、panelClass 自定义面板类名,两者均落在 Teleport 后的面板上;panelClass 的样式需写在全局样式中(scoped 样式无法命中),zIndex 用于覆盖面板层级(默认 1050)


Show Code
vue
<template>
  <Space align="center">
    <ColorPicker
      :width="240"
      :panel-style="{
        width: '280px',
        padding: '4px',
        borderRadius: '8px'
      }"
    />
    <ColorPicker :width="240" default-value="#ff6900" panel-class="custom-color-picker-panel" />
    <ColorPicker :width="240" default-value="#ff6900" :z-index="1100" />
  </Space>
</template>

<style lang="less">
/* 面板经 Teleport 挂载,scoped 样式无法命中,故用 panelClass 下发类名 + 全局样式 */
@demo-primary: #ff6900;

.custom-color-picker-panel {
  border: 1px solid @demo-primary;
  box-shadow: 0 8px 20px fade(@demo-primary, 25%);
}
</style>

额外页脚 ​

Show Code
vue
<template>
  <ColorPicker :width="240">
    <template #footer> extra footer </template>
  </ColorPicker>
</template>

受控展开 ​

使用 v-model:open 控制面板显隐;点击触发器、点击外部与 Esc 收起都会写回 open,openChange 同步派发展开状态的变化


显示
隐藏
Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const open = ref(false)
function handleOpenChange(value: boolean) {
  console.log('openChange', value)
}
</script>
<template>
  <Space align="center">
    <ColorPicker :width="240" default-value="#ff6900" v-model:open="open" @open-change="handleOpenChange" />
    <Button type="primary" :disabled="open" @click="open = true">显示</Button>
    <Button :disabled="!open" @click="open = false">隐藏</Button>
  </Space>
</template>

浮层挂载与卸载 ​

通过 to 指定面板挂载的容器(不传时优先挂到最近的承载层内容容器,无承载层时为 body;设为 false 时留在原地)

设置 destroyOnHide 后,面板在离开动画结束时卸载 DOM,再次展开时重新创建并定位,默认 false 时元素常驻、仅切换显隐。两者只改变挂载点与节点存亡,外观与交互一致,差异需在开发者工具中查看


to:
默认
留在原地
挂到示例容器
destroyOnHide:
Show Code
vue
<script setup lang="ts">
import { ref, computed } from 'vue'
type ToMode = 'auto' | 'false' | 'container'
const toMode = ref<ToMode>('auto')
const toOptions: { label: string; value: ToMode }[] = [
  { label: '默认', value: 'auto' },
  { label: '留在原地', value: 'false' },
  { label: '挂到示例容器', value: 'container' }
]
const destroyMode = ref(false)
const containerRef = ref<HTMLDivElement>()
// to 的三态映射:不传(默认承载层 / body)/ false(留在原地)/ 示例容器元素
const panelTo = computed(() => {
  const mode = toMode.value
  if (mode === 'false') return false
  if (mode === 'container') return containerRef.value
  return undefined
})
</script>
<template>
  <Space vertical>
    <Space align="center"> to: <Segmented v-model:value="toMode" :options="toOptions" /> </Space>
    <Space align="center"> destroyOnHide: <Switch v-model:value="destroyMode" /> </Space>
    <div
      ref="containerRef"
      style="display: inline-block; padding: 48px 24px; border-radius: 8px; border: 1px dashed #d9d9d9"
    >
      <ColorPicker :width="240" default-value="#ff6900" :to="panelTo" :destroy-on-hide="destroyMode" />
    </div>
  </Space>
</template>

APIs ​

ColorPicker Props ​

受控 / 非受控:value 与 open 传入即受控(值以父为准,组件只上报 update:value / update:open);不传则由组件自持,交互照常生效,可用 defaultValue / defaultOpen 指定初值。

名称说明类型默认值
value
v-model
颜色选择器的值;传入即受控,不传时组件自持(可用 defaultValue 指定初值)stringundefined
defaultValue非受控时的初始颜色值stringundefined
open
v-model
面板是否展开;传入即受控,不传时由组件内部维护booleanundefined
defaultOpen非受控时面板的初始显隐booleanfalse
label展示的内容,返回值同时支持字符串与 VNode(color: string) => VNodeChildundefined
swatches色板的值string[][]
footer底部额外的页脚内容stringundefined
modes颜色选择器支持颜色的格式ColorPickerMode[]['rgb', 'hex', 'hsl']
width颜色选择器的宽度,单位 px;仅内置触发器生效,使用 trigger 插槽自定义触发器时外壳随触发器内容自适应string | number'100%'
size颜色选择器的尺寸'small' | 'middle' | 'large''middle'
showAlpha是否可调节 alpha 通道booleantrue
showPreview是否展示颜色预览块booleanfalse
placement弹出面板的位置'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight' | 'left' | 'leftTop' | 'leftBottom' | 'right' | 'rightTop' | 'rightBottom''bottomLeft'
disabled是否禁用booleanfalse
actions显示按钮ColorPickerAction[][]
panelClass面板的类名(皮肤挂载点)stringundefined
panelStyle面板样式,在定位与层级之后合并CSSProperties{}
zIndex面板层级,优先级最高(未传时使用默认层级或 ConfigProvider 的 baseZIndex 分配)numberundefined
offset面板与触发器的主轴间距,单位 pxnumber6
destroyOnHide隐藏后是否卸载面板 DOM,再次展开时重新创建并重新定位booleanfalse
to弹出面板挂载的容器节点,可选:元素标签名 (例如 'body') 或者元素本身,false 会待在原地string | HTMLElement | falseundefined
inputProps输入框组件 props,参考 Input PropsInputProps{}

ColorPickerMode Type ​

名称值
ColorPickerMode'rgb' | 'hsl' | 'hsv' | 'hex'

ColorPickerAction Type ​

名称值
ColorPickerAction'confirm' | 'clear'

Slots ​

名称说明用法
label自定义展示的内容v-slot:label="{ color }"
footer自定义底部额外的页脚内容v-slot:footer
trigger自定义触发器(点击开合、面板定位与外点判定均由组件接管,无需回传处理函数与 ref)v-slot:trigger="{ value }"

Events ​

名称说明类型
openChange面板展开状态改变时的回调(内部开合与受控 open 被外部改变都算状态变化,状态未变时不派发)(open: boolean) => void
complete颜色完成改变后的回调(输入框提交和鼠标拖动结束时触发;色板选色、点击清除、原生取色器选色不触发)(color: string) => void
confirm点击确认按钮的回调(color: string) => void
clear点击清除按钮的回调() => void

触发语义由组件接管:点击触发区开合、点击外部关闭、Esc 收起并把焦点交还触发区、Enter / Space 开合(与点击同语义,键盘开合为内置常开)。自定义触发器内容请渲染在外壳内部;若内容自行 @click.stop 吞掉点击,面板不会展开(可用受控 v-model:open 自行控制)。

Released under the MIT License.