在用brush画刷批量选取力学导图的node节点时,页面初始化时是一切正常的。 但是点击zoom事件放大缩小后,brush画刷选取开始出现明显的不正常,有时候可以选取到,有时候选取不到。
正常情况:
zoom后:
这是我初始化brush的代码:
这是zoom的代码
//set zoom function setZoom() { $('#zoomOut').click(function () { if (scale < 5) { scale = scale + 0.1; //增加比例尺 gTranslateAndScale(scale); zoomType = "out"; } $(this).blur(); }); $('#zoomIn').click(function () { if (scale >= 0.2) { scale = scale - 0.1; gTranslateAndScale(scale); zoomType = "in"; } $(this).blur(); }); } //translate and scale function gTranslateAndScale(scale) { g.attr("transform", "translate(" + (width * (1 - scale)) / 2 + "," + ($("svg").height() * (1 - scale)) / 2 + ")scale(" + scale + ")"); }
原因是:zoom之后元素坐标系发生变化,brush的坐标系和zoom对不上了。
brush的坐标和zoom的坐标是不在一个平面内的。
transform="translate(-57.45000000000005,-20.10000000000002)scale(1.1)"
translate(x,y) // 定义 2D 转换。 向左移动57,向上移动27 scale // 放大1.1
解决办法:zoom 之后他们在两套坐标系统内,那么只能把一个坐标转化到另一个系统中 相同坐标系下做对比。zoom后,在brush的extent判断落点里把extent的x,y也相对的放大,判断当前node的落点
是否在extent区域内
重点是:在一个坐标系变换后,要统计两个坐标系的判断标准。
最终解决代码如下:
zoom代码:
//translate and scale /* * transform="translate(-57.45000000000005,-20.10000000000002)scale(1.1)" * translate(x,y) 定义 2D 转换。 向左移动57,向上移动27 * scale 放大1.1 * */ function gTranslateAndScale(scale) { translate_a = (width * (1 - scale)) / 2; translate_b = ($("svg").height() * (1 - scale)) / 2; g.attr("transform", "translate(" + (width * (1 - scale)) / 2 + "," + ($("svg").height() * (1 - scale)) / 2 + ")scale(" + scale + ")"); }
brush代码:
var brush = svg.append("g") .datum(function() { return {selected: false, previouslySelected: false}; }) .attr("class", "brush") .call(d3.svg.brush() .x(d3.scale.identity().domain([0, width])) .y(d3.scale.identity().domain([0, height])) .on("brushstart", function(d) { nodes.each(function(d) { d.previouslySelected = shiftKey && d.selected; }); }) .on("brush", function() { var extent = d3.event.target.extent(); nodes.classed("selected", function(d) { if( zoomType == "out" || zoomType == "in"){ console.log("重新设置了brush的extent"); /* 警告zoom放大或者缩小后,<g class="nodes" transform="translate(170.29999999999995,76.29999999999998)scale(0.8)" nodes的坐标系发生了变化。由于nodes和brush不在一个坐标系 nodes坐标系变化,brush的extent[画刷的点击框选范围]也要随之变化,这样才能正确判断node是否在extent范围内 * */ return d.selected = d.previouslySelected ^ (((extent[0][0]-translate_a)/scale) <= d.x && d.x < ((extent[1][0]-translate_a)/scale) && ((extent[0][1]-translate_b)/scale) <= d.y && d.y < ((extent[1][1]-translate_b)/scale) ); } else{ console.log("没有重新设置extent"); return d.selected = d.previouslySelected ^ (extent[0][0] <= d.x && d.x < extent[1][0] && extent[0][1] <= d.y && d.y < extent[1][1]); } }); }) .on("brushend", function() { d3.event.target.clear(); d3.select(this).call(d3.event.target); }));