本文系 D3.js 实战系列第二弹,主要讲述了如何让 svg 图形能够监听鼠标的事件进行缩放和平移,以及如何将对图形的初始化进行操作。
基础缩放
基本思想
- 创建 svg 元素及内部矩形元素
- 创建缩放函数
- 给 svg 元素绑定缩放事件
实例展示
1 2 3 4 5 6 7 8 9 10 11 12 13
| // 创建一个svg元素,并设置宽高 const svg = d3.select('#canvas').append('svg').attr('width', 500).attr('height', 500);
// 创建一个矩形元素 const rect = svg.append('rect').attr('width', 200).attr('height', 100).attr('fill', 'red');
// 创建缩放函数 const zoom = d3.zoom().on('zoom', (e) => { rect.attr('transform', e.transform); // 更新矩形的位置 });
// 给svg元素绑定缩放事件 svg.call(zoom);
|
初始图形居中
业务需求场景
现有一场景,绘制的 svg 的图的左上角坐标不是(0,0),并且绘制的 svg 图大于屏幕中的容器,需要将 svg 图初始展示缩小至全图可见的状态,且不能超过容器的范围。
基本思想
- 获取容器的长宽
- 获取 svg 图形的长宽和左上角的坐标
- 计算初始缩放比 scale 的值
- 计算在容器中居中所需的平移量
- 给 svg 绑定缩放事件
实例展示
现有的 div 容器:
1
| <div id="canvas" style={{ width: '1200px', height: '1200px' }}></div>
|
在实现监听缩放事件的同时,实现首次缩放和首次平移至容器中心:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| let svg = d3.select('#canvas').append('svg').attr('width', '1200px').attr('height', '1200px');
const element = document.getElementById('canvas');
const svgElement = svg.node()?.getBBox(); if (!element || !svgElement) return;
const boxWidth = element.clientWidth; const boxHeight = element.clientHeight; const svgWidth = svgElement.width; const svgHeight = svgElement.height;
const scaleX = boxWidth / svgWidth; const scaleY = boxHeight / svgHeight; const scale = Math.min(scaleX, scaleY);
const translateX = (boxWidth - svgWidth * scale) / 2 - svgElement.x * scale; const translateY = (boxHeight - svgHeight * scale) / 2 - svgElement.y * scale;
const handleZoom = (e: any) => { d3.selectAll('svg g').attr('transform', e.transform); }; let zoom = d3.zoom().on('zoom', handleZoom) as any; const initIdentity = d3.zoomIdentity.translate(translateX, translateY).scale(scale);
svg.call(zoom.transform, initIdentity);
svg.call(zoom);
|
结语
本文只是一种业务场景的实现,可以为其他场景提供参考思路,当然 zoom 的监听函数 handleZoom 也可以按业务需求自定义。此外,d3.zoom 还有其他很多 API 规范 zoom 的行为,去d3-zoom 官网可以查看更多。