Javascript PreserveSpectRatio、viewBox和layout.size()的问题
我编写了以下代码,旨在显示d3js树布局,但在尝试根据纵横比调整生成的svg大小时遇到了一些困难。我能够(在附带的演示中)使svg按我所希望的方式缩放,但我编写的代码受Javascript PreserveSpectRatio、viewBox和layout.size()的问题,javascript,d3.js,svg,viewport,viewbox,Javascript,D3.js,Svg,Viewport,Viewbox,我编写了以下代码,旨在显示d3js树布局,但在尝试根据纵横比调整生成的svg大小时遇到了一些困难。我能够(在附带的演示中)使svg按我所希望的方式缩放,但我编写的代码受常量纵横比的限制,如下所示: canvas.attr(“viewBox”,“0 0”+window.innerWidth++(window.innerWidth*纵横比)) 再往下看,这里: layout.size([(window.innerWidth*纵横比),window.innerWidth-128]) 有没有办法避免这种
常量纵横比
的限制,如下所示:
canvas.attr(“viewBox”,“0 0”+window.innerWidth++(window.innerWidth*纵横比))代码>
再往下看,这里:
layout.size([(window.innerWidth*纵横比),window.innerWidth-128])代码>
有没有办法避免这种情况?我不希望每次svg的纵横比发生变化时(即,任何时候添加新内容时)都必须手动更改此值
问候,
布莱恩
tl;dr:帮我消除常量纵横比。
代码:
/// <reference path="d3.d.ts" />
"use strict";
/* (c) brianjenkins94 | brianjenkins94.me | MIT licensed */
// Get JSON, impose synchronicity
d3.json("js/data.json", function(error, treeData) {
if (!error) {
// Instantiate canvas
var canvas = d3.select("#canvas");
// Aspect ratio nonsense
const ASPECT_RATIO = 1.89260808926;
canvas.attr("viewBox", " 0 0 " + window.innerWidth + " " + (window.innerWidth * ASPECT_RATIO));
canvas.attr("preserveAspectRatio", "xMinYMin slice");
// Update
update();
function update() {
// Add an SVG group element
canvas.append("g");
// Instantiate group
var group = canvas.select("g");
// Translate group right
group.attr("transform", "translate(64, 0)");
// Instantiate layout tree
var layout = d3.layout.tree();
// Initialize layout dimensions
layout.size([(window.innerWidth * ASPECT_RATIO), window.innerWidth - 128]);
// Instantiate rotation diagonal
var diagonal = d3.svg.diagonal();
// Rotate projection 90 degrees about the diagonal
diagonal.projection(function(d) { return [d.y, d.x]; });
// Initialize node array
var nodes = layout.nodes(treeData);
// Initialize link array
var links = layout.links(nodes);
// Select all paths in group
group.selectAll("path")
// For each link, create a path
.data(links).enter().append("path")
// Provide the specific diagonal
.attr("d", diagonal);
// Select all groups in group
var node = group.selectAll("g")
// For each node, create a group
.data(nodes).enter().append("g")
// Translate accordingly
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
// Add a circle at every node
node.append("circle")
.attr("r", 3);
// Add label
node.append("text")
// To the left if the node has children, otherwise right
.attr("dx", function(d) { return d.children ? -8 : 8; })
.attr("dy", 0)
// Branch if the node has children
.attr("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return d.name; });
}
} else {
console.log("There was a connection error of some sort.");
}
});
//
“严格使用”;
/*(c)Brianjenkins 94 | Brianjenkins 94.me |麻省理工学院许可*/
//获取JSON,强制同步
d3.json(“js/data.json”,函数(错误,treeData){
如果(!错误){
//实例化画布
var canvas=d3.选择(“画布”);
//纵横比无意义
常量纵横比=1.89260898926;
canvas.attr(“viewBox”,“0 0”+window.innerWidth+”+(window.innerWidth*纵横比));
attr(“preserveAspectRatio”、“xMinYMin切片”);
//更新
更新();
函数更新(){
//添加SVG组元素
画布。附加(“g”);
//实例化组
var组=画布。选择(“g”);
//右转组
attr(“transform”,“translate(64,0)”);
//实例化布局树
var layout=d3.layout.tree();
//初始化布局尺寸
layout.size([(window.innerWidth*纵横比),window.innerWidth-128]);
//实例化旋转对角线
var diagonal=d3.svg.diagonal();
//将投影绕对角线旋转90度
对角线投影(函数(d){返回[d.y,d.x];});
//初始化节点数组
var节点=布局节点(treeData);
//初始化链接数组
var links=layout.links(节点);
//选择组中的所有路径
group.selectAll(“路径”)
//为每个链接创建一个路径
.data(links).enter().append(“路径”)
//提供具体的对角线
.attr(“d”,对角线);
//选择组中的所有组
变量节点=组。选择全部(“g”)
//为每个节点创建一个组
.data(节点).enter().append(“g”)
//相应地翻译
.attr(“转换”,函数(d){return“translate”(+d.y+),“+d.x+”);});
//在每个节点上添加一个圆
node.append(“圆”)
.attr(“r”,3);
//添加标签
node.append(“文本”)
//如果节点有子节点,则向左,否则向右
.attr(“dx”,函数(d){返回d.children?-8:8;})
.attr(“dy”,0)
//如果节点有子节点,则执行分支
.attr(“文本锚定”,函数(d){返回d.children?“结束”:“开始”})
.text(函数(d){返回d.name;});
}
}否则{
log(“有某种连接错误。”);
}
});
演示:
/// <reference path="d3.d.ts" />
"use strict";
/* (c) brianjenkins94 | brianjenkins94.me | MIT licensed */
// Get JSON, impose synchronicity
d3.json("js/data.json", function(error, treeData) {
if (!error) {
// Instantiate canvas
var canvas = d3.select("#canvas");
// Aspect ratio nonsense
const ASPECT_RATIO = 1.89260808926;
canvas.attr("viewBox", " 0 0 " + window.innerWidth + " " + (window.innerWidth * ASPECT_RATIO));
canvas.attr("preserveAspectRatio", "xMinYMin slice");
// Update
update();
function update() {
// Add an SVG group element
canvas.append("g");
// Instantiate group
var group = canvas.select("g");
// Translate group right
group.attr("transform", "translate(64, 0)");
// Instantiate layout tree
var layout = d3.layout.tree();
// Initialize layout dimensions
layout.size([(window.innerWidth * ASPECT_RATIO), window.innerWidth - 128]);
// Instantiate rotation diagonal
var diagonal = d3.svg.diagonal();
// Rotate projection 90 degrees about the diagonal
diagonal.projection(function(d) { return [d.y, d.x]; });
// Initialize node array
var nodes = layout.nodes(treeData);
// Initialize link array
var links = layout.links(nodes);
// Select all paths in group
group.selectAll("path")
// For each link, create a path
.data(links).enter().append("path")
// Provide the specific diagonal
.attr("d", diagonal);
// Select all groups in group
var node = group.selectAll("g")
// For each node, create a group
.data(nodes).enter().append("g")
// Translate accordingly
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
// Add a circle at every node
node.append("circle")
.attr("r", 3);
// Add label
node.append("text")
// To the left if the node has children, otherwise right
.attr("dx", function(d) { return d.children ? -8 : 8; })
.attr("dy", 0)
// Branch if the node has children
.attr("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return d.name; });
}
} else {
console.log("There was a connection error of some sort.");
}
});
以下是我学到的:
- svg可以是“无量纲的”,但不能是“无纵横比的”。必须有一些核心纵横比来控制调整大小
- 和函数创建“不受屏幕坐标限制”的“任意坐标系”
- 长宽比由开发者决定,可以表示为“任意坐标”,或者根据响应设计,可以表示为相对论测量
我的解决办法如下:
// Viewbox & preserveAspectRatio
canvas.attr("viewBox", " 0 0 " + window.innerWidth + " " + (2 * window.innerWidth));
canvas.attr("preserveAspectRatio", "xMinYMin slice");
...
// Initialize layout dimensions
layout.size([(2 * window.innerWidth), (window.innerWidth - 128)]);
因此,消除了对常量纵横比的依赖,有利于基于浏览器尺寸的相对测量
这可能会(几乎肯定会)导致多个视口之间的渲染不一致,但可以通过在渲染前查询视口并进行外观调整来相应地处理。p/s:您的演示不起作用。~~我突然想到我从未编写过调整窗口大小的侦听器。。。但是它应该可以通过手动刷新正常工作。~~它工作正常。我想这可能与我对该功能的误解有关。你所说的“低纵横比”是什么意思。始终会有纵横比,因为它是宽度和高度之间的比。不过,您可以通过preserveSpectratio=“none”停止强制执行viewBox比率。我对svg是什么有一个误解。事后看来,这似乎很清楚,但我并不认为可伸缩矢量图形是有维度的。