D3中是否有“轴相等”?

蝴蝶

我正在使用D3和Python创建一些绘图。使用Python,我能够做到轴相等,如图1所示:

在Python中使用Axis Equal

我想在使用D3的SVG中实现相同的目的。请参考图2,轴不相等:

在Javascript d3中没有Axis Equal

我正在使用的轴刻度如下:

var xScale = d3.scaleLinear()
    .range([0, width])
    .domain([minX, maxX]);

var yScale = d3.scaleLinear()
    .range([height, 0])
    .domain([minY, maxY]);

var xAxis = d3.axisBottom(xScale).ticks(5),
    yAxis = d3.axisLeft(yScale).ticks(5);

谁能告诉我如何使轴与D3相等?

杰拉尔多·富塔多

简短的回答:不,D3中没有“轴相等”D3级别很低,它只是方法的集合,因此您几乎必须手工完成所有工作...

好消息是,您解决问题所需的就是一些数学运算来计算新范围。

As an introduction, since this is a tagged question, "axis equal" is a term used in some programs like Matlab, which...

Use the same length for the data units along each axis.

It can be better explained visually. Have a look at this image, with different domains and ranges (source):

在此处输入图片说明

After this brief introduction, let's go back to your problem. Suppose this simple code, generating two axes:

const minX = 0,
  minY = 0,
  maxX = 120,
  maxY = 50,
  width = 500,
  height = 300,
  paddings = [10, 10, 20, 30];

const xScale = d3.scaleLinear()
  .range([paddings[3], width - paddings[1]])
  .domain([minX, maxX]);

const yScale = d3.scaleLinear()
  .range([height - paddings[2], paddings[0]])
  .domain([minY, maxY]);

const svg = d3.select("svg")
  .attr("width", width)
  .attr("height", height);

svg.append("g")
  .attr("transform", `translate(0,${height - paddings[2]})`)
  .call(d3.axisBottom(xScale).tickSizeInner(-height + paddings[2] + paddings[0]));

svg.append("g")
  .attr("transform", `translate(${paddings[3]},0)`)
  .call(d3.axisLeft(yScale).tickValues(xScale.ticks()).tickSizeInner(-width + paddings[3] + paddings[1]));
svg {
  border: 2px solid tan;
}

line {
  stroke-dasharray: 2, 2;
  stroke: gray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

As we can clearly see, the units are not equally spaced. We can do two things for creating axes with equally spaced units: 1. Change the domains; 2. Change the ranges.

According to your comment, changing the domains is not an option. So, let's change the ranges instead.

我们所需要的只是计算每个用户空间的单位数,并使用其中最大的一个(x或y)来更改相反刻度的范围。

例如,给定上面片段的比例:

const xStep = Math.abs((xScale.domain()[1] - xScale.domain()[0]) / (xScale.range()[1] - xScale.range()[0]));

const yStep = Math.abs((yScale.domain()[1] - yScale.domain()[0]) / (yScale.range()[1] - yScale.range()[0]));

xStep大于yStep,向我们显示x轴每像素具有更多单位。因此,我们将更改y轴范围:

yScale.range([yScale.range()[0], yScale.range()[0] - (yScale.domain()[1] - yScale.domain()[0]) / xStep]);

这是演示:

const minX = 0,
  minY = 0,
  maxX = 120,
  maxY = 50,
  width = 500,
  height = 300,
  paddings = [10, 10, 20, 30];

const xScale = d3.scaleLinear()
  .range([paddings[3], width - paddings[1]])
  .domain([minX, maxX]);

const yScale = d3.scaleLinear()
  .range([height - paddings[2], paddings[0]])
  .domain([minY, maxY]);

const xStep = Math.abs((xScale.domain()[1] - xScale.domain()[0]) / (xScale.range()[1] - xScale.range()[0]));

const yStep = Math.abs((yScale.domain()[1] - yScale.domain()[0]) / (yScale.range()[1] - yScale.range()[0]));

yScale.range([yScale.range()[0], yScale.range()[0] - (yScale.domain()[1] - yScale.domain()[0]) / xStep]);

const svg = d3.select("svg")
  .attr("width", width)
  .attr("height", height);

svg.append("g")
  .attr("transform", `translate(0,${height - paddings[2]})`)
  .call(d3.axisBottom(xScale).tickSizeInner(-height + paddings[2] + yScale.range()[1]));

svg.append("g")
  .attr("transform", `translate(${paddings[3]},0)`)
  .call(d3.axisLeft(yScale).tickValues(yScale.ticks().filter(function(d){return !(+d%10)})).tickSizeInner(-width + paddings[3] + paddings[1]));
svg {
  border: 2px solid tan;
}

line {
  stroke-dasharray: 2, 2;
  stroke: gray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

如您所见,使用网格线时,单位之间的距离现在相等。

最后,请记住,以编程方式确定将要更改的比例尺,重新调整正确的范围(例如,您的比例尺从底部到顶部),将轴居中等完全是不同的问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

约束d3中的轴标签

来自分类Dev

约束d3中的轴标签

来自分类Dev

为什么在D3中没有从DOM中删除轴标签?

来自分类Dev

d3中具有顺序x轴的水平平移

来自分类Dev

创建没有刻度标签的D3轴

来自分类Dev

创建没有刻度标签的D3轴

来自分类Dev

检查d在D3中的函数(d){...}中是否具有变量

来自分类Dev

使用d3中的数据绑定创建轴

来自分类Dev

如何在D3中更改x轴?

来自分类Dev

在d3中双缩放图表的左右轴缩放

来自分类Dev

D3轴按年份中的星期几滴答

来自分类Dev

绕D3图形中的轴旋转rect

来自分类Dev

X轴文本标签未在d3中旋转

来自分类Dev

如何更改 D3 中 x 轴的标签

来自分类Dev

在 d3 中制作轴刻度字符串

来自分类Dev

我们如何在 d3 js 中的线性刻度的所有刻度之间留出相等的间距

来自分类Dev

检查路径是否在带有d3的svg中具有标题

来自分类Dev

D3打孔卡中的轴问题-需要数据以超出轴限制

来自分类Dev

numpy中的3D数组是否轴= 3?

来自分类Dev

D3:是否可以缩放+平移一个轴而仅平移另一个轴?

来自分类Dev

绘制具有反应的d3轴,无需直接进行D3 DOM操作

来自分类Dev

D3轴在图形顶部渲染

来自分类Dev

SVG外部的d3轴渲染

来自分类Dev

反转Y轴D3

来自分类Dev

更新D3轴标签

来自分类Dev

每周D3的X轴

来自分类Dev

轴未在D3图中显示

来自分类Dev

D3 /画布:不显示轴

来自分类Dev

使用D3 JavaScript缩放轴