如何将d3.linearScale()居中对齐到页面中心?

5

我正在尝试创建一个2D笛卡尔坐标系,其原点位于svg的中心。就像这样: 我想要的样子... 我的当前方法是平移轴,使它们的原点在中间。

  // Add the x Axis
  svg.append("g")
      .attr("transform", "translate(" + 0 + "," + height/2 + ")")
      .call(d3.axisBottom(x).ticks(100));

  // Add the y Axis
  svg.append("g")
      .attr("transform", "translate(" + width/2 + "," + 0 + ")")
      .call(d3.axisLeft(y).ticks(100));
      });

然而,为了使y轴居中,我需要手动调整范围。由于每个屏幕大小所需的值不同,因此我需要帮助找出如何始终在每个屏幕上使坐标轴居中。

  var x = d3.scaleLinear().range([width/2-5*width,width/2+5*width]).domain([-50, 50]); 
  var y = d3.scaleLinear().range([height/2-5*height,height/2+3.244*width]).domain([50,  -50]); //the value 3.244 is the problem, it changes on every screen

我创建了一个Fiddle,以便向您展示我如何创建坐标轴。

2个回答

3

我并不理解这些复杂而且不必要的数学计算(例如,在你原始的fiddle中,为什么要使用一个神奇的数字?它在没有那个数字的情况下也可以工作:https://jsfiddle.net/smftm5sv/)。

在SVG的中心设置笛卡尔平面的原点非常简单。首先,您可以按照您想要的方式定义范围... 最简单的选项只是:

var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([0, height]);

第二,要将笛卡尔平面上的两个轴对齐,只需将比例尺的零值传递给每个translate (y(0)x(0))。即使 x 轴和 y 轴的域不同,只要起始值和终止值的绝对值相同即可实现对齐:

svg.append("g")
    .attr("transform", "translate(0"," + y(0) + ")")
    .call(d3.axisBottom(x));

svg.append("g")
    .attr("transform", "translate(" + x(0) + ",0)")
    .call(d3.axisLeft(y));

这里是更新后的代码(同时,我删掉了jQuery,因为在D3中不需要使用jQuery):

var width = window.innerWidth;
var height = window.innerHeight;
var padding = 10;


  var svg = d3.select("body")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .call(d3.zoom().on("zoom", function() {
      svg.attr("transform", d3.event.transform);
    }))
    .append("g");

  var viewport = svg.append('g');

  var x = d3.scaleLinear().range([0 + padding, width - padding]).domain([-50, 50]); 
  var y = d3.scaleLinear().range([0 + padding, height - padding]).domain([50, -50]);

  // Add the x Axis
  svg.append("g")
    .attr("transform", "translate(" + 0 + "," + y(0) + ")")
    .call(d3.axisBottom(x));

  // Add the y Axis
  svg.append("g")
    .attr("transform", "translate(" + x(0) + "," + 0 + ")")
    .call(d3.axisLeft(y));
<script src="https://d3js.org/d3.v4.min.js"></script>

由于 Stack 代码段窗口比较小(并且您正在动态获取窗口尺寸),因此 y 轴会非常短,而 x 轴则会更长。


1

好的,我自己找到了解决方法。关键是使用宽高比例。更新后的Fiddle在这里

  var x = d3.scaleLinear().range([width/2-5000*width/height,width/2+5000*width/height]).domain([-50, 50]);
  var y = d3.scaleLinear().range([height/2-5000*width/height,height/2+5000*width/height]).domain([50,  -50]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接