canvas-color-disc 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.cn.md +77 -11
- package/README.md +77 -11
- package/dist/canvas-color-disc.es.js +426 -104
- package/dist/canvas-color-disc.umd.js +1 -1
- package/dist/style.css +1 -1
- package/dist/vue3/canvas-color-disc.es.js +462 -116
- package/dist/vue3/canvas-color-disc.umd.js +1 -1
- package/dist/vue3/style.css +1 -1
- package/package.json +17 -7
- package/src/color.js +271 -0
- package/src/components/CanvasColorDisc.vue +495 -148
- package/src/index.d.ts +74 -0
- package/src/index.js +4 -4
- package/src/style.css +27 -0
- package/src/util.js +89 -129
package/README.cn.md
CHANGED
|
@@ -121,7 +121,22 @@ export default {
|
|
|
121
121
|
</script>
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
`v-model`
|
|
124
|
+
`v-model` 绑定的形状由 `format` 决定,父组件修改绑定值时色盘选择器会同步移动。
|
|
125
|
+
|
|
126
|
+
### 颜色格式
|
|
127
|
+
|
|
128
|
+
`format` 决定绑定值的形状(默认 `rgb`):
|
|
129
|
+
|
|
130
|
+
| format | 绑定值 | 示例 |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| `rgb` | `{ r, g, b }`,通道 0~255 | `{ r: 255, g: 0, b: 0 }` |
|
|
133
|
+
| `hex` | 字符串,支持 3/4/6/8 位 | `'#ff0000'` |
|
|
134
|
+
| `hsv` | `{ h, s, v }`,h 0~360、s/v 0~100 | `{ h: 0, s: 100, v: 100 }` |
|
|
135
|
+
| `hsl` | `{ h, s, l }`,h 0~360、s/l 0~100 | `{ h: 0, s: 100, l: 50 }` |
|
|
136
|
+
|
|
137
|
+
字符串一律按 hex 解析;对象会先按 `format` 解析,未指定 `format` 时按字段推断。
|
|
138
|
+
|
|
139
|
+
`alpha` 为 `true` 时额外读写 `a` 分量(0~1),hex 格式下输出 8 位(如 `#ff000080`)。色盘是二维的,本身不调节透明度与明度,这两项需要由外部控件或绑定值给出。
|
|
125
140
|
|
|
126
141
|
## API
|
|
127
142
|
|
|
@@ -129,30 +144,75 @@ export default {
|
|
|
129
144
|
|
|
130
145
|
| 参数 | 说明 | 类型 | 默认值 | 适用版本 |
|
|
131
146
|
| --- | --- | --- | --- | --- |
|
|
132
|
-
| value | 当前颜色,配合 `v-model` 使用 | Object
|
|
133
|
-
| modelValue | 当前颜色,配合 `v-model` 使用 | Object
|
|
134
|
-
| width | 画布宽度(CSS
|
|
135
|
-
| height | 画布高度(CSS
|
|
147
|
+
| value | 当前颜色,配合 `v-model` 使用 | Object / String | `{ r: 255, g: 255, b: 255 }` | Vue 2 |
|
|
148
|
+
| modelValue | 当前颜色,配合 `v-model` 使用 | Object / String | `undefined`(回退到 `value`) | Vue 3 |
|
|
149
|
+
| width | 画布宽度(CSS 像素),`'auto'` 表示跟随容器 | Number / String | 300 | 通用 |
|
|
150
|
+
| height | 画布高度(CSS 像素),`'auto'` 表示跟随容器 | Number / String | 300 | 通用 |
|
|
151
|
+
| format | 绑定值格式:`rgb` / `hex` / `hsv` / `hsl` | String | `rgb` | 通用 |
|
|
152
|
+
| alpha | 是否保留并输出 alpha 分量 | Boolean | `false` | 通用 |
|
|
153
|
+
| disabled | 禁用指针与键盘交互 | Boolean | `false` | 通用 |
|
|
154
|
+
| keyboardStep | 方向键步进(饱和度百分点 / 色相度数),按住 Shift 时 ×10 | Number | 1 | 通用 |
|
|
136
155
|
|
|
137
156
|
### Events
|
|
138
157
|
|
|
139
158
|
| 事件名 | 说明 | 回调参数 | 适用版本 |
|
|
140
159
|
| --- | --- | --- | --- |
|
|
141
|
-
| input | 颜色变化时实时触发(按帧节流,配合 `v-model`) | `
|
|
142
|
-
| update:modelValue | 同 `input`,配合 `v-model` 使用 | `
|
|
143
|
-
| change |
|
|
160
|
+
| input | 颜色变化时实时触发(按帧节流,配合 `v-model`) | 与 `format` 一致 | Vue 2 |
|
|
161
|
+
| update:modelValue | 同 `input`,配合 `v-model` 使用 | 与 `format` 一致 | Vue 3 |
|
|
162
|
+
| change | 一次选择(按下后抬起,或一次键盘调整)结束时触发 | 与 `format` 一致 | 通用 |
|
|
144
163
|
|
|
145
164
|
`input` 与 `update:modelValue` 会同时派发,未被监听的一方会被忽略。
|
|
146
165
|
|
|
166
|
+
### 插槽
|
|
167
|
+
|
|
168
|
+
| 名称 | 作用域参数 | 说明 |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| palette | `color`(当前颜色)、`setColor(value)` | 渲染在色盘下方的附加区域,常用于预设色板 |
|
|
171
|
+
|
|
172
|
+
```vue
|
|
173
|
+
<canvas-color-disc v-model="rgb">
|
|
174
|
+
<template #palette="{ setColor }">
|
|
175
|
+
<button @click="setColor({ r: 255, g: 0, b: 0 })">红</button>
|
|
176
|
+
</template>
|
|
177
|
+
</canvas-color-disc>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 实例方法
|
|
181
|
+
|
|
182
|
+
通过 `ref` 调用(Vue 3 下经由 `expose` 暴露,Vue 2 下直接从 `$refs` 取到):
|
|
183
|
+
|
|
184
|
+
| 方法 | 说明 |
|
|
185
|
+
| --- | --- |
|
|
186
|
+
| `getColor()` | 取当前颜色,对象格式为副本 |
|
|
187
|
+
| `setColor(value)` | 设置颜色,值需符合当前 `format`,非法值被忽略;会同时派发 `change` |
|
|
188
|
+
| `reset()` | 重置为白色 |
|
|
189
|
+
|
|
190
|
+
### 键盘操作
|
|
191
|
+
|
|
192
|
+
色盘的交互元素可被聚焦(`tabindex="0"`,带 `role="slider"` 与 `aria-valuetext`),聚焦后:
|
|
193
|
+
|
|
194
|
+
| 按键 | 行为 |
|
|
195
|
+
| --- | --- |
|
|
196
|
+
| ← / → | 色相 ∓/± `keyboardStep` 度 |
|
|
197
|
+
| ↑ / ↓ | 饱和度 ±/∓ `keyboardStep` |
|
|
198
|
+
| Home / End | 饱和度归零 / 拉满 |
|
|
199
|
+
| Shift + 方向键 | 步进 ×10 |
|
|
200
|
+
|
|
147
201
|
### 说明
|
|
148
202
|
|
|
149
|
-
- 色盘为 HSV
|
|
150
|
-
- `width`/`height` 为画布逻辑尺寸(CSS
|
|
203
|
+
- 色盘为 HSV 模型:色相取角度、饱和度取离圆心的半径比例;明度(V)取自绑定值并原样保留,因此传入灰色不会被拉成纯色
|
|
204
|
+
- `width`/`height` 为画布逻辑尺寸(CSS 像素),色盘半径自动按「短边半径减去比例留白(收敛在 8~18px)」适配,圆心居中;两者可以不相等。选择器圆环与圆心白色死区同样随半径缩放,因此极小与极大的色盘都能保持一致的观感
|
|
151
205
|
- 画布按 `devicePixelRatio` 放大绘制,高清屏下不会模糊
|
|
152
206
|
- 取色坐标会自动换算回画布逻辑坐标:即使画布被外部 CSS 缩放(如全局 `canvas { max-width: 100% }`、父容器压缩、transform 缩放),取色位置仍与视觉位置一致
|
|
153
207
|
- 点击或拖动超出色盘范围时,选择器会钉在圆周上(取圆周对应位置的颜色)
|
|
154
|
-
- 基于 Pointer Events,鼠标与触摸的操作方式一致;拖动通过 `setPointerCapture`
|
|
208
|
+
- 基于 Pointer Events,鼠标与触摸的操作方式一致;拖动通过 `setPointerCapture` 捕获,指针移出画布也不中断;若捕获失败(部分浏览器/合成事件),window 上的兜底监听仍会正常结束一次选择
|
|
209
|
+
- 只响应主键与主指针:右键/中键不会取色,多指触摸时后续手指不会打断正在进行的拖动
|
|
210
|
+
- 拖动过程中页面滚动会立即使缓存的画布位置失效,避免出现取色偏移
|
|
211
|
+
- `width`/`height` 传 `'auto'` 时画布尺寸跟随容器,容器尺寸变化会自动重绘;该方向需要父容器有确定尺寸
|
|
212
|
+
- `devicePixelRatio` 变化(跨屏拖动窗口、修改系统缩放)时会自动按新比例重建画布
|
|
213
|
+
- 色盘像素按几何参数缓存,尺寸与 dpr 未变时不会重算;圆周做 1 物理像素的透明度渐变,避免锯齿
|
|
155
214
|
- 样式为普通 CSS,通过 `.canvas-color-disc` 后代选择器限定作用域,每个应用引入一次对应版本的 `style.css` 即可
|
|
215
|
+
- 包内附带 `src/index.d.ts`,TS 项目可直接获得 props 与实例方法的类型
|
|
156
216
|
|
|
157
217
|
## 本地开发
|
|
158
218
|
|
|
@@ -163,12 +223,18 @@ npm install
|
|
|
163
223
|
# 启动 Vue 2 demo(localhost:5173)
|
|
164
224
|
npm run dev
|
|
165
225
|
|
|
226
|
+
# 启动 Vue 3 demo(localhost:5174)
|
|
227
|
+
npm run dev:vue3
|
|
228
|
+
|
|
166
229
|
# 同时构建 Vue 2(dist/)与 Vue 3(dist/vue3/)产物
|
|
167
230
|
npm run build
|
|
168
231
|
|
|
169
232
|
# 单独构建某一版本
|
|
170
233
|
npm run build:vue2
|
|
171
234
|
npm run build:vue3
|
|
235
|
+
|
|
236
|
+
# 运行单元测试
|
|
237
|
+
npm test
|
|
172
238
|
```
|
|
173
239
|
|
|
174
240
|
## 许可证
|
package/README.md
CHANGED
|
@@ -121,7 +121,22 @@ export default {
|
|
|
121
121
|
</script>
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
The shape of the bound value is decided by `format`. Updating it from the parent moves the selector accordingly.
|
|
125
|
+
|
|
126
|
+
### Color formats
|
|
127
|
+
|
|
128
|
+
`format` (default `rgb`) decides the shape of the bound value:
|
|
129
|
+
|
|
130
|
+
| format | Value | Example |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| `rgb` | `{ r, g, b }`, channels 0~255 | `{ r: 255, g: 0, b: 0 }` |
|
|
133
|
+
| `hex` | string, 3/4/6/8 digits | `'#ff0000'` |
|
|
134
|
+
| `hsv` | `{ h, s, v }`, h 0~360, s/v 0~100 | `{ h: 0, s: 100, v: 100 }` |
|
|
135
|
+
| `hsl` | `{ h, s, l }`, h 0~360, s/l 0~100 | `{ h: 0, s: 100, l: 50 }` |
|
|
136
|
+
|
|
137
|
+
Strings are always parsed as hex. Objects are parsed with `format` first, and by field names when `format` is not given.
|
|
138
|
+
|
|
139
|
+
With `alpha` enabled an extra `a` channel (0~1) is read and written, and hex output becomes 8 digits (e.g. `#ff000080`). The disc is two-dimensional, so it does not adjust alpha or value itself — provide them through the bound value or your own controls.
|
|
125
140
|
|
|
126
141
|
## API
|
|
127
142
|
|
|
@@ -129,30 +144,75 @@ export default {
|
|
|
129
144
|
|
|
130
145
|
| Prop | Description | Type | Default | Vue version |
|
|
131
146
|
| --- | --- | --- | --- | --- |
|
|
132
|
-
| value | Current color, used by `v-model` | Object
|
|
133
|
-
| modelValue | Current color, used by `v-model` | Object
|
|
134
|
-
| width | Canvas width
|
|
135
|
-
| height | Canvas height
|
|
147
|
+
| value | Current color, used by `v-model` | Object / String | `{ r: 255, g: 255, b: 255 }` | Vue 2 |
|
|
148
|
+
| modelValue | Current color, used by `v-model` | Object / String | `undefined` (falls back to `value`) | Vue 3 |
|
|
149
|
+
| width | Canvas width in CSS pixels, `'auto'` follows the container | Number / String | 300 | both |
|
|
150
|
+
| height | Canvas height in CSS pixels, `'auto'` follows the container | Number / String | 300 | both |
|
|
151
|
+
| format | Bound value format: `rgb` / `hex` / `hsv` / `hsl` | String | `rgb` | both |
|
|
152
|
+
| alpha | Keep and emit the alpha channel | Boolean | `false` | both |
|
|
153
|
+
| disabled | Disable pointer and keyboard interaction | Boolean | `false` | both |
|
|
154
|
+
| keyboardStep | Arrow key step (saturation percentage / hue degrees), ×10 with Shift | Number | 1 | both |
|
|
136
155
|
|
|
137
156
|
### Events
|
|
138
157
|
|
|
139
158
|
| Event | Description | Payload | Vue version |
|
|
140
159
|
| --- | --- | --- | --- |
|
|
141
|
-
| input | Fired in real time while the color changes (throttled per frame, used by `v-model`) |
|
|
142
|
-
| update:modelValue | Same as `input`, used by `v-model` |
|
|
143
|
-
| change | Fired when a pick gesture (press then release)
|
|
160
|
+
| input | Fired in real time while the color changes (throttled per frame, used by `v-model`) | matches `format` | Vue 2 |
|
|
161
|
+
| update:modelValue | Same as `input`, used by `v-model` | matches `format` | Vue 3 |
|
|
162
|
+
| change | Fired when a pick gesture (press then release) or a key adjustment ends | matches `format` | both |
|
|
144
163
|
|
|
145
164
|
Both `input` and `update:modelValue` are always emitted, so the unused one is simply ignored.
|
|
146
165
|
|
|
166
|
+
### Slot
|
|
167
|
+
|
|
168
|
+
| Name | Scope | Description |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| palette | `color` (current color), `setColor(value)` | Extra area rendered below the disc, typically used for preset swatches |
|
|
171
|
+
|
|
172
|
+
```vue
|
|
173
|
+
<canvas-color-disc v-model="rgb">
|
|
174
|
+
<template #palette="{ setColor }">
|
|
175
|
+
<button @click="setColor({ r: 255, g: 0, b: 0 })">Red</button>
|
|
176
|
+
</template>
|
|
177
|
+
</canvas-color-disc>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Instance methods
|
|
181
|
+
|
|
182
|
+
Available through a `ref` (exposed via `expose` on Vue 3, directly on `$refs` on Vue 2):
|
|
183
|
+
|
|
184
|
+
| Method | Description |
|
|
185
|
+
| --- | --- |
|
|
186
|
+
| `getColor()` | Returns the current color; objects are returned as copies |
|
|
187
|
+
| `setColor(value)` | Sets the color; the value must match `format`, invalid values are ignored. Also emits `change` |
|
|
188
|
+
| `reset()` | Resets to white |
|
|
189
|
+
|
|
190
|
+
### Keyboard
|
|
191
|
+
|
|
192
|
+
The interactive element is focusable (`tabindex="0"`, `role="slider"` with `aria-valuetext`). Once focused:
|
|
193
|
+
|
|
194
|
+
| Key | Action |
|
|
195
|
+
| --- | --- |
|
|
196
|
+
| ← / → | Hue ∓/± `keyboardStep` degrees |
|
|
197
|
+
| ↑ / ↓ | Saturation ±/∓ `keyboardStep` |
|
|
198
|
+
| Home / End | Saturation to 0 / 100 |
|
|
199
|
+
| Shift + arrows | Step ×10 |
|
|
200
|
+
|
|
147
201
|
### Notes
|
|
148
202
|
|
|
149
|
-
- The disc uses the HSV model: hue comes from the angle, saturation from the distance to the center ratio
|
|
150
|
-
- `width` / `height` are logical canvas sizes in CSS pixels. The disc radius is
|
|
203
|
+
- The disc uses the HSV model: hue comes from the angle, saturation from the distance to the center ratio. Value is taken from the bound value and preserved, so passing a gray does not turn it into a fully saturated color
|
|
204
|
+
- `width` / `height` are logical canvas sizes in CSS pixels. The disc radius is the shorter half side minus a proportional padding (clamped to 8~18px) and the origin is centered; they do not have to be equal. The selector ring and the white dead zone at the center scale with the radius too, so tiny and large discs keep the same proportions
|
|
151
205
|
- The canvas is rendered with `devicePixelRatio` scaling, so it stays sharp on high-DPI screens
|
|
152
206
|
- Pointer coordinates are converted back to logical canvas coordinates: even if the canvas is scaled by external CSS (e.g. a global `canvas { max-width: 100% }`, a squeezed parent, or a `transform` scale), the picked position still matches the visual position
|
|
153
207
|
- Clicking or dragging outside the disc pins the selector to the circumference and takes the color at that point
|
|
154
|
-
- Built on Pointer Events, so mouse and touch behave the same; dragging uses `setPointerCapture`, so it continues even when the pointer leaves the canvas
|
|
208
|
+
- Built on Pointer Events, so mouse and touch behave the same; dragging uses `setPointerCapture`, so it continues even when the pointer leaves the canvas, and a window-level fallback ends the gesture if the capture could not be taken
|
|
209
|
+
- Only the primary button / primary pointer starts a pick: right and middle clicks are ignored, and extra fingers in a multi-touch gesture do not take over an ongoing drag
|
|
210
|
+
- The cached canvas rect is invalidated on scroll, so picking stays accurate while the page is scrolled during a drag
|
|
211
|
+
- Passing `'auto'` for `width` / `height` makes the canvas follow its container and redraw on container resizes; the parent needs a definite size on that axis
|
|
212
|
+
- When `devicePixelRatio` changes (dragging the window to another screen, changing the OS scaling), the canvas is rebuilt at the new ratio
|
|
213
|
+
- Disc pixels are cached by geometry, so nothing is recomputed while size and dpr stay the same; the circumference fades over one physical pixel to avoid aliasing
|
|
155
214
|
- Styles are shipped as plain CSS scoped by the `.canvas-color-disc` ancestor selector; import the matching `style.css` once per app
|
|
215
|
+
- `src/index.d.ts` ships with the package, so TS projects get prop and instance method types out of the box
|
|
156
216
|
|
|
157
217
|
## Local development
|
|
158
218
|
|
|
@@ -163,12 +223,18 @@ npm install
|
|
|
163
223
|
# serve the Vue 2 demo at localhost:5173
|
|
164
224
|
npm run dev
|
|
165
225
|
|
|
226
|
+
# serve the Vue 3 demo at localhost:5174
|
|
227
|
+
npm run dev:vue3
|
|
228
|
+
|
|
166
229
|
# build both Vue 2 (dist/) and Vue 3 (dist/vue3/) bundles
|
|
167
230
|
npm run build
|
|
168
231
|
|
|
169
232
|
# build a single target
|
|
170
233
|
npm run build:vue2
|
|
171
234
|
npm run build:vue3
|
|
235
|
+
|
|
236
|
+
# run the unit tests
|
|
237
|
+
npm test
|
|
172
238
|
```
|
|
173
239
|
|
|
174
240
|
## License
|