Javascript PreserveSpectRatio、viewBox和layout.size()的问题

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]) 有没有办法避免这种

我编写了以下代码,旨在显示d3js树布局,但在尝试根据纵横比调整生成的svg大小时遇到了一些困难。我能够(在附带的演示中)使svg按我所希望的方式缩放,但我编写的代码受
常量纵横比
的限制,如下所示:

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是什么有一个误解。事后看来,这似乎很清楚,但我并不认为可伸缩矢量图形是有维度的。