ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

wired-icon:用 Web Component 把任意 SVG 图标一键转成手绘素描风

wired-icon:用 Web Component 把任意 SVG 图标一键转成手绘素描风 UI组件前端【免费下载链接】wired-elementsCollection of custom elements that appear hand drawn. Great for wireframes or a fun look.项目地址https://gitcode.com/gh_mirrors/wi/wired-elements点击查看免费下载wired-icon是 wired-elements 实验包中的一个 Web Component它能把任意标准 SVG 图标实时转换为带有手绘hand-drawn / sketchy质感的版本非常适合线框稿wireframe或追求随性趣味的界面。读完本文你将掌握它的安装方式、config配置参数、Light DOM 约束、无障碍处理以及如何把它嵌套进wired-icon-button中并理解其底层转换原理与源码实现。组件定位从图标到手绘图标wired-icon的核心能力可以概括为一句话把任何 SVG 转换为其手绘、素描版本见 experimental/wired-icon/README.md。它不会要求你使用某个特定图标库而是接受你传入的任意svg片段再通过底层绘制库wired-lib基于 roughjs 重新渲染成抖动的、不完美的线条与填充形成类似手绘草稿的视觉风格。在项目内它还有一层特殊身份它是wired-mat-icon的基础库。wired-mat-icon内置了几乎全套 Material Design 图标集本质上就是在wired-icon的转换能力之上预置了图标路径数据参见 wired-mat-icon/README.md。因此理解wired-icon也就理解了整个 wired 图标体系的地基。安装与引入按 README 的说明安装只需一条命令npm i wired-icon引入方式有两种任选其一直接在 HTML 页面中以 ES Module 方式加载script typemodule srcwired-icon/lib/wired-icon.js/script或在你自己的模块脚本中 importimport wired-icon;从 experimental/wired-icon/package.json 可以看到该包以lib/wired-icon.js作为入口main: lib/wired-icon.js运行时依赖lit-element^2.3.1与wired-lib^2.0.0——前者负责组件生命周期与属性响应后者负责把 SVG 渲染成手绘版本。构建产物lib/由 TypeScript 编译生成build: rm -rf lib tsc仓库内已包含编译后的 lib/WiredIcon.js 可供直接查看。基础用法用wired-icon包裹你的 SVGwired-icon的使用方式非常直接把任意 SVG 图标放进wired-icon标签内部它会在渲染时自动完成转换。README 给出了一个完整的示例wired-icon config{fillStyle: zigzag, fill: #A4C639, hachureGap: 1.5, fillWeight: 0.9} svg width70 height70 viewBox-1 -1 24 26 path dM6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l-1.48 1.48A5.84 5.84 0 0 0 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-.71 0-.2.2-.2.51 0 .71l1.31 1.31A5.983 5.983 0 0 0 6 7h12c0-1.99-.97-3.75-2.47-4.84zM10 5H9V4h1v1zm5 0h-1V4h1v1z/ /svg /wired-icon这个例子同时展示了两个关键点图标内容照常书写——path的d数据来自普通 Material Design 图标无需任何改写效果通过config属性定制——这里配置了zigzag锯齿填充、草绿色#A4C639、较密的排线间距等渲染出的就是手绘填色的效果。仓库中的演示页面 experimental/icon.html 提供了大量可直接运行的真实案例来自 Vaadin 图标集的星形、Facebook 图标、Wi-Fi 状态图标、信封、猫爪paw print等均以不同config组合展示是调参时最好的灵感来源。config属性手绘效果的完整控制面config是wired-icon唯一的核心属性类型为可选的对象用来配置 roughjs 的渲染选项。README 明确提示完整选项列表可参考 roughjs 的 wikiOptions 一节并结合示例页寻找灵感。默认值roughness 0.1README 特别强调了一个默认值默认 roughness 被设置为 0.1这在对图标而言大多数时候都是最合适的一个值。这一默认值在源码中有直接证据。WiredIcon.ts 顶部定义了const DEFAULT_CONFIG: Options { roughness: 0.1, };roughness控制线条的抖动/潦草程度——数值越大线条越狂野而 0.1 这个低值让图标在保留手绘感的同时仍能清晰可辨非常适合小尺寸图标。在connectedCallback中用户配置会与默认配置合并后生效wiredSvg(svg, {...DEFAULT_CONFIG, ...this.config});也就是说你未指定的参数全部使用内置默认只有显式传入的键会被覆盖。属性反射reflectconfig被声明为property({ type: Object, reflect: true }) config: Options DEFAULT_CONFIG;reflect: true意味着通过 JavaScript 修改config属性时会同步反映到 DOM 属性上反过来在 HTML 中直接写config属性也能被读取。这为后续的程序化控制例如在框架或自定义组件中动态换肤留好了接口——wired-mat-icon的 README 就演示了wiredMatIcon.config {fill: red, fillWeight: 1}这类用法。常用参数速查来自仓库示例的实测组合下表整理了 README 与 experimental/icon.html 中实际出现过的参数及其含义参数作用示例取值roughness线条抖动/潦草程度默认0.10.1、0.2、0.3fill填充颜色#A4C639、lightblue、gray、blue、redfillStyle填充纹理风格hachure默认排线、zigzag锯齿、cross-hatch交叉排线、solidfillWeight填充线条的粗细0.5、0.8、0.9hachureGap排线间距越小越密1、1.5hachureAngle排线角度20、50stroke描边颜色默认#000设为transparent可去描边strokeWidth描边粗细0.3、0.8典型组合示例来自示例页——柔和浅蓝填充wired-icon classicon config{fill: lightblue, hachureGap: 1.5, fillWeight: 0.9, roughness: 0.1} svg viewbox-1 -1 18 18 path dM7.5 12.2c-2.3 0-4.2-1.9-4.2-4.2s1.9-4.2 4.2-4.2 4.2 1.9 4.2 4.2c0.1 2.3-1.9 4.2-4.2 4.2z.../path /svg /wired-icon小贴士阅读示例页时注意手绘线条通常比原图略胖示例中大量图标使用viewbox-1 -1 18 18这类带负坐标起点的视图框正是为了给抖动线条留出边距。Light DOM 约束必须遵守的书写规则wired-icon不使用 Shadow DOM。看 WiredIcon.ts 的实现createRenderRoot() { // No use for shadow DOM return this; }因此你写在标签内部的内容就是 Light DOMconnectedCallback会直接执行this.querySelector(svg)找到第一个svg节点交给wiredSvg处理。这也带来三条硬性约束约束一必须用svg包裹转换的输入是一个svg节点裸元素无法被识别。无效 Light DOM 示例 1没有 svg 标签包裹circle cx16.5 cy5.5 r2.5/约束二只能有一层深度README 原文要求only one level of depth。也就是说svg的直接子元素会被转换但嵌套在g等容器内的元素不会被转换而是原样保留。无效 Light DOM 示例 2g内的 rect 不会被转换svg viewbox0 0 24 24 g rect x3 y8 width18 height13/rect rect x1 y3 width22 height5/rect /g line x110 y112 x214 y212/line /svg上面的示例中两个rect因为被g包裹而保持原样只有line会被手绘化。有效的 Light DOM 示例svg viewbox0 0 24 24 rect x3 y8 width18 height13/rect rect x1 y3 width22 height5/rect line x110 y112 x214 y212/line /svg约束三支持的基本图形集合wired-icon能转换以下 SVG 标签circle圆ellipse椭圆line直线path路径polygon多边形polyline折线⚠️ 转换结果将与polygon相同即会被当作闭合多边形处理rect矩形其余任何标签都会被原样包含在转换后的 SVG 中——这一点对实践很重要如果图标里存在wired-icon不支持的元素它不会被丢弃而是以原始形式混入最终结果。从仓库底层的 src/wired-lib.ts 可以看到这一能力集对应的绘制函数rectangle、line、polygon、ellipse、arc分别把基本几何图形交给 roughjs 的 renderer 生成手绘路径roughRectangle、roughLine、roughPolygon、roughEllipse、roughArc再用opsToPath把渲染操作move / bcurveTo / lineTo拼成最终的path元素。值得留意的是其中对尺寸的处理细节例如rectangle会向内收缩 2pxrectangle(x 2, y 2, width - 4, height - 4, ...)、ellipse会按尺寸收缩 14px目的同样是给手绘抖动留出视觉边距——这印证了示例中负起点 viewBox 的用法并非偶然。样式与缩放README 的 Styling 一节给出了两条指引缩放在wired-icon元素或内部svg标签上通过 CSS 设置width/height即可改变图标尺寸。变色不要用 CSS 改颜色请优先使用config属性中的颜色参数如fill、stroke。原因在于手绘效果由 roughjs 在渲染期生成路径CSS 颜色规则无法作用到这些生成路径的填充/描边上所以统一走config才是可控的方式。组合玩法放进wired-icon-buttonwired-icon可以与 wired-elements 家族的其他组件无缝嵌套README 专门演示了放入wired-icon-button的用法——这也是图标组件最常见的落地场景style .icon-button{ display: block; width: 30px; } /style wired-icon-button elevation5 wired-icon classicon-button config{strokeWidth: 0.3, fill: blue, fillStyle: cross-hatch} svg viewbox-1 -1 18 18 path dM9 11h-3c0-3 1.6-4 2.7-4.6 0.4-0.2 0.7-0.4 0.9-0.6 0.5-0.5 0.3-1.2 0.2-1.4-0.3-0.7-1-1.4-2.3-1.4-2.1 0-2.5 1.9-2.5 2.3l-3-0.4c0.2-1.7 1.7-4.9 5.5-4.9 2.3 0 4.3 1.3 5.1 3.2 0.7 1.7 0.4 3.5-0.8 4.7-0.5 0.5-1.1 0.8-1.6 1.1-0.9 0.5-1.2 1-1.2 2z/ path dM9.5 14c0 1.105-0.895 2-2 2s-2-0.895-2-2c0-1.105 0.895-2 2-2s2 0.895 2 2z/ /svg /wired-icon /wired-icon-button这段代码同时示范了两个实践要点通过给内部的wired-icon加 CSS 类并设置width: 30px让图标尺寸匹配按钮的视觉比例图标路径可以有多个这里是灯泡主题的两个path它们各自独立被手绘化。experimental/icon.html中同样的组合还展示了wired-mat-icon版本iconedit两种写法在按钮场景下可以互换。无障碍为图标补充语义标签图标类组件如果只提供纯视觉内容对使用屏幕阅读器的用户是不友好的。README 推荐在svg内使用aria-labelledbytitle的方式来提供可读的图标名称wired-icon classicon config{fill: gray, fillStyle: cross-hatch, hachureGap: 1.5, fillWeight: 0.5, roughness: 0.1} svg viewBox0 0 24 24 aria-labelledbyicon-label title idicon-labelIcon of a pet footprint/title circle cx4.5 cy9.5 r2.5/ circle cx9 cy5.5 r2.5/ circle cx15 cy5.5 r2.5/ circle cx19.5 cy9.5 r2.5/ path dM17.34 14.86c-.87-1.02-1.6-1.89-2.48-2.91-.46-.54-1.05-1.08-1.75-1.32-.11-.04-.22-.07-.33-.09-.25-.04-.52-.04-.78-.04s-.53 0-.79.05c-.11.02-.22.05-.33.09-.7.24-1.28.78-1.75 1.32-.87 1.02-1.6 1.89-2.48 2.91-1.31 1.31-2.92 2.76-2.62 4.79.29 1.02 1.02 2.03 2.33 2.32.73.15 3.06-.44 5.54-.44h.18c2.48 0 4.81.58 5.54.44 1.31-.29 2.04-1.31 2.33-2.32.31-2.04-1.3-3.49-2.61-4.8z/ /svg /wired-icon注意这里同时用到了 4 个circle和 1 个path的混合结构且全部位于svg直接子层——完全符合前面说的 Light DOM 约束这也说明真实图标往往是多元素混合的形态。可以推断aria-labelledby与title的关系在转换后仍会保留因为它们是svg属性与子节点的一部分README 亦将其作为官方推荐做法。图标素材从哪来README 提供了一份有主观倾向、非穷尽的高质量免费图标来源清单这些来源的图标都是标准 SVG 结构与wired-icon兼容Google Material Design SVG Icon RepoMaterial 官方 SVG 精灵图集图标均为标准path/circle结构拿来即用Vaadin IconsVaadin 组件库配套的图标集同样质量高且免费。如果使用 Material 图标更高效的做法是直接上wired-mat-icon——它把几乎全部 Material 图标打包成了内置 iconset通过iconandroid这样的字符串即可引用省去手动寻找 SVG path 的麻烦参见 wired-mat-icon/README.md。但需要注意wired-mat-icon的 README 明确警告它会对打包体积产生较大影响因为内置了全套图标路径生产环境建议优先用wired-icon自行挑选需要的 SVG 来做体积优化。源码结构解读30 行代码背后的设计wired-icon的核心实现非常精简。整个包只有两个源文件1. src/WiredIcon.ts —— 组件类定义import { Options, wiredSvg } from wired-lib/lib/wired-lib; import { LitElement, css, CSSResult, property } from lit-element; const DEFAULT_CONFIG: Options { roughness: 0.1, }; export class WiredIcon extends LitElement { property({ type: Object, reflect: true }) config: Options DEFAULT_CONFIG; static get styles(): CSSResult { return css :host { display: block; } ; } connectedCallback() { super.connectedCallback(); const svg this.querySelector(svg); if (svg) { wiredSvg(svg, {...DEFAULT_CONFIG, ...this.config}); } } createRenderRoot() { // No use for shadow DOM return this; } }几个值得注意的实现细节转换时机connectedCallback中执行wiredSvg(svg, config)即元素挂载到 DOM 时一次性完成 SVG 的手绘化重写空保护if (svg)判断保证没有svg子节点时组件不会报错只是安静地不执行转换不渲染模板没有render()方法、没有 shadow DOM组件生命周期只负责找到 svg → 交给 wiredSvg这件事。2. src/wired-icon.ts —— 自定义元素注册import { customElement } from lit-element; import { WiredIcon } from ./WiredIcon; // We separate the class from its registration as a custom element, // so that WiredIcon class can be extended. // Otherwise, CustomElementRegistry would register it twice and would throw an error. window.customElements.get(wired-icon) || customElement(wired-icon)(WiredIcon); export { WiredIcon };这里刻意把类定义与自定义元素注册拆成两个文件并用window.customElements.get(wired-icon) || ...做幂等注册既允许他人继承WiredIcon类扩展新组件又避免重复注册抛错。这是wired-mat-icon得以在其之上构建的关键前提。3. 工程配置tsconfig.json 继承仓库根配置输出目录指向./libpackage.json 声明了依赖与build/tsc:watch脚本。需要自行构建时在该包目录下执行npm run build即可重新产出lib/。注意事项小结wired-icon位于仓库的experimental/目录属于实验性组件功能稳定但仍在演进正式项目接入前建议先在目标浏览器中实测polyline会被当作polygon处理闭合使用折线类图标时留意结果差异svg内嵌套g的分组元素不会被转换复杂图标请先拍平结构追求极致手绘效果时roughness可从默认的0.1向上试探但注意过大的值会让小尺寸图标难以辨认生产环境优先用wired-icon按需选取 SVG把wired-mat-icon视为原型/开发阶段的效率工具其内置 iconset 体积较大。至此从安装、配置、约束到源码原理wired-icon的完整使用路径已经打通只需一个svg和一个config你就能在任何页面里拥有一整套手绘风图标体系。赞分享UI组件前端【免费下载链接】wired-elementsCollection of custom elements that appear hand drawn. Great for wireframes or a fun look.项目地址https://gitcode.com/gh_mirrors/wi/wired-elements点击查看免费下载相关推荐5分钟上手打造独特手绘风格UIWired Elements完全指南5分钟上手打造独特手绘风格UIWired Elements完全指南 Wired Elements是一个创新的开源Web组件库它通过手绘风格的UI元素为网页UI组件前端Rerun 绘制任意标量数据用组件映射Component Mappings把非 Rerun 语义数据变成时序图Rerun 绘制任意标量数据用组件映射Component Mappings把非 Rerun 语义数据变成时序图 本文讲解 Rerun 的「任意标量Any数据可视化3D渲染数据分析Kaku终端CmdL聊天面板全解流式Markdown、代码高亮与工具调用Kaku终端CmdL聊天面板全解流式Markdown、代码高亮与工具调用 Kaku 是一个专为 AI 编程打造的极速开箱即用终端其核心卖点之一是按 Cmd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表