Skip to content

Commit bff2e89

Browse files
committed
feat: rewrite color picker and add alpha picker
1 parent 70c50e8 commit bff2e89

File tree

1 file changed

+167
-11
lines changed

1 file changed

+167
-11
lines changed

wasm/index.html

Lines changed: 167 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,23 @@
88
<link rel="preload" as="fetch" type="application/wasm" href="./index_bg.wasm" crossorigin>
99
<script src="./index.min.js"></script>
1010
<style>
11+
:root {
12+
--slider-thumb-size: 26px;
13+
--slider-track-height: 14px;
14+
--slider-thumb-bg-color: #FF8253;
15+
--input-border-color: #666;
16+
}
17+
1118
html {
1219
box-sizing: border-box;
20+
font-family: system-ui, Arial, Helvetica, sans-serif;
21+
}
22+
23+
html:before {
24+
content: '';
25+
color: color-mix( in srgb, var(--picker-color), transparent var(--picker-alpha, 0%) );
26+
/* Or use Relative color */
27+
/* color: rgb(from var(--picker-color) r g b / var(--picker-alpha, 1)); */
1328
}
1429

1530
*, *:before, *:after {
@@ -49,12 +64,12 @@
4964
margin-right: auto;
5065
}
5166

52-
input[type="color"] {
67+
input[type="color" i] {
5368
border: none;
5469
background: none;
5570
}
5671

57-
input[type="color"]::-webkit-color-swatch-wrapper {
72+
input[type="color" i]::-webkit-color-swatch-wrapper {
5873
padding: 0;
5974
}
6075

@@ -63,7 +78,26 @@
6378
user-select: none;
6479
}
6580

66-
input:not([type="color"]), select {
81+
.color-picker-box {
82+
position: relative;
83+
display: flex;
84+
align-items: center;
85+
height: var(--slider-track-height);
86+
}
87+
88+
#color-picker {
89+
visibility: hidden;
90+
width: 40px;
91+
height: var(--slider-track-height);
92+
position: absolute;
93+
bottom: -10px;
94+
visibility: hidden;
95+
position-anchor: --picker-target;
96+
left: anchor(left);
97+
margin-left: -106px;
98+
}
99+
100+
input:not([type="color" i]), select {
67101
height: 30px;
68102
padding: 0 .5em;
69103
font-size: 16px;
@@ -73,6 +107,7 @@
73107
display: flex;
74108
flex: 1;
75109
margin-top: 20px;
110+
margin-bottom: 30px;
76111
}
77112

78113
#input-svg {
@@ -169,6 +204,71 @@
169204
.github:hover .octo-arm {
170205
animation: octocat-wave 560ms ease-in-out;
171206
}
207+
/* 自定义 Alpha 选择器样式 */
208+
input[type="range" i] {
209+
appearance: none;
210+
max-width: 150px;
211+
}
212+
213+
input[type="range" i]::-webkit-slider-thumb {
214+
anchor-name: --picker-target;
215+
appearance: none;
216+
height: var(--slider-thumb-size);
217+
width: var(--slider-thumb-size);
218+
max-width: 80px;
219+
position: relative;
220+
z-index: 2048;
221+
top: 50%;
222+
transform: translateY(-50%);
223+
border-radius: 50%;
224+
border: 2px solid #fff;
225+
box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.6), inset 0px 1px 3px rgba(0, 0, 0, 0.3);
226+
background: var(--picker-color, var(--slider-thumb-bg-color));
227+
}
228+
input[type="range" i]::-moz-range-thumb {
229+
anchor-name: --picker-target;
230+
appearance: none;
231+
height: var(--slider-thumb-size);
232+
width: var(--slider-thumb-size);
233+
max-width: 80px;
234+
position: relative;
235+
z-index: 2048;
236+
border-radius: 50%;
237+
border: 2px solid #fff;
238+
box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.6), inset 0px 1px 3px rgba(0, 0, 0, 0.3);
239+
background: var(--picker-color, var(--slider-thumb-bg-color));
240+
}
241+
input[type="range" i]:focus::-webkit-slider-thumb {
242+
outline: solid 2px #000;
243+
}
244+
input[type="range" i]:focus::-moz-range-thumb {
245+
outline: solid 2px #000;
246+
}
247+
248+
input[type="range" i]::-webkit-slider-runnable-track {
249+
appearance: none;
250+
height: var(--slider-track-height);
251+
border-radius: 999px;
252+
border: 1px solid var(--input-border-color, #666);
253+
box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.3);
254+
--chessboard-size: var(--slider-track-height);
255+
background:
256+
linear-gradient(to right, transparent, var(--picker-color, var(--slider-thumb-bg-color))),
257+
repeating-conic-gradient(#808080 0% 25%, transparent 0% 50%)
258+
50% / var(--chessboard-size) var(--chessboard-size);
259+
}
260+
input[type="range" i]::-moz-range-track {
261+
appearance: none;
262+
height: var(--slider-track-height);
263+
border-radius: 999px;
264+
border: 1px solid var(--input-border-color, #666);
265+
box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.3);
266+
--chessboard-size: var(--slider-track-height);
267+
background:
268+
linear-gradient(to right, transparent, var(--picker-color, var(--slider-thumb-bg-color))),
269+
repeating-conic-gradient(#808080 0% 25%, transparent 0% 50%)
270+
50% / var(--chessboard-size) var(--chessboard-size);
271+
}
172272
</style>
173273
<script>
174274
const fontList = [
@@ -350,6 +450,7 @@
350450
}
351451

352452
const colorPickerElement = document.querySelector('#color-picker')
453+
const colorPickerAlphaElement = document.querySelector('#color-picker-alpha')
353454
const svgSizeElement = document.querySelector('#svg-size')
354455
const cropElement = document.querySelector('#crop-by-bbox')
355456
const svgSelectElement = document.querySelector('#slt-svg')
@@ -396,12 +497,40 @@
396497
}
397498
})
398499

399-
colorPickerElement.addEventListener('change', function (event) {
400-
const value = event.target.value
500+
function onChangeColor() {
401501
const hasCrop = cropElement.checked
402-
if (!value) return
403-
resvgOpts.background = value
502+
const style = window.getComputedStyle(document.querySelector('html'), ':before')
503+
const color = style.getPropertyValue('color')
504+
const rgb_color = convertColorToRGBA(color)
505+
506+
console.info('getComputedStyle color\n', color)
507+
console.info('convert to rgba()\n', rgb_color)
508+
509+
resvgOpts.background = rgb_color
404510
svg2png(null, resvgOpts, hasCrop)
511+
}
512+
513+
colorPickerElement.addEventListener('input', function (event) {
514+
const value = event.target.value
515+
if (!value) return
516+
document.documentElement.style.setProperty('--picker-color', value)
517+
onChangeColor()
518+
})
519+
colorPickerAlphaElement.addEventListener('click', function (event) {
520+
colorPickerElement.showPicker()
521+
})
522+
523+
colorPickerAlphaElement.addEventListener('input', function (event) {
524+
const value = event.target.value
525+
if (!value) return
526+
527+
const color_picker_value = getComputedStyle(document.documentElement).getPropertyValue('--picker-color')
528+
if (!color_picker_value) {
529+
document.documentElement.style.setProperty('--picker-color', '#FF8253')
530+
}
531+
// 如果使用 Relative color,这里直接使用 value + %
532+
document.documentElement.style.setProperty('--picker-alpha', 100 - value + '%')
533+
onChangeColor()
405534
})
406535

407536
svgSizeElement.addEventListener('change', function (event) {
@@ -487,6 +616,30 @@
487616
}
488617
return { checkResult: false, index: currentFontIndex }
489618
}
619+
620+
// 将 color() 转换为 rgba()
621+
function convertColorToRGBA(color) {
622+
if (!color || typeof color !== 'string') return color
623+
624+
const match = color.match(/color\(srgb\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+%?))?\)/)
625+
if (match) {
626+
const r = Math.round(match[1] * 255)
627+
const g = Math.round(match[2] * 255)
628+
const b = Math.round(match[3] * 255)
629+
let alpha = match[4]
630+
// 如果 alpha 是百分比形式,转换为 0 到 1 之间的小数
631+
if (!alpha) {
632+
alpha = 1
633+
} else if (alpha.includes('%')) {
634+
alpha = parseFloat(alpha) / 100
635+
} else {
636+
alpha = parseFloat(alpha)
637+
}
638+
639+
return `rgba(${r}, ${g}, ${b}, ${alpha})`
640+
}
641+
return color
642+
}
490643
</script>
491644
</head>
492645

@@ -518,12 +671,15 @@ <h1 class="site-title">resvg-js playground</h1>
518671
</select>
519672
</div>
520673
<div class="opts-cell">
521-
<label for="color-picker">Change background:</label>
522-
<input type="color" name="color-picker" id="color-picker">
674+
<label for="color-picker">Background:</label>
675+
<div class="color-picker-box">
676+
<input type="color" name="color-picker" value="#FF8253" id="color-picker">
677+
<input type="range" id="color-picker-alpha" min="0" max="100" value="100">
678+
</div>
523679
</div>
524680
<div class="opts-cell">
525-
<label for="svg-size">Change width:</label>
526-
<input type="number" name="svg-size" id="svg-size">
681+
<label for="svg-size">Width:</label>
682+
<input type="number" name="svg-size" id="svg-size" style="max-width: 6em;">
527683
</div>
528684
<div class="opts-cell">
529685
<label for="crop-by-bbox">Crop by BBox:</label>

0 commit comments

Comments
 (0)