d3.zoom还是一个很强大得zoom工具包(放大、缩小、平移), 不只适合用在svg, 可以应用再dom、canvas等需要zoom得任何场景
绘制基础图形用来做zoom来用。 效果图如下:
<!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>
<style>
#container {
width: 500px;
margin: 50px auto 0;
}
</style>
</head>
<body>
<div id="container">
</div>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
const svg = d3.select('#container')
.append('svg')
.attr('width', 500)
.attr('height', 500);
const container = svg.append('g'); // group
const data = [
{ id: 1, fill: 'black', x: 10, y: 10 },
{ id: 2, fill: 'black', x: 50, y: 50 },
{ id: 3, fill: 'black', x: 100, y: 70 },
{ id: 4, fill: 'black', x: 20, y: 100 }
];
draw(); // 绘制
function draw() {
const update = container.selectAll('rect')
.data(data, d => d.id);
//修改层
update.attr('x', (d, idx) => d.x)
.attr('y', (d, idx) => d.y)
.attr('fill', (d) => d.fill)
//渲染层
const enter = update.enter();
//删除层
const exit = update.exit();
enter.append('rect')
.attr('width', 20)
.attr('height', 20)
.attr('id', d => d.id)
.attr('x', (d, idx) => d.x)
.attr('y', (d, idx) => d.y)
.attr('fill', (d) => d.fill)
.attr('stroke', 'blue')
.attr('strokeWidth', 1)
exit.remove()
}
</script>
给画布绑定上zoom(平移、放大、缩小)
code
let transform = {
x: 0,
y: 0,
k: 1,
};
let zoom = null;
const zoomMin = 0.3;
const zoomMax = 5;
const container = svg.append('g')
.attr(
'transform',
`translate(${transform.x},${transform.y} ) scale(${transform.k})`,
); // 绑定transform
function bindZoom() { // 绑定zoom
zoom = d3.zoom()
.scaleExtent([zoomMin, zoomMax]) // 设置最大、最小zoom范围
.on('zoom', function () {
transform = d3.zoomTransform(this); // 使用改方法获取到zoom当前得新值{x,y,k}
container.attr('transform', transform); // 重新绑定新得transform
console.log(transform, 'transform...')
});
svg.call(zoom).on('dblclick.zoom', null); // 把方法指定再svg
}
效果图:
解除zoom绑定 code
function stopZoom() { //解除zoom绑定
svg.on('mousedown.zoom', null);
svg.on('mousemove.zoom', null);
svg.on('dblclick.zoom', null);
svg.on('touchstart.zoom', null);
}
实现放大、缩小按钮功能键
code
function zoomIn() { // 缩小
svg.transition().call(zoom.scaleBy, 0.7);
};
function zoomOut() { //放大
svg.transition().call(zoom.scaleBy, 1.3);
};
效果图:
实现容器再画布得中间显示(再画布得正中间位置)
code
function zoomCenter() {
const containerX = data.map((item) => item.x);
const containerY = data.map((item) => item.y);
const minX = Math.min.apply(null, containerX);
const maxX = Math.max.apply(null, containerX);
const minY = Math.min.apply(null, containerY);
const maxY = Math.max.apply(null, containerY);
const containerGroupBBox = { // 用数据获取到当前group得w、h、x、y
width: maxX - minX,
height: maxY - minY,
x: minX,
y: minY,
};
const scaleX = width / containerGroupBBox.width;
const scaleY = height / containerGroupBBox.height;
let k = Math.min(scaleX, scaleY) * 0.7;
k = Math.max(k, zoomMin);
k = Math.min(k, zoomMax); // 用画布大小 / 当前svg得大小 获取到比例值
// 算出居中得x、y坐标(往俩盒子 一个大盒子(画布)和另外一个盒子(group)怎么让group居中呢!!!
// 用画布自身得一半 减去 gropu得一半 * 缩放 K, 再减去gropu得translate
const translateByX = width / 2 - (containerGroupBBox.width / 2) * k - (containerGroupBBox.x * k);
const translateByY = height / 2 - (containerGroupBBox.height / 2) * k - (containerGroupBBox.y * k);
const transform = d3.zoomIdentity
.translate(translateByX, translateByY)
.scale(k); // 获取到目标 transform
svg.transition() // 过渡效果
.duration(100) // 100ms
.call(zoom.transform, transform);
}
效果图如下:
<!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>
<style>
#container {
width: 500px;
margin: 50px auto 0;
}
</style>
</head>
<body>
<div id="container">
<button onclick="zoomOut()">放大</button>
<button onclick="zoomIn()">缩小</button>
<button onclick="zoomCenter()">居中</button>
</div>
</body>
</html>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
let transform = {
x: 0,
y: 0,
k: 1,
};
let zoom = null;
const zoomMin = 0.3;
const zoomMax = 5;
const width = 500;
const height = 500;
const svg = d3.select('#container')
.append('svg')
.attr('width', width)
.attr('height', width);
const container = svg.append('g')
.attr(
'transform',
`translate(${transform.x},${transform.y} ) scale(${transform.k})`,
);
const data = [
{ id: 1, fill: 'black', x: 10, y: 10 },
{ id: 2, fill: 'black', x: 50, y: 50 },
{ id: 3, fill: 'black', x: 100, y: 70 },
{ id: 4, fill: 'black', x: 20, y: 100 }
];
draw(); // 绘制
bindZoom(); //绑定zoom
function draw() {
const update = container.selectAll('rect')
.data(data, d => d.id);
//修改层
update.attr('x', (d, idx) => d.x)
.attr('y', (d, idx) => d.y)
.attr('fill', (d) => d.fill)
//渲染层
const enter = update.enter();
//删除层
const exit = update.exit();
enter.append('rect')
.attr('width', 20)
.attr('height', 20)
.attr('id', d => d.id)
.attr('x', (d, idx) => d.x)
.attr('y', (d, idx) => d.y)
.attr('fill', (d) => d.fill)
.attr('stroke', 'blue')
.attr('strokeWidth', 1)
exit.remove()
}
function bindZoom() {
zoom = d3.zoom()
.scaleExtent([zoomMin, zoomMax])
.on('zoom', function () {
transform = d3.zoomTransform(this);
container.attr('transform', transform);
console.log(transform, 'transform...')
})
svg.call(zoom).on('dblclick.zoom', null);
};
function stopZoom() { //解除zoom绑定
svg.on('mousedown.zoom', null);
svg.on('mousemove.zoom', null);
svg.on('dblclick.zoom', null);
svg.on('touchstart.zoom', null);
};
function zoomIn() {
svg.transition().call(zoom.scaleBy, 0.7);
};
function zoomOut() {
svg.transition().call(zoom.scaleBy, 1.3);
};
function zoomCenter() {
const containerX = data.map((item) => item.x);
const containerY = data.map((item) => item.y);
const minX = Math.min.apply(null, containerX);
const maxX = Math.max.apply(null, containerX);
const minY = Math.min.apply(null, containerY);
const maxY = Math.max.apply(null, containerY);
const containerGroupBBox = { // 用数据获取到当前group得w、h、x、y
width: maxX - minX,
height: maxY - minY,
x: minX,
y: minY,
};
const scaleX = width / containerGroupBBox.width;
const scaleY = height / containerGroupBBox.height;
let k = Math.min(scaleX, scaleY) * 0.7;
k = Math.max(k, zoomMin);
k = Math.min(k, zoomMax); // 用画布大小 / 当前svg得大小 获取到比例值
// 算出居中得x、y坐标(往俩盒子 一个大盒子(画布)和另外一个盒子(图形撑起来得))怎么让图形撑起来得居中呢!!!
// 用画布自身得一半 减去 gropu得一半 * 缩放 K, 再减去gropu得translate
const translateByX = width / 2 - (containerGroupBBox.width / 2) * k - (containerGroupBBox.x * k);
const translateByY = height / 2 - (containerGroupBBox.height / 2) * k - (containerGroupBBox.y * k);
const transform = d3.zoomIdentity
.translate(translateByX, translateByY)
.scale(k); // 获取到目标 transform
svg.transition() // 过渡效果
.duration(100) // 100ms
.call(zoom.transform, transform);
}
</script>
本篇文章主要讲了下使用zoom,和常用得一些zoom场景得实现,相信尼对zoom又有了一个新得认识。他不只可以用在svg里面,我再canvas、doms上也用到了该zoom方法,就是哪里需要就可以用在哪里就好了。
阅读量:1009
点赞量:0
收藏量:0