d3.js zoom使用的高级进阶
一、应用场景描述
假设我们在绘制svg图形的时候,需要将一个地方放大后再添加一些图标或者拖拽图标到其他位置的时候,我们需要先将svg通过放大与平移操作找到svg上的图标,然后拖拽某一图标到其他位置。然后继续通过缩放与平移操作找到其他的图标继续执行拖拽功能。此时在这一系列的操作上就存在两个主要功能。
1、svg的zoom功能,包括scale与translate功能
2、停止svg的zoom功能,然后执行图标的drag功能。
3、继续svg的zoom功能,包括scale与translate功能
1、 问题难点有两个,zoom功能与drag功能的冲突
2、 Zoom功能需要以之前的scale与translate继续操作
Demo功能介绍
StartZoom 按下,可以缩放与平移
StopZoom按下,停止缩放与平移
绘制按下,可以在svg上绘制
代码如下:
<!DOCTYPEhtml>
<html>
<head>
<title>title>
<metacharset="UTF-8"/>
<scriptsrc="Scripts/jquery-1.7.1.js">script>
<scriptsrc="Scripts/d3.min.js">script>
<script>
varsvgLineContainer = null; var zoom = null;
vartranslate = [0, 0], currentScale = 1;
varhasInitZoom = false, isDrag= false;
var imgUrl = "/guihua.jpg";
var width =500, autoHeight = 500;
$(function () {
var svg = d3.select("#d3LineDiv").append("svg").attr("id", "svg_obj_line").attr("width", width).attr("height", autoHeight).attr("xmlns", "http://www.w3.org/2000/svg");
svgLineContainer = svg.append("g").attr("id", "svg_obj_line123");
svgLineContainer.append("image").attr("x", 0).attr("y", 0).attr("width",width).attr("height", autoHeight).attr("id", "svg_obj_image").attr("xlink:href", imgUrl);
$("#btnStart").on("click", function () {
isDrag = false;
InitZoom();
});
$("#btnStop").on("click", function () {
stopZoom();
isDrag = true;
});
$("#btnDrag").on("click", function () {
stopZoom();
isDrag = true;
InitDrag();
});
});
functionInitZoom() {
var bodyDom = d3.select("#svg_obj_line");
//缩放
zoom =d3.behavior.zoom().scaleExtent([1, 20]).on("zoom", zoomed);
function zoomed() {
//放大缩小
// now,constrain the x and y components of the translation by the
//dimensions of the viewport
var e = d3.event;
var tx = Math.min(0, Math.max(e.translate[0], width - width* e.scale));
var ty = Math.min(0, Math.max(e.translate[1], autoHeight -autoHeight * e.scale));
// then,update the zoom behavior's internal translation, so that
// itknows how to properly manipulate it on the next movement
zoom.translate([tx, ty]);
// andfinally, update the
//correct translation and scale (in reverse order)
svgLineContainer.attr("transform", [
"translate(" + [tx, ty] + ")",
"scale(" + e.scale + ")"
].join(""));
translate = [tx, ty];
currentScale = e.scale;
}
if (!hasInitZoom) {
bodyDom.call(zoom);
hasInitZoom = true;
} else {
//调用zoom
bodyDom.call(zoom);
//恢复到上次zoom到的状态
d3.transition().duration(250).tween("zoom", function () {
bodyDom.call(zoom.translate(translate).scale(currentScale).event);
});
}
}
functionstopZoom() {
var bodyDom = d3.select("#svg_obj_line");
bodyDom.on("mousedown.zoom", null);
bodyDom.on("mousemove.zoom", null);
bodyDom.on("dblclick.zoom", null);
bodyDom.on("touchstart.zoom", null);
bodyDom.on("wheel.zoom", null);
bodyDom.on("mousewheel.zoom", null);
bodyDom.on("MozMousePixelScroll.zoom", null);
}
var startx= 0, starty = 0;
functionInitDrag() {
var svgdrag = d3.behavior.drag().on("dragstart", function (d) { }).on("dragend", function (d) {
startx = 0; starty = 0;
}).on("drag", function (d) {
if (startx == 0 && starty == 0) {
startx = d3.mouse(this)[0];
starty = d3.mouse(this)[1];
} else {
if (isDrag) {
var currentx =d3.mouse(this)[0];
var currenty =d3.mouse(this)[1];
//删除选框rect
var removeparam =d3.select("#d3LineDiv").select("#changeRect");
if (removeparam) {
removeparam.remove();
}
//绘制新的选框
var rewidth = 0,reheigth = 0;
rewidth =Math.abs(currentx - startx);
reheigth =Math.abs(currenty - starty);
if (currentx >startx) {
if (currenty >starty) {
svgLineContainer.append("rect").attr("id", "changeRect").attr("x", startx).attr("y", starty).attr("width", rewidth).attr("height", reheigth).attr("stroke", "blue").attr("stroke-width", 2).attr("fill", "rgba(0,0,255,0.2)");
} else {
svgLineContainer.append("rect").attr("id", "changeRect").attr("x", startx).attr("y", currenty).attr("width",rewidth).attr("height", reheigth).attr("stroke", "blue").attr("stroke-width", 2).attr("fill", "rgba(0,0,255,0.2)");
}
} else {
if (currenty >starty) {
svgLineContainer.append("rect").attr("id", "changeRect").attr("x", currentx).attr("y", starty).attr("width", rewidth).attr("height", reheigth).attr("stroke", "blue").attr("stroke-width", 2).attr("fill", "rgba(0,0,255,0.2)");
} else {
svgLineContainer.append("rect").attr("id", "changeRect").attr("x", currentx).attr("y", currenty).attr("width", rewidth).attr("height", reheigth).attr("stroke", "blue").attr("stroke-width", 2).attr("fill", "rgba(0,0,255,0.2)");
}
}
}
}
});
//calldrag
svgLineContainer.call(svgdrag);
}
script>
head>
<body>
<divid="MainDiv"style="text-align:center;">
<buttonid="btnStart">StartZoombutton>
<buttonid="btnStop">StopZoombutton>
<buttonid="btnDrag">绘制button>
<divid="d3LineDiv"style="margin-left: auto;margin-right: auto;margin-top: 10px;width:500px;height:500px;border:solid1pxred;">
div>
div>
body>
html>