【前端学习】AntV G6-07 深入图形与图形分组、自定义节点、节点动画(上、中)

课程链接

AntV G6:深入图形与图形分组、自定义节点、节点动画(上)_哔哩哔哩_bilibili

AntV G6:深入图形与图形分组、自定义节点、节点动画(中)_哔哩哔哩_bilibili


图形分组 Group | G6 (antgroup.com)

自定义元素 G6.registerX | G6 (antgroup.com)

图形样式属性 Shape Attr | G6 (antgroup.com)


通过G6.registerNode方法,绘制基于 rect 的自定义卡片,并且提到:

1. 如果要更新自定义node,需要注意重绘时 update方法 是否要重写,有2个方法可以解决

2. 更新节点时候需要注意位置变形的问题,通过设置相对的x,y解决

3. KeyShape的draggable属性,可以控制是否这部分可以被拖拽

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>05 深入图形与图形分组、自定义节点、节点动画</title>
	<!-- 引入 G6 -->
	<script src="https://gw.alipayobjects.com/os/lib/antv/g6/4.3.11/dist/g6.min.js"></script>
</head>

<body>
	<div id="container"></div>
	<script>
		const ICON_MAP = {
			a: 'https://ts2.cn.mm.bing.net/th?id=ODLS.70f7e605-0e03-4ed5-8935-b48cb3ee855f&w=32&h=32&o=6&pid=AdsPlus',
			b: 'https://ts2.cn.mm.bing.net/th?id=OADD2.7353136438133_1J11L5COSQ5ZDZ3TDJ&w=32&h=32&o=6&pid=21.2'
		}

		const data = {
			nodes: [
				{
					id: 'node2',
					title: 'node2',
					error: false,
					nodeType: 'a',
					nodeLevel: 0,
					panels: [
						{ title: '成功率', value: '11%' },
						{ title: '耗时', value: '50s' },
						{ title: '错误数', value: '12' },
					],
					x: 100,
					y: 100
				},
				{
					id: 'node3',
					title: 'node3',
					error: true,
					nodeType: 'b',
					nodeLevel: 0,
					panels: [
						{ title: '成功率', value: '19%' },
						{ title: '耗时', value: '10s' },
						{ title: '错误数', value: '8' },
					],
					x: 100,
					y: 200
				},
			],
		}

		// 第1个参数,卡片节点的名字
		// 第2个参数,options
		// 第3个参数,继承的节点类型
		G6.registerNode('card-node', {
			// 复写 draw 方法
			// 第1个参数,这个节点的配置
			// 第2个参数,这个节点的图形分组,现在的目的是往这个图形分组中去增加图形
			draw: (cfg, group) => {
				const color = cfg.error ? '#F4664A' : '#30BF78';
				const x = -200 / 2;
				const y = -60 / 2;
				const keyShape = group.addShape('rect', {
					attrs: {
						x,
						y,
						width: 200,
						height: 60,
						stroke: color,
						fill: '#fff',
						radius: 2
					},
					name: 'card-node-keyshape'
				});
				const titleRect = group.addShape('rect', {
					attrs: {
						x,
						y,
						width: 200,
						height: 20,
						stroke: color,
						fill: color,
						radius: 2
					},
					name: 'card-node-title-back',
					draggable: true  // G6为keyShape添加了draggable属性,为true时这部分图形才可以被拖拽
				});
				const image = group.addShape('image', {
					attrs: {
						x: x + 2,
						y: y + 2,
						width: 14,
						height: 14,
						img: ICON_MAP[cfg.nodeType],
						cursor: 'pointer'
					}
				});
				const title = group.addShape('text', {
					attrs: {
						text: cfg.title,
						x: x + 30,
						y: y + 4,
						fill: '#fff',
						textBaseline: 'top'
					},
					name: 'card-node-title'
				});
				let panelX = - x + 40;  // 疑问点:视频里这里不需要负号
				const subGroup = group.addGroup();
				cfg.panels?.forEach((panel, i) => {
					const panelTitle = subGroup.addShape('text', {
						attrs: {
							text: panel.title,
							x: x + panelX,
							y: y + 38,
							fill: '#ccc',
							textAlign: 'center'
						},
						name: `card-node-panel-title-${i}`
					})
					subGroup.addShape('text', {
						attrs: {
							text: panel.value,
							x: x + panelX,
							y: y + 54,
							fill: '#111',
							textAlign: 'center'
						},
						name: `card-node-panel-title-${i}`
					})

					// 根据前面图形的大小来放置后面的图形
					const titleBBox = panelTitle.getBBox();
					// console.log(titleBBox);
					panelX = titleBBox.maxX + 40;

					// panelX += 60;
				})

				return keyShape;
			},
			// update: undefined
			// 如果重写了update方法,渲染层面就会走这个update方法,而不会清空整个节点去重新绘制
			update: (cfg, item) => {
				const group = item.getContainer(); // 获取图形容器
				const titleShape = group.find(ele => ele.get('name') === 'card-node-title') // 通过name属性找到需要更新的图形
				// titleShape.attr('text', cfg.title); // 更新title里的text字段,attr 用来更新某个绘图属性
				// 批量更新
				titleShape.attr({
					text: cfg.title,
					// ... 其他属性
				})

			}
		}, 'rect')
		// 如果要更新node,方法1:取消继承自 rect
		// 如果要更新node,方法2:在继承自 rect 的前提下,设置update方法为undefined,重绘时就会走自定义的draw

		const width = document.getElementById('container').scrollWidth
		const height = document.getElementById('container').scrollHeight || 500

		const graph = new G6.Graph({
			container: 'container',
			width,
			height,
			fitCenter: true,
			// fitView: true,
			// 模式
			modes: {
				// 拖拽画布 drag-canvas
				// 拖拽节点 drag-node 
				// 缩放画布 zoom-canvas
				default: ['drag-canvas', 'drag-node'],
			},
			defaultNode: {
				type: 'card-node'
			}

		})


		graph.data(data);
		graph.render();

		graph.updateItem(graph.getNodes()[0], {
			// 如果要更新node,方法1:取消继承自 rect
			// 如果要更新node,方法2:在继承自 rect 的前提下,设置update方法为undefined,重绘时就会走自定义的draw
			title: 'new-title~~'
		})

		if(typeof window !== 'undefined')
			window.onresize = () => {
				if(!graph || graph.get('destroyed')) return;
				if(!container || !container.scrollWidth || !container.scrollHeight)
				graph.changeSize(container.scrollWidth, container.scrollHeight);
			}
	</script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值