GrapesJS Canvas 如何禁用内置 Spot 并创建自定义 Spot?
【免费下载链接】grapesjsFree and Open source Web Builder Framework. Next generation tool for building templates without coding项目地址: https://gitcode.com/GitHub_Trending/gr/grapesjs
Canvas spots 是绘制在 GrapesJS 画布上层的元素,用于在组件周围渲染信息(选中框、悬浮提示、拖放定位提示等)。当你想隐藏内置的高亮/选中效果,并在特定组件(例如文本组件)下方渲染自己的按钮或标签时,需要通过canvas.customSpots配置禁用内置 spot,再调用Canvas.addSpot()注册自定义 spot。
以下操作路径来自 Canvas 模块文档,该文档声明适用 GrapesJS v0.21.5 或更高版本,customSpots与 spot 相关 API 在此版本之前不存在。
先了解内置 Spot 的 5 种类型
内置 spot 类型定义在 CanvasSpot.ts 的CanvasSpotBuiltInTypes中,共 5 种:
| 类型 | 作用 |
|---|---|
select | 显示选中组件,并渲染其工具栏项 |
resize | 按组件的 resizable 选项允许缩放组件 |
target | 拖放时高亮组件,指示放置位置 |
hover | 高亮悬浮组件并显示组件名称 |
spacing | 显示组件的 padding / margin 偏移 |
确认你要禁用的是哪一类,再决定下面的配置写法。
在编辑器初始化时禁用内置 Spot
通过主配置对象的canvas属性传入customSpots。customSpots的可选键就是内置 spot 类型(见 config.ts 中的customSpots?: boolean | Partial<Record<CanvasSpotBuiltInTypes, boolean>>):
grapesjs.init({ // ... canvas: { // 只禁用 hover 类型的 spot customSpots: { hover: true }, }, });如果要一次性关闭所有内置 spot 的渲染:
grapesjs.init({ // ... canvas: { customSpots: true, }, });该配置只在初始化时生效,用于控制内置 spot 是否渲染;它不替代自定义 spot 的创建逻辑。
验证某个内置 Spot 是否已被接管
Canvas.hasCustomSpot(type)检查某个内置 spot 是否声明了自定义渲染(即是否被customSpots禁用)。文档给出的示例:在customSpots: { target: true }的初始化配置下:
canvas.hasCustomSpot('select'); // false canvas.hasCustomSpot('target'); // true以上输出为文档示例,用于说明判断结果的含义:被禁用的类型返回true,未禁用的返回false。
创建自定义 Spot
以下示例基于 Canvas 模块文档 中的 "Spots customization" 演示改写:禁用默认的hoverspot,自行渲染高亮矩形,并为选中的text组件渲染一个下方的 "+ Add" 按钮。
注册与移除 Spot
Canvas.addSpot(props)用于添加或更新一个 spot。传入component可以让 spot 的样式坐标在页面滚动或组件更新时被正确更新,这是自定义 spot 定位的前提:
// 添加自定义 spot,type 自定义,component 为要附着的组件 Canvas.addSpot({ type: 'my-text-spot', component }); // 按类型过滤查询 const mySpots = Canvas.getSpots({ type: 'my-text-spot' }); // 移除所有该类型的 spot Canvas.removeSpots({ type: 'my-text-spot' });addSpot的更多用法(含内置类型select、通过复用id更新已有 spot)见 docs/api/canvas.md 中的addSpot条目。
选择变化时的完整逻辑(来自文档演示):
editor.on('component:toggled', (component) => { const Canvas = editor.Canvas; // 先移除所有与自定义类型相关的 spot Canvas.removeSpots({ type: 'my-text-spot' }); if (component === editor.getSelected() && component.is('text')) { Canvas.addSpot({ type: 'my-text-spot', component }); } });自定义容器必须放进 GrapesJS 的 spots 容器
文档明确强调,自定义容器要移动到 GrapesJS 的 spots 容器内,否则不会跟随画布坐标体系:
editor.onReady(() => { editor.Canvas.getSpotsEl().appendChild(spotContainer); });getSpotsEl()返回 spots 容器元素(实现见 Canvas 模块 的getSpotsEl)。
用 spot.getStyle() 定位,并注意 pointer-events
单个 spot 的定位靠spot.getStyle()返回的样式对象(文档 API 示例,见 docs/api/canvas_spot.md):
canvasSpot.getStyle(); // { width: '100px', height: '...', ... }文档演示中将其应用到 spot 元素上::style="spot.getStyle()"。在普通 JS 中等价做法是把spot.getStyle()返回的属性逐一写到元素style上。
还有一个容易踩的坑:spots 容器默认依赖pointer-events: none(见 _gjs_canvas.scss 中__spots的样式),目的是防止 spot 挡住与画布组件的交互。因此自定义 spot 上需要交互的元素必须重新开启指针事件。文档演示中的按钮样式:
.spot-text-btn { background-color: #3b97e3; border: none; color: white; padding: 4px 8px; border-radius: 3px; cursor: pointer; position: absolute; left: 50%; bottom: 0; translate: -50% 120%; pointer-events: auto; /* spots 容器默认 pointer-events: none,需在此重新开启 */ }文档示例:按钮点击后在选中组件后插入新文本
以下为文档演示中的onBtnAdd逻辑,展示自定义 spot 内按钮如何操作编辑器模型:
function onBtnAdd() { const selected = editor.getSelected(); const parent = selected.parent(); if (parent) { parent.append( { type: 'text', components: 'New text component' }, { at: selected.index() + 1 } ); } }监听 spot 的更新
spots 有变化时会触发canvas:spot事件(catch-all),文档演示中用它驱动外部视图重绘:
editor.on('canvas:spot', () => { const spots = editor.Canvas.getSpots(); // 根据 spots 重新渲染你的 spot 容器内容 });细粒度事件还有canvas:spot:add、canvas:spot:update、canvas:spot:remove,均以{ spot }作为参数,完整事件列表见 docs/api/canvas.md 的 Available Events 部分:
editor.on('canvas:spot:add', ({ spot }) => { console.log('Spot added', spot); });限制与注意事项
customSpots只在grapesjs.init()时读取,运行中修改配置不会生效;需要"接管"某个内置 spot 时,先禁用其渲染,再用addSpot添加自己的实现。- 不传
component的 spot 没有组件可附着,getStyle()的定位将依赖boxRect等属性(见 CanvasSpot API 中boxRect的说明)。 spot.getStyle()返回的是position: 'absolute'加translate的定位样式,你的 spot 元素样式不要覆盖这些定位属性。- spots 容器默认
pointer-events: none,任何需要点击/悬停的自定义元素都要显式设置pointer-events: auto。
进一步阅读
- 内置 spot 类型说明与演示:docs/modules/Canvas.md
- Canvas 模块完整 API(
addSpot/getSpots/removeSpots/hasCustomSpot):docs/api/canvas.md - CanvasSpot 属性与
getBoxRect/getStyle/isType:docs/api/canvas_spot.md
【免费下载链接】grapesjsFree and Open source Web Builder Framework. Next generation tool for building templates without coding项目地址: https://gitcode.com/GitHub_Trending/gr/grapesjs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考