d3.js缩放并将力布局平移到视口中心
d3.js scaling and translating a force layout to the center of a viewport
我有一个d3.js力布局,对力计算进行了一些调整。当我使用大型数据集时,有时图形部分或完全在视口之外。我想添加一个命令来重新缩放图形并将其居中到视口内,但遇到了一些问题。
什么有效:
我有一个画布和一个视口:
this.svg_canvas = d3.select("#" + this.container_id)
.append("svg")
.attr("width", this.width)
.attr("height", this.height)
.call(this.zoom_behavior.bind(this))
;
this.viewport = this.svg_canvas.append("g")
.attr("id", "viewport")
;
我有缩放和平移视口的缩放行为:
this.zoom_behavior = d3.behavior.zoom()
.scaleExtent([GraphView.MIN_ZOOM, GraphView.MAX_ZOOM])
.on('zoom', this._handleZoom.bind(this))
;
GraphView.prototype._handleZoom = function() {
var translate = d3.event.translate;
var scale = d3.event.scale;
this.viewport.attr("transform",
"translate(" + translate + ") " +
"scale(" + scale + ")");
};
所有这些都起到了应有的作用。
什么不起作用
我添加了一个"重新居中和缩放"方法,该方法应该执行缩放和平移,以将图形带到视口中。它的工作方式是,它首先找到图的范围(通过我的boundingBox()
方法),然后用适当的缩放和转换参数调用zoom.behavior
:
GraphView.prototype.recenterAndScale = function(nodes) {
var bounding_box = this._boundingBox(nodes || this.force.nodes());
var viewport = this.zoom_behavior.size(); // viewport [width, height]
var tx = viewport[0]/2 - bounding_box.x0;
var ty = viewport[1]/2 - bounding_box.y0;
var scale = Math.min(viewport[0]/bounding_box.dx, viewport[1]/bounding_box.dy);
this.zoom_behavior.translate([tx, ty])
.scale(scale)
.event(this.svg_canvas)
;
};
这行不通。它(通常)将图形定位在视口的边缘。也许我使用了错误的参考资料。网上有没有关于如何"正确"(使用d3习语)做到这一点的例子?
为了完整起见,这里是我对boundingBox()
的定义——它返回图中节点的几何中心和范围。据我所知,这一切都很正常:
// Return {dx:, dy:, x0:, y0:} for the given nodes. If no nodes
// are given, return {dx: 0, dy: 0, x0: 0, y0: 0}
GraphView.prototype._boundingBox = function(nodes) {
if (nodes.length === 0) {
return {dx: 0, dy: 0, x0: 0, y0: 0};
} else {
var min_x = Number.MAX_VALUE;
var min_y = Number.MAX_VALUE;
var max_x = -Number.MAX_VALUE;
var max_y = -Number.MAX_VALUE;
nodes.forEach(function(node) {
if (node.x < min_x) min_x = node.x;
if (node.x > max_x) max_x = node.x;
if (node.y < min_y) min_y = node.y;
if (node.y > max_y) max_y = node.y;
});
return {dx: max_x - min_x,
dy: max_y - min_y,
x0: (max_x + min_x) / 2.0,
y0: (max_y + min_y) / 2.0
};
}
}
这其实很容易:在计算翻译时,我需要应用缩放的效果。校正后的recenterAndScale()
方法为:
GraphView.prototype.recenterAndScale = function(nodes) {
var bbox = this._boundingBox(nodes || this.force.nodes());
var viewport = this.zoom_behavior.size(); // => [width, height]
var scale = Math.min(viewport[0]/bbox.dx, viewport[1]/bbox.dy);
var tx = viewport[0]/2 - bbox.x0 * scale; // <<< account for scale
var ty = viewport[1]/2 - bbox.y0 * scale; // <<< account for scale
this.zoom_behavior.translate([tx, ty])
.scale(scale)
.event(this.svg_canvas)
;
};
相关文章:
- 将视口底部滚动到元素底部
- 使用JavaScript根据窗口/视口的高度动态调整图像大小
- 使用条件语句,使 jquery fadeIn/fadeOut 仅在视口 >= 480px 时才有效
- 宽度为100%的CSS元素位于视口之外
- CSS3:当页面向下滚动到第一个视口时,是否可以在元素上触发转换
- 如何设置浏览器视口大小
- Javascript em根据窗口/视口尺寸调整大小,不影响文档样式的text/css
- 检测视口并重定向到不同的主页
- 如何在按住鼠标按钮且光标在视口外时检测鼠标离开
- iOS iPad平板电脑渲染视口不正确
- 移动设备上的视口问题
- 视口大小更改时自动刷新页面
- 在移动设备上获取视口大小
- 在 ReactJS 中获取视口/窗口高度
- 使jquery延迟加载插件在视口内工作
- Div 设置为视口高度,即使调整屏幕大小也是如此
- jQuery调整大小和视口检查点
- 用于管理视口布局的Javascript库
- d3.js缩放并将力布局平移到视口中心
- ExtJs 4 视口与带边框布局的面板 - 使用哪个以及为什么