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>
上一篇下一篇

猜你喜欢

热点阅读