X6 2.0 自定义边实现边上滑动短线

本文介绍了如何在X6图形化环境中使用SVG和自定义边缘实现流畅的滑动效果,以及注意事项,如避免渐变颜色导致部分路线不显示的问题。

 X6 给了无限可能,玩转图形化

节点之间的边上增加一个滑动小球容易,可是效果不理想,滑动不丝滑。利用path实现短线滑动,像一辆小车跑在轨道上。注意不要用渐变颜色,否则可能部分路线不显示,其实没有消失,只是颜色插值问题。

全部代码,保证运行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Comet Edge in X6</title>
    <script src="https://unpkg.com/@antv/x6@2"></script>
    <style>
        #container {
            width: 800px;
            height: 600px;
            border: 1px solid #000;
            display: block;
            margin: auto;
            background-color: #f0f0f0;
        }
    </style>
</head>
<body>


<svg width="400" height="200" style="background:black">
	<svg width="200" height="200">
  <defs>
    <linearGradient id="lineGradient" x1="0%" y1="0%" x2="0%" y2="100%">
      <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(11,222,15);stop-opacity:1" />
    </linearGradient>
  </defs>
  <path d="M 100.01 50 L 100 60" stroke="url(#lineGradient)" stroke-width="1" fill="none"/>


	<path d="M 200 50 V 150 Z" stroke="url(#lineGradient)" fill="none"/>
</svg>

<div id="container" style="background:#190a1a;"></div>

<script>
document.addEventListener('DOMContentLoaded', function() {
    const { Graph } = X6;

    const graph = new Graph({
        container: document.getElementById('container'),
        width: 1900,
        height: 1200,
		background:'#890fea'
    });

  // 在SVG的<defs>部分添加渐变定义
    const svg = graph.view.svg;
    const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
    const linearGradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
    linearGradient.setAttribute('id', 'cometGradient');
    linearGradient.innerHTML = `
		<stop offset="0%" stop-color="rgb(11,222,15)" />
		<stop offset="50%" stop-color="rgb(255,255,255)" />
        <stop offset="100%" stop-color="rgb(11,222,15)"/>
    `;
	 const linearGradient2 = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
    linearGradient.setAttribute('id', 'redCometGradient');
    linearGradient.innerHTML = `
		<stop offset="0%" stop-color="rgb(221,12,15)" />
		<stop offset="50%" stop-color="rgb(255,255,255)" />
        <stop offset="100%" stop-color="rgb(211,12,15)"/>
    `;
    defs.appendChild(linearGradient);
    svg.appendChild(defs);
    

    // 注册自定义边
    Graph.registerEdge('cometEdge', {
        markup: [
            {
                tagName: 'path',
                selector: 'line',
            },
            {
                tagName: 'path',
                selector: 'shortLine',
            },
			/**{
			  tagName: 'polygon',
			  selector: 'polygon',
			},*/
        ],
        attrs: {
            line: {
				stroke: 'green',//1890FF
				strokeWidth: 2,
				connection:true,
				fill:'none',
			},
            shortLine: {
				fill: 'none',
				stroke: 'rgba(11,255,11,0.9)',//'url(#cometGradient)',
				strokeWidth: 2,
				strokeLinecap: 'round',
				d:'M 0 0 L 0 0 Z',
				
			},
        },
    }, true);
	 // 添加节点
    const source = graph.addNode({
        shape: 'circle',
        x: 40,
        y: 40,
        width: 60,
        height: 60,
        attrs: {
            body: {
                fill: '#2ECC71',
                stroke: '#000',
            },
            label: {
                text: 'Start',
                fill: '#333',
            },
        },
    });

    const target = graph.addNode({
        shape: 'circle',
        x: 100,
        y: 140,
        width: 60,
        height: 60,
        attrs: {
            body: {
                fill: '#F39C12',
                stroke: '#000',
            },
            label: {
                text: 'End1',
                fill: '#333',
            },
        },
    });

	 const target2 = graph.addNode({
		shape: 'circle',
		x: 340,
		y: 40,
		width: 60,
		height: 60,
		attrs: {
			body: {
				fill: '#F39C12',
				stroke: '#000',
			},
			label: {
				text: 'End2',
				fill: '#333',
			},
		},
	});
	
	 const target3 = graph.addNode({
		shape: 'circle',
		x: 500,
		y: 50,
		width: 60,
		height: 60,
		attrs: {
			body: {
				fill: '#F39C12',
				stroke: '#000',
			},
			label: {
				text: 'End3',
				fill: '#333',
			},
		},
	});
	 const target4 = graph.addNode({
		shape: 'circle',
		x: 200,
		y: 300,
		width: 60,
		height: 60,
		attrs: {
			body: {
				fill: '#F39C12',
				stroke: '#000',
			},
			label: {
				text: 'End4',
				fill: '#333',
			},
			assetName:'23434',
			port: 123
		},
	});
    // 添加自定义边到图中
    const edge = graph.addEdge({
        shape: 'cometEdge',
        source: source,
        target:target,
		connector: { name: 'rounded' },
    });
	// 添加自定义边到图中
    const edge2 = graph.addEdge({
        shape: 'cometEdge',
        source: source,
        target:target2,
		connector: { name: 'smooth' },
    });
    // 添加自定义边到图中
    const edge3 = graph.addEdge({
        shape: 'cometEdge',
        source: target2,
        target:target3,
		//connector: { name: 'rounded' },
		router: {
			name: 'er',
			args: {
			  offset: 'center',
			},
		},
    });
	// 添加自定义边到图中
    const edge4 = graph.addEdge({
        shape: 'cometEdge',
        source: target,
        target:target4,
		connector: { name: 'rounded' },
    });
	
	const edge1 = graph.addEdge({
	  shape: 'edge', // 使用默认边形状,或者你自定义的边形状
	  source: target3,
	  target: target4,
	  attrs: {
		line: {
		  stroke: '#1890FF',
		  strokeWidth: 2,
		  strokeDasharray: '10,5', // 定义虚线模式
		  strokeDashoffset: 120, // 初始偏移量
		},
	  },
	});
	edge1.transition('attrs/line/strokeDashoffset', 0, {
	  delay: 0, // 延迟开始动画的时间,单位为毫秒
	  duration: 2000, // 动画持续时间,单位为毫秒
	  timing: 'linear', // 动画的时序函数
	  interp: (a, b) => (t) => a + (b - a) * t, // 插值函数
	});
	setTimeout(()=>{
		const edgeView3 = graph.findViewByCell(edge3);
		const connection3  = edgeView3.getConnection();
		const totalLength3 = edgeView3.getConnectionLength();
		const atLength = edgeView3.getPointAtLength(0);
		console.log(edgeView3,connection3,totalLength3,atLength,'||',target2.position());
		
		
		updateShortLine(edge3);
	},1000);
	

	let t = 1;
	const speed = 1;
	


	const update = (edgeParam,offset)=>{
		const edgeView = graph.findViewByCell(edgeParam);
		const connection  = edgeView.getConnection();
		const totalLength = edgeView.getConnectionLength();
		
		
		const shortLineLen = 5;//移动线段的长度
		let startPoint, endPoint;
		edgeParam.attr('shortLine/speed','5');
		//edgeParam.attr('shortLine/stroke','url(#redCometGradient)');
		
		startPoint= edgeView.getPointAtLength(offset);
		offset += speed;
		endPoint = edgeView.getPointAtLength(offset+shortLineLen);
		
		// 移动核心代码
		edgeParam.attr('shortLine', {
			d: `M ${startPoint.x} ${startPoint.y} L ${endPoint.x} ${endPoint.y} Z`,
		});
		
		
		if(totalLength<=offset){//复位
			offset = 0;
		}
		requestAnimationFrame(()=>{
			update(edgeParam,offset);
		})
		
		
		
	}
	setTimeout( () => {
		const edges = graph.getEdges();
		edges.forEach(edge => {
		  if('cometEdge' === edge.shape){
			update(edge,0);
		  }
		  
		});
	
	},500);
	

	
	

	
	
	
});
</script>

</body>
</html>

 预览效果

AntV X6自定义样式有多种方式,以下详细介绍几种常见的方法: #### 基于内置形状自定义 可以通过继承内置的形状,并重写其属性来实现自定义样式。以下是一个自定义直线样式的示例: ```javascript import { Graph, shapes } from '@antv/x6' // 自定义直线 const CustomEdge = shapes.standard.Line.define({ shape: 'custom-line-edge', attrs: { line: { stroke: '#FF6B6B', // 的颜色 strokeWidth: 3, // 的宽度 targetMarker: { name: 'classic', size: 8, fill: '#FF6B6B' // 箭头颜色 } } } }) // 注册自定义 Graph.registerEdge('custom-line-edge', CustomEdge) // 创建画布 const graph = new Graph({ container: document.getElementById('container'), width: 800, height: 600 }) // 添加自定义到画布 const edge = graph.addEdge({ shape: 'custom-line-edge', source: { x: 100, y: 100 }, target: { x: 200, y: 200 } }) ``` #### 使用 HTML 自定义样式 如果需要更复杂的样式,可以使用 HTML 来创建自定义。以下是一个示例: ```javascript import { Graph } from '@antv/x6' // 创建 HTML 内容 const html = ` <div style="background-color: #FFD700; width: 3px; height: 100%;"></div> ` // 创建画布 const graph = new Graph({ container: document.getElementById('container'), width: 800, height: 600 }) // 添加 HTML 到画布 const edge = graph.addEdge({ shape: 'html-edge', source: { x: 100, y: 100 }, target: { x: 200, y: 200 }, markup: [ { tagName: 'foreignObject', selector: 'body', attrs: { width: '100%', height: '100%' } } ], html: html }) ``` #### 动态样式 可以通过事件监听来动态改变的样式。以下是一个示例,当鼠标悬停在边上时改变的颜色: ```javascript import { Graph, shapes } from '@antv/x6' // 创建画布 const graph = new Graph({ container: document.getElementById('container'), width: 800, height: 600 }) // 添加 const edge = graph.addEdge({ shape: 'standard.line', source: { x: 100, y: 100 }, target: { x: 200, y: 200 }, attrs: { line: { stroke: '#333', strokeWidth: 2 } } }) // 监听鼠标悬停事件 edge.on('mouseenter', () => { edge.attr('line/stroke', '#FF6B6B') }) // 监听鼠标移出事件 edge.on('mouseleave', () => { edge.attr('line/stroke', '#333') }) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值