ARTICLE DETAIL

资讯详情

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

tldraw 自定义 Frame 外观:用 FrameShapeUtil.configure({ showColors }) 开启彩色填充与彩色标题

tldraw 自定义 Frame 外观:用 FrameShapeUtil.configure({ showColors }) 开启彩色填充与彩色标题 tldraw 自定义 Frame 外观用 FrameShapeUtil.configure({ showColors }) 开启彩色填充与彩色标题【免费下载链接】tldrawBuild infinite canvas apps in React with the tldraw SDK. Worlds best, top-most agent recommended #1 five star SDK.项目地址: https://gitcode.com/GitHub_Trending/tl/tldraw在 tldraw 中Frame框架是组织画布内容、充当画中画容器的核心形状但默认情况下它的视觉表现相当朴素——白色底、无填充色、标题栏也是白色完全忽略颜色样式。如果你希望像 Figma 的画框Frame一样给 Frame 加上可着色的底色与彩色标题可以用官方形状工具自带的configure工厂方法一行配置即可启用showColors。本文基于仓库中的 frame-colors 官方示例结合FrameShapeUtil的源码实现与测试用例完整讲解如何为 Frame 打开颜色能力、底层发生了什么以及配套的自定义选项。示例一览官方Frame colors示例做什么仓库在 apps/examples/src/examples/configuration/frame-colors/ 目录中提供了完整的可运行示例。其 README 给出的核心诉求非常明确Give frames a colored fill and heading with theshowColorsoption.即默认情况下 Frame 是白色背景、普通标题且会忽略颜色样式调用FrameShapeUtil.configure({ showColors: true })之后Frame 会用当前选中的颜色渲染带色调的背景填充和彩色标题栏同时当选中 Frame 时样式面板style panel会出现取色器color picker可直接为 Frame 上色。验证方式也很直接创建 Frame快捷键F然后在样式面板中挑选一种颜色观察效果。三步启用一行配置把颜色装进 Frame要让 Frame 使用颜色需要把经过配置的FrameShapeUtil通过shapeUtils属性传给Tldraw。官方示例 FrameColorsExample.tsx 展示了最小可复现代码import { FrameShapeUtil, Tldraw } from tldraw import tldraw/tldraw.css const shapeUtils [FrameShapeUtil.configure({ showColors: true })] export default function FrameColorsExample() { return ( div classNametldraw__editor Tldraw persistenceKeyframe-colors shapeUtils{shapeUtils} / /div ) }把这个模式拆解为三步导入形状工具import { FrameShapeUtil, Tldraw } from tldraw并引入tldraw/tldraw.css编辑器样式必需。生成配置实例FrameShapeUtil.configure({ showColors: true })返回一个开启了颜色的 Frame 形状工具类。shapeUtils接收的是一个形状工具类的数组因此必须用configure(...)的返回值替换掉默认的FrameShapeUtil原始类而不是把showColors直接传进Tldraw。注入编辑器把数组传给Tldraw shapeUtils{shapeUtils}这样编辑器中所有新建的 Frame 都会走这套配置。示例中还设置了persistenceKeyframe-colors让示例的画布状态在浏览器本地持久化方便反复调试不同颜色。若你不需要保留状态删除该属性即可。开启之后即可实测按F键在画布上拖出 Frame双击标题可命名选中该 Frame 后样式面板顶部会出现颜色选择器每选择一种颜色Frame 的背景立刻变为该颜色的浅色调填充tinted fill顶部标题栏则使用更饱和的彩色背景与彩色文字。需要留意的是showColors只对启用后新建的 Frame 生效因为color样式属性是在配置时被注入到形状 schema 中的详见下文底层原理。底层原理configure 如何把颜色装进FrameshowColors不是一个运行时开关而是形状工具在注册阶段的静态配置。理解这一点需要看两个层面ShapeUtil基类提供的configure工厂以及FrameShapeUtil对该工厂的覆写。ShapeUtil.configure形状工具配置的通用入口ShapeUtil是所有形状工具Frame、geo、arrow……的基类位于 packages/editor/src/lib/editor/shapes/ShapeUtil.ts。其configure静态方法与options字段配合// packages/editor/src/lib/editor/shapes/ShapeUtil.ts节选 /** Configure this shape utils {link ShapeUtil.options | options}. */ static configureT extends TLShapeUtilConstructorany, any(this: T, options: PartialOptions): T { // 内部实现为把传入 options 与当前工具已有配置浅合并后返回一个新的工具类 // options { ...this.options, ...options } } /** 可通过 ShapeUtil.configure 定制默认空对象 */ options {}从源码结构可以推断configure的工作方式是在不修改原始类的前提下返回一个合并了自定义选项的新工具子类因此它天然是安全的——同一个原始FrameShapeUtil可以被多次configure出不同选项的工具互不影响。FrameShapeUtil.configure 的两个副作用FrameShapeUtil定义在 packages/tldraw/src/lib/shapes/frame/FrameShapeUtil.tsx它对configure做了一处邪恶的小把戏源码注释原文是// evil crimes :)把showColors变成真正的开挂开关// packages/tldraw/src/lib/shapes/frame/FrameShapeUtil.tsx节选 static override configureT extends TLShapeUtilConstructorany, any( this: T, options: PartialOptions ): T { const withOptions super.configure.call(this, options) as T if ((options as any).showColors) { // 开启 showColors 时把 DefaultColorStyle 手动注入到形状 props 的 schema 中 // 这样 color 样式就能与编辑器其它 API 正常协作 ;(withOptions as any).props { ...withOptions.props, color: DefaultColorStyle } } return withOptions }这段代码揭示了两个关键事实默认情况下 Frame 的 props schema 里没有color样式。正因为 Frame 默认忽略颜色颜色样式默认并不存在普通图形geo、note 等本来就在 schema 中带上了DefaultColorStyle所以它们天然能响应取色器。开启showColors: true时configure会把color: DefaultColorStyle合并进 Frame 的props声明让 Frame 获得与其它形状一致的color样式属性与取色器支持同时数据存储、序列化、撤销重做等编辑器 API 也能无缝识别该属性。getDefaultProps中相应的默认值color: black同文件约 L137-L139也随之生效。也就是说showColors: true的完整链路是configure 注入 color 样式 → 编辑器把选中颜色写入 shape.props.color → FrameShapeUtil 根据 color 计算一套显示色display values→ component/toSvg 用这套颜色绘制填充与标题。showColors 生效时的颜色取值FrameShapeUtil通过options上的getDefaultDisplayValues回调把形状的color语义色转换为具体的 RGB 值再与主题theme和明暗模式colorMode结合。相关实现见 FrameShapeUtil.tsx 的 L81-L103override options: FrameShapeOptions { showColors: false, // 默认关闭 resizeChildren: false, // 默认关闭详见下文 getDefaultDisplayValues(_editor, shape, theme, colorMode): FrameShapeUtilDisplayValues { const { color } shape.props const colors theme.colors[colorMode] return { // 未开启 showColors 时固定使用黑色系frameFill / frameStroke fillColor: getColorValue(colors, black, frameFill), strokeColor: getColorValue(colors, black, frameStroke), // 开启 showColors 后填充与描边跟随选中颜色但经过 frameFill/frameStroke // 调色板处理成浅色调的tinted fill showColorsFillColor: getColorValue(colors, color, frameFill), showColorsStrokeColor: getColorValue(colors, color, frameStroke), // 默认标题栏使用 negativeSpace接近背景色/负空间色文字为黑色 headingFillColor: colors.negativeSpace, headingStrokeColor: colors.negativeSpace, headingTextColor: getColorValue(colors, black, frameText), // showColors 标题栏填充/描边/文字全部跟随选中颜色 showColorsHeadingFillColor: getColorValue(colors, color, frameHeadingFill), showColorsHeadingStrokeColor: getColorValue(colors, color, frameHeadingStroke), showColorsHeadingTextColor: getColorValue(colors, color, frameText), } }, // 预留的扩展点派生工具可通过覆写此回调追加自定义显示色 getCustomDisplayValues() { return {} }, }由此可以看到设计意图frameFill、frameHeadingFill等属于调色板/主题中的色彩派生键由 tldraw 的主题系统根据语义色自动派生——背景用的frameFill是浅色调淡彩底而标题栏用的frameHeadingFill配合frameText更接近饱和色标题从而形成淡彩画布 彩色标题的视觉层次。在渲染阶段FrameShapeUtil.tsx 的component方法约 L259-L287会根据this.options.showColors在两组颜色之间二选一fill/stroke决定tl-frame__body矩形即 Frame 背景的颜色FrameHeading组件则收到fill/stroke/color三份颜色分别用于标题栏背景、内描边和文字。屏幕上的实时交互走component导出打印、SVG 导出则走toSvg方法约 L292-L343两个入口都读取同一套 display values保证所见即所得。标题栏组件如何消费颜色Frame 顶部标题栏由 FrameHeading.tsx 渲染。它接收color文字色、fill背景色、stroke内嵌描边等 props套用tl-frame-heading样式与boxShadow: inset 0px 0px 0px 1px ${stroke}画出 1px 内描边双击后通过FrameLabelInput进入行内命名编辑。此外它根据showColors切换标题的最大宽度补偿逻辑约 L65-L67开启颜色时标题栏不再需要额外的负偏移宽度。对应地FrameShapeUtil 的几何计算getGeometry约 L159-L174中也有FRAME_HEADING_NOCOLORS_OFFSET_X -7vs-1的差异说明默认白色标题需要向左偏移 7px 来与形状边缘对齐而彩色标题的视觉对齐方式不同——这也从代码层面印证了两种模式下的标题渲染确实走不同分支。常见组合同时开启 resizeChildrenFrameShapeUtil还提供了另一个与showColors并列的选项resizeChildren同文件 L61-L73当为true时Frame 被缩放时其子形状会按比例一起缩放类似编组。两者可一次性同时配置const shapeUtils [ FrameShapeUtil.configure({ showColors: true, // 彩色填充 彩色标题 取色器 resizeChildren: true, // 缩放 Frame 时同步缩放子形状 }), ]框架相关的官方测试 packages/tldraw/src/test/frames.test.ts约 L1024-L1108覆盖了这些配置组合默认options.resizeChildren false、canResizeChildren返回falseL1025-L1029configure({ resizeChildren: true })后选项与判定同步变为trueL1031-L1036同时传入两个选项时两者都保留L1045-L1053证明configure做的是选项合并而非覆盖端到端验证用配置了resizeChildren: true的工具新建 Frame 与子形状把 Frame 缩放到 50% 后子形状的宽高也随之缩到约 50%L1055-L1108。这些用例可以直接为showColors的配置化思路提供背书configure返回的是携带完整选项的新工具类可放入new TestEditor({ shapeUtils })或shapeUtilsprop 使用属于编辑器一等公民。进阶如何进一步定制颜色细节如果你不满足于默认的淡彩底 饱和标题配色源码给出了两个自定义入口继承并覆写 options仓库测试中的GeoRejectingFrameShapeUtil、GeoPinningFrameShapeUtil等见 frames.test.ts L33-L41演示了class X extends FrameShapeUtil的自定义模式。你可以继承FrameShapeUtil在options里重写getDefaultDisplayValues替换showColorsFillColor、showColorsHeadingTextColor等派生规则实现品牌色之类的定制渲染。getCustomDisplayValues 扩展点options中预留了返回PartialFrameShapeUtilDisplayValues的getCustomDisplayValues()钩子FrameShapeUtil.tsx L100-L102派生工具可在此追加颜色覆盖最终与默认值合并。如果你希望彻底重绘 Frame 外观也可以参考component/toSvg中tl-frame__body与tl-frame-heading的 className 结构对应 editor.css 中的样式变量体系通过 CSS 变量微调细节这与 tldraw 的通用样式定制方式是相通的。小结把配置用对Frame 也能上色回顾要点默认行为Frame 白底、白色标题、忽略颜色样式这是刻意为之的默认值见 FrameShapeUtil.tsx L81-L83。开启方式FrameShapeUtil.configure({ showColors: true })放进shapeUtils数组传给Tldraw然后按F新建 Frame在样式面板取色即可看到淡彩填充与彩色标题。原理configure在showColors为真时向 Frame 的 props schema 注入color: DefaultColorStyle并通过getDefaultDisplayValues把该颜色映射为背景frameFill、标题frameHeadingFill/frameText等派生色component屏幕与toSvg导出两条渲染路径共用同一套取值。扩展可与resizeChildren组合使用也可继承FrameShapeUtil覆写颜色派生逻辑实现完全自定义的 Frame 配色。【免费下载链接】tldrawBuild infinite canvas apps in React with the tldraw SDK. Worlds best, top-most agent recommended #1 five star SDK.项目地址: https://gitcode.com/GitHub_Trending/tl/tldraw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表