- UI组件
- 前端
【免费下载链接】wired-elements
Collection of custom elements that appear hand drawn. Great for wireframes or a fun look.
导读
wired-icon-button是 wired-elements 组件库中一个以"手绘素描风格"呈现的圆形图标按钮:它由 RoughJS 生成手绘椭圆边框,中心通过 slot 承载任意图标内容(例如 Material Icons 的mwc-icon),非常适合用于线框图(wireframe)、原型草图或追求手绘趣味风格的界面。本文以 docs/wired-icon-button.md 为骨架,完整覆盖其安装、导入、属性、CSS 变量与事件用法,并结合 src/wired-icon-button.ts 及 examples/icon-button.html 等仓库源码,深入讲解它的渲染原理、样式系统与可扩展用法,读完即可直接上手使用与二次定制。
组件是什么
根据 docs/wired-icon-button.md 的定义,wired-icon-button是一个"手绘素描风格的圆形按钮,中心放置一张图片"。这里的"图片"并非限制为<img>,也可以是由图标字体或图标 Web Component 渲染的图标,比如@material/mwc-icon(Material Web Components 的图标组件)。
在 src/wired-icon-button.ts 中,它通过@customElement('wired-icon-button')注册为原生自定义元素,继承自 src/wired-base.ts 中封装的WiredBase抽象基类,依赖 roughjs 与 lit 两个核心库(见 package.json)。
安装与引入
通过 npm 安装
在项目根目录执行:
npm i wired-elements安装后,wired-icon-button会随wired-elements包一起提供(该包同时导出WiredButton、WiredInput等全套手绘组件,src/wired-elements.ts 中可见export * from './wired-icon-button'等统一导出)。
模块方式导入
在你的 JavaScript / TypeScript 代码中:
import { WiredIconButton } from 'wired-elements'; // 或按需单独引入,体积更小 import { WiredIconButton } from 'wired-elements/lib/wired-icon-button.js';直接通过 CDN 加载
无需构建工具,直接在 HTML 页面中加载 ES Module:
<script type="module" src="https://unpkg.com/wired-elements/lib/wired-icon-button.js?module"></script>注:以上路径以当前仓库
wired-elements包(版本3.0.0-rc.7,见 package.json)为准,发布到 npm 后即可通过上述方式引用。
基础用法
引入组件后,直接在 HTML 中使用自定义标签即可:
<wired-icon-button> <mwc-icon>favorite</mwc-icon> </wired-icon-button> <wired-icon-button class="red"> <mwc-icon>favorite</mwc-icon> </wired-icon-button>其中<mwc-icon>是 Material Design 的图标组件(需要额外引入@material/mwc-icon)。你也可以放入任意 HTML 内容——凡是能通过 slot 分发的内容都会被渲染在圆形手绘按钮的中央。
仓库的 examples/icon-button.html 给出了一个可直接运行的完整示例:它通过 Google Fonts 加载 Material Icons 字体,再引入@material/mwc-icon与本组件,页面中依次展示了默认样式、红色文字(.red)、粉色背景(.pinkbg)、大图标(.big)以及禁用态(disabled)五种形态。
属性(Properties)
disabled— 是否禁用按钮。默认值为false。
<wired-icon-button disabled> <mwc-icon>favorite</mwc-icon> </wired-icon-button>在 src/wired-icon-button.ts 第 8 行,它被声明为响应式布尔属性并反射到 DOM:
@property({ type: Boolean, reflect: true }) disabled = false;reflect: true意味着当属性变化时,disabled会同步反映为 HTML attribute,便于通过 CSS 选择器匹配。渲染层通过?disabled="${this.disabled}"将disabled透传给内部的原生<button>元素(第 63 行)。对应的禁用样式见第 38~43 行:
button[disabled] { opacity: 0.6 !important; background: rgba(0, 0, 0, 0.07); cursor: default; pointer-events: none; }禁用后按钮呈现半透明、浅灰底且不响应鼠标事件的视觉效果。由于内部是真正的<button>元素,键盘焦点管理、表单语义等原生能力天然可用。
自定义 CSS 变量
组件通过两个 CSS 自定义属性暴露样式定制入口:
| 变量 | 作用 | 默认值 |
|---|---|---|
--wired-icon-size | 图标(slot 内容)的数字字号 | 24(px) |
--wired-icon-bg-color | 按钮背景色 | 未设置(透明) |
调整图标大小
在 src/wired-icon-button.ts 第 53~56 行,slot 内容的字号直接绑定该变量:
button ::slotted(*) { position: relative; font-size: var(--wired-icon-size, 24px); }示例(对应 examples/icon-button.html 中的.big类):
<style> .big { --wired-icon-size: 40px; padding: 16px; } </style> <wired-icon-button class="big"> <mwc-icon>favorite</mwc-icon> </wired-icon-button>设置背景色
--wired-icon-bg-color由WiredBase提供的基础样式(src/wired-base.ts 的BaseCSS)消费:
#overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; }叠加层#overlay覆盖整个按钮区域但pointer-events: none,不拦截点击事件,手绘 SVG 绘制在其上。示例中的.pinkbg即通过该变量实现粉色背景:
<style> .pinkbg { color: red; --wired-icon-bg-color: pink; } </style> <wired-icon-button class="pinkbg"> <mwc-icon>favorite</mwc-icon> </wired-icon-button>颜色跟随 currentColor
值得一提的是,手绘边框描边颜色并非由专门变量控制,而是继承currentColor(见 src/wired-base.ts 中path { stroke: currentColor; })。因此给wired-icon-button设置color即可改变手绘圆圈的线条颜色,示例中的.red { color: red; }正是利用了这一机制。
事件(Events)
click— 按钮被点击时触发。
由于组件内部渲染的是原生<button>元素(src/wired-icon-button.ts 第 63 行),click事件是浏览器原生事件,无需手动派发。使用方式:
const btn = document.querySelector('wired-icon-button'); btn.addEventListener('click', () => { console.log('icon button clicked'); });或者在 HTML 中直接绑定:
<wired-icon-button onclick="alert('clicked')"> <mwc-icon>favorite</mwc-icon> </wired-icon-button>当disabled为true时,原生<button>与样式中的pointer-events: none会共同阻止 click 事件的触发。
渲染原理:从 WiredBase 到手绘椭圆
wired-icon-button的手绘边框并非静态图片,而是运行时由 RoughJS 生成的 SVG。理解其原理有助于正确使用与排查尺寸问题。
模板结构
render()输出的模板(src/wired-icon-button.ts 第 61~70 行):
<button ?disabled="${this.disabled}"> <slot @slotchange="${this.wiredRender}"></slot> <div id="overlay"> <svg></svg> </div> </button>关键点:<slot>负责分发用户放置的图标内容;<div id="overlay">内的<svg>是手绘椭圆绘制的画布;slotchange事件触发时会重新渲染手绘边框,保证图标尺寸变化后边框能自适应。
尺寸计算与绘制
组件继承WiredBase(src/wired-base.ts),实现两个抽象方法:
canvasSize():取内部<button>的getBoundingClientRect()宽高作为画布尺寸(第 72~78 行);draw(svg, size):取宽高中的较小值min,将 SVG 设为正方形,并在中心调用ellipse()绘制手绘椭圆(第 80~85 行):
protected draw(svg: SVGSVGElement, size: Point) { const min = Math.min(size[0], size[1]); svg.setAttribute('width', `${min}`); svg.setAttribute('height', `${min}`); ellipse(svg, min / 2, min / 2, min, min, this.seed); }ellipse()定义于 src/wired-lib.ts 第 108~112 行,内部调用roughEllipse并返回 RoughJS 生成的<path>节点;this.seed是组件实例创建时随机生成的 31 位整数(src/wired-base.ts 第 38 行),用于控制手绘笔画的随机抖动——这也解释了为什么每个组件实例的"手绘感"都不完全一样。
渲染触发机制
WiredBase.updated()在每次属性/状态更新后自动调用wiredRender();wiredRender()会对比当前画布尺寸与上次记录值,仅在尺寸变化时重绘 SVG 并清除旧节点,避免无谓的 DOM 操作(src/wired-base.ts 第 44~59 行)。绘制完成后组件会添加wired-rendered类,配合BaseCSS中:host从opacity: 0过渡到1的规则,实现"先隐藏、绘制完成再显示"的平滑呈现,避免闪烁。
交互反馈细节
源码中还有两处值得注意的交互细节(src/wired-icon-button.ts):
- 按下时手绘路径微缩(第 44~46 行):
button:active path { transform: scale(0.97) translate(1.5%, 1.5%); },模拟实体按钮被按下的效果; - 键盘聚焦时描边加粗(第 47~49 行):
button:focus path { stroke-width: 1.5; },提升无障碍可访问性。
进阶:与 wired-icon 组合使用
除mwc-icon外,wired-icon-button还可以与仓库中的实验性组件wired-icon(位于 experimental/wired-icon)组合,把手绘风格延伸到图标本身:wired-icon能将任意 SVG 图标转换为手绘版本,正好契合 icon button 的"手绘按钮 + 图标"场景。在wired-icon-button内部放置wired-icon,并利用--wired-icon-size控制图标显示尺寸,即可得到内外全部手绘的统一视觉风格。
许可协议
wired-icon-button随 wired-elements 项目以 MIT License 开源,版权归作者 Preet Shihn 所有(见 docs/wired-icon-button.md 与 package.json 的 license 字段)。
小结
wired-icon-button是一个实现简洁但细节完整的手绘图标按钮组件:
- 用法:安装
wired-elements后,以<wired-icon-button>标签 + slot 内容即可使用,支持 npm 模块导入与 CDN 直接加载; - 定制:
disabled属性控制禁用态,--wired-icon-size控制图标字号,--wired-icon-bg-color控制背景色,color继承机制控制手绘描边颜色; - 事件:原生
click事件即点即用; - 原理:基于
WiredBase+ RoughJS 的 SVG 运行时绘制,具备自适应重绘、按下反馈与键盘聚焦样式。
想要更完整地查看所有组件用法,可以参考仓库中的 examples/icon-button.html 示例,以及 docs 目录下其他组件的 API 文档。
- UI组件
- 前端
【免费下载链接】wired-elements
Collection of custom elements that appear hand drawn. Great for wireframes or a fun look.
相关推荐
Material Components Web 图标按钮(Icon Button)完全指南:安装、Toggle 状态管理与源码级实现
Material Components Web 图标按钮(Icon Button)完全指南:安装、Toggle 状态管理与源码级实现 本文聚焦于 Materia
前端UI组件设计系统Ant Design Button 图标按钮实战:icon 属性用法、源码原理与最佳实践
Ant Design Button 图标按钮实战:icon 属性用法、源码原理与最佳实践 Ant Design 的 Button 组件通过 icon 属性即可将
前端UI组件设计系统Shoelace sl-icon-button 图标按钮组件完全指南:属性、事件与样式定制
Shoelace sl icon button 图标按钮组件完全指南:属性、事件与样式定制 sl icon button 是 Shoelace 提供的一种纯图标
UI组件前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考