GrapesJS Canvas 如何禁用内置 Spot 并创建自定义 Spot?
2026/9/13 9:06:55 网站建设 项目流程

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属性传入customSpotscustomSpots的可选键就是内置 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:addcanvas:spot:updatecanvas: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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询