4.7 自定义节点-html
2021-12-24 本文已影响0人
skoll
简介
1 .可以插入节点后,我们几乎就可以做任意的样式定制了,还有一些逻辑相关比如点击收起这种,我们只要把相关的数据传递给html节点,然后让他来渲染就可以了,包括删除节点那些操作.打开了新世界
2 .原理:SVG中的一个特殊元素foreignObject元素,在这个元素中可以内嵌任何XHTML元素,所以我们可以借助这个元素来渲染HTML元素和React组件来渲染想要的操作到位置
3 .将节点的shape属性指定为HTML,就可以通过html属性来指定需要渲染的html元素或一个返回HTML元素的方法
4 .关键:当HTML属性为HTML元素或函数时,将不能通过graph.toJSON方法导出画布
5 .https://codesandbox.io/s/icno7?file=/src/app.tsx
框架
1 .单个节点特别复杂,有需要交互的操作的时候最需要
2 .比如点击收起,手风琴.框架以及html最关键的是这里吧
3 .
渲染React节点
1 .@antv/x6-react-shape 包
2 .通过 component 属性来指定渲染节点的 React 组件
3 .优化渲染之后在考虑把,有专门的hook,可以走useMemo那一套
挂载React节点,方便导出数据显示
1 .注册React节点到Graph里面
// 注册 React 组件
Graph.registerReactComponent('my-component1', <MyComponent text="Hello" />)
// 注册返回 React 组件的函数
Graph.registerReactComponent('my-component2', (node) => {
const data = node.getData()
return (<div>{data.text}</div>)
})
2 .添加的节点里面也要通知
graph.addNode({
x: 40,
y: 40,
width: 100,
height: 40,
shape: 'react-shape',
component: 'my-component1',
})
自定义开关节点
1 .电路联通的开关,组合单个SVG节点,构成组合图案
image.png
2 .其实就是三根线,中间那个根线角度发生变化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://unpkg.com/@antv/x6/dist/x6.js"></script>
<style>
.my-btn{
position: relative;
display: inline-block;
padding: 10px 20px;
color: #03e9f4;
font-size: 16px;
text-decoration: none;
text-transform: uppercase;
overflow: hidden;
transition: .3s;
margin-top: 40px;
letter-spacing: 3px
}
.my-btn:hover {
background: #03e9f4;
color: #fff;
border-radius: 5px;
box-shadow: 0 0 5px #03e9f4,
0 0 25px #03e9f4,
0 0 50px #03e9f4,
0 0 100px #03e9f4;
}
</style>
</head>
<body>
<h3>多边形</h3>
<div id="container">
</div>
<script>
const graph=new X6.Graph({
container:document.getElementById('container'),
width:800,
height:600,
grid:true,
})
const switchCenter={
x:35,
y:-2
}
const switchOpen=`rotate(-30 ${switchCenter.x} ${switchCenter.y})`
const switchClose=`rotate(-12 ${switchCenter.x} ${switchCenter.y})`
graph.addNode({
x:200,
y:200,
markup:[
{
tagName:'g',
//这里还是一种集合,里面包含两个独立的元素
selector:'left-group',
children:[
{
tagName:'rect',
selector:"left",
//下面以及后面的操作也是看这里的样式
groupSelector:'line',
attrs:{
x:0,
y:0,
}
},{
tagName:'circle',
selector:'lco',
groupSelector:'co',
attrs:{
cx:30
}
},
//大圆,黑色
{
tagName:'circle',
selector:'lci',
groupSelector:'ci',
attrs:{
cx:30
}
}
//小圆,白色
]
},
//第一条线,其实也算是不在同一个联通关系的,可以拆分的操作
{
tagName:"rect",
selector:'switch',
groupSelector:'line'
},
//右边的横线
{
tagName:'g',
selector:"right-group",
children:[
{
tagName:'rect',
selector:'right',
groupSelector:'line',
attrs:{
x:70,
y:0,
}
},{
tagName:"circle",
selector:'rco',
groupSelector:'co',
attrs:{
cx:70
}
},{
tagName:'circle',
selector:'rci',
//操作的时候选择器是这个
groupSelector:'ci',
//用来让下边的attrs选到这个
attrs:{
cx:70
}
}
]
}
],
//大量绘制SVG的操作全都是用这种方法
attrs:{
line:{
width:20,
height:2,
fill:"#000",
stroke:'#000'
},
co:{
r:8,
fill:"#000"
},
//大圆,黑色
ci:{
r:4,
fill:'#fff'
},
//小圆,白色.合起来就是一个黑色的环
switch:{
x:35,
y:-2,
width:35,
transform:switchOpen,
}
//连接线的样式.transform有点类似css样式
}
})
graph.on('node:click',({node})=>{
const attrPath='attrs/switch/transform'
const current=node.prop(attrPath)
//获取这个节点的属性: 获取指定路径的属性值
//console.log(node.prop())
//不传参数是获取全部属性
//动画变化版本
//const target=current===switchOpen?switchClose:switchOpen
//node.transition(attrPath, target, {
// interp: (a, b) => {
// const reg = /-?\d+/g
// const start = parseInt(a.match(reg)[0], 10)
// const end = parseInt(b.match(reg)[0], 10)
// const d = end - start
// return (t) => {
// return `rotate(${start + d * t} ${switchCenter.x} ${switchCenter.y})`
// }
// },
//})
//非动画版本
if(current===switchOpen){
node.prop(attrPath,switchClose)
}else{
node.prop(attrPath,switchOpen)
}
})
</script>
</body>
</html>