|
8 | 8 | <link rel="preload" as="fetch" type="application/wasm" href="./index_bg.wasm" crossorigin> |
9 | 9 | <script src="./index.min.js"></script> |
10 | 10 | <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 | + |
11 | 18 | html { |
12 | 19 | 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)); */ |
13 | 28 | } |
14 | 29 |
|
15 | 30 | *, *:before, *:after { |
|
49 | 64 | margin-right: auto; |
50 | 65 | } |
51 | 66 |
|
52 | | - input[type="color"] { |
| 67 | + input[type="color" i] { |
53 | 68 | border: none; |
54 | 69 | background: none; |
55 | 70 | } |
56 | 71 |
|
57 | | - input[type="color"]::-webkit-color-swatch-wrapper { |
| 72 | + input[type="color" i]::-webkit-color-swatch-wrapper { |
58 | 73 | padding: 0; |
59 | 74 | } |
60 | 75 |
|
|
63 | 78 | user-select: none; |
64 | 79 | } |
65 | 80 |
|
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 { |
67 | 101 | height: 30px; |
68 | 102 | padding: 0 .5em; |
69 | 103 | font-size: 16px; |
|
73 | 107 | display: flex; |
74 | 108 | flex: 1; |
75 | 109 | margin-top: 20px; |
| 110 | + margin-bottom: 30px; |
76 | 111 | } |
77 | 112 |
|
78 | 113 | #input-svg { |
|
169 | 204 | .github:hover .octo-arm { |
170 | 205 | animation: octocat-wave 560ms ease-in-out; |
171 | 206 | } |
| 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 | + } |
172 | 272 | </style> |
173 | 273 | <script> |
174 | 274 | const fontList = [ |
|
350 | 450 | } |
351 | 451 |
|
352 | 452 | const colorPickerElement = document.querySelector('#color-picker') |
| 453 | + const colorPickerAlphaElement = document.querySelector('#color-picker-alpha') |
353 | 454 | const svgSizeElement = document.querySelector('#svg-size') |
354 | 455 | const cropElement = document.querySelector('#crop-by-bbox') |
355 | 456 | const svgSelectElement = document.querySelector('#slt-svg') |
|
396 | 497 | } |
397 | 498 | }) |
398 | 499 |
|
399 | | - colorPickerElement.addEventListener('change', function (event) { |
400 | | - const value = event.target.value |
| 500 | + function onChangeColor() { |
401 | 501 | 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 |
404 | 510 | 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() |
405 | 534 | }) |
406 | 535 |
|
407 | 536 | svgSizeElement.addEventListener('change', function (event) { |
|
487 | 616 | } |
488 | 617 | return { checkResult: false, index: currentFontIndex } |
489 | 618 | } |
| 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 | + } |
490 | 643 | </script> |
491 | 644 | </head> |
492 | 645 |
|
@@ -518,12 +671,15 @@ <h1 class="site-title">resvg-js playground</h1> |
518 | 671 | </select> |
519 | 672 | </div> |
520 | 673 | <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> |
523 | 679 | </div> |
524 | 680 | <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;"> |
527 | 683 | </div> |
528 | 684 | <div class="opts-cell"> |
529 | 685 | <label for="crop-by-bbox">Crop by BBox:</label> |
|
0 commit comments