https://github.com/lloydzhou/x6-html-shape
x6 html shape without foreignObject. x6-html-shape, x6-react-shape, x6-vue-shape, x6-svelte-shape all in one!
https://github.com/lloydzhou/x6-html-shape
antv-x6 html portal react shape svelte teleport vue x6-html-shape x6-react-shape x6-svelte-shape x6-vue-shape
Last synced: 9 days ago
JSON representation
x6 html shape without foreignObject. x6-html-shape, x6-react-shape, x6-vue-shape, x6-svelte-shape all in one!
- Host: GitHub
- URL: https://github.com/lloydzhou/x6-html-shape
- Owner: lloydzhou
- License: mit
- Created: 2023-04-11T16:42:38.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-08-28T07:15:29.000Z (8 months ago)
- Last Synced: 2025-04-01T08:36:48.660Z (19 days ago)
- Topics: antv-x6, html, portal, react, shape, svelte, teleport, vue, x6-html-shape, x6-react-shape, x6-svelte-shape, x6-vue-shape
- Language: TypeScript
- Homepage:
- Size: 390 KB
- Stars: 11
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-x6 - x6-html-shape - 非官方版自定义组件:可选择不依赖foreignObject挂载自定义组件,支持react18/react17/react-portal/vue2/vue3/vue-teleport/svelte等7种方式自定义节点 (Frameworks / HTML shape)
README
# x6-html-shape
html shape for [@antv/x6](https://github.com/antvis/X6)
![]()


## online demo
[svelte codesandbox demo](https://codesandbox.io/s/x6-html-shape-svelte-5t1r9r)
[vue codesandbox demo](https://codesandbox.io/s/x6-html-shape-vue-xvvlsh)
[react codesandbox demo](https://codesandbox.io/s/html-shape-for-x6-0y71sv)

## example
```
import { register } from "x6-html-shape";register({
shape: "html-shape-for-react",
render: (node, graph, container) => {
const root = createRoot(container);
root.render();
return () => root.unmount();
},
width: 100,
height: 40
});const graph = new Graph({
container: this.container,
background: {
color: "#F2F7FA"
}
});graph.addNode({
shape: "html-shape-for-react",
x: 100,
y: 200,
label: 'rect',
})```
## 事件穿透
1. 由于DOM层级关系,html-shape实现的节点总是在svg上层
2. 通过给`x6-html-shape-container`设置`pointer-events: none`屏蔽这一层的交互,使得鼠标事件能穿透到svg内部节点。但是`x6-html-shape-node`内部有一些元素是需要交互的,所以给节点打开
3. 至于事件穿透使用`forwardEvent`将节点内部的鼠标事件转发到对应的`x6-node`内部```
export function forwardEvent(eventType, fromElement, toElement) {
fromElement.addEventListener(eventType, function (event) {
toElement.dispatchEvent(new event.constructor(event.type, event));
event.preventDefault();
event.stopPropagation();
});
}
```# react
## react18
```
import createRender from 'x6-html-shape/dist/react'const render = createRender(Component)
register({
shape: 'react18-node',
render,
width: 100,
height: 40,
})
```## react17
```
import createRender from 'x6-html-shape/dist/react17'const render = createRender(Component)
register({
shape: 'react17-node',
render,
width: 100,
height: 40,
})
```## react-portal
```
import { register } from 'x6-html-shape'
import createRender from 'x6-html-shape/dist/portal'
// 1. createRender using Component
const [render, Provider] = createRender(Component)
2. register node
register({
shape: 'react-portal-node',
render,
width: 100,
height: 40,
})// 3.render Provider in react app before call graph.addNode
// 4. add Node
graph.addNode({
shape: 'react-portal-node',
id: 'node1',
label: 'node1',
x: 100,
y: 100,
})
```# vue
## vue3
```
import createRender from 'x6-html-shape/dist/vue'const render = createRender(Component)
register({
shape: 'vue3-node',
render,
width: 100,
height: 40,
})
```## vue2
```
import createRender from 'x6-html-shape/dist/vue2'const render = createRender(Component)
register({
shape: 'vue2-node',
render,
width: 100,
height: 40,
})
```## vue3-teleport
```
import { register } from 'x6-html-shape'
import createRender from 'x6-html-shape/dist/teleport'
// 1. createRender using Component
const [render, Provider] = createRender(Component)
2. register node
register({
shape: 'vue3-teleport-node',
render,
width: 100,
height: 40,
})// 3.render Provider in react app before call graph.addNode
// 4. add Node
graph.addNode({
shape: 'vue3-teleport-node',
id: 'vue3-teleport-node',
label: 'vue3 teleport node',
x: 100,
y: 100,
})
```# svelte
```
import { register } from 'x6-html-shape'
import createRender from 'x6-html-shape/dist/svelte'
// 1. createRender using Component
const render = createRender(Component)
2. register node
register({
shape: 'svelte-node',
render,
width: 100,
height: 40,
})// 3. add Node
graph.addNode({
shape: 'svelte-node',
label: 'svelte node',
x: 100,
y: 100,
})
```