【问题标题】:Why subtract margins only add them back in when setting svg width为什么减去边距只在设置 svg 宽度时将它们添加回来
【发布时间】:2021-07-12 01:13:12
【问题描述】:

在下面的 d3 折线图中,作者创建了一个边距对象,其属性为 top、right、bottom 和 left。

var margin = {top: 20, right: 20, bottom: 60, left: 80}

然后按以下方式设置宽度变量。

width = 700 - margin.left - margin.right // 700 - 80 - 20 = 600
// So, width variable is 600

只有到那时,在设置 svg 的宽度时重新添加边距。

attr('width', width + margin.left + margin.right) // 600 + 80 + 20 = 700
// So, width attr of the svg is 700

为什么不直接设置宽度 700 而不必减去边距? svg 最终被设置为。这种模式的目的是什么我以前见过它并试图理解这样做的目的。谢谢。

完整代码如下。

var margin = {top: 20, right: 20, bottom: 60, left: 80},
     width = 700 - margin.left - margin.right,
     height = 700 - margin.top - margin.bottom;
var svg = d3.select("body") //create Svg element
   .append("svg")
   .attr('width', width + margin.right + margin.left)
   .attr('height', height + margin.top + margin.bottom)
   .style("border", "solid 1px red")
   .attr("transform","translate(100,0)"); // To align svg at the center in the output tab.
var data = [
    {  date:"2020/01/01 00:00:00", patients: 600 },
    {  date:"2020/02/01 00:00:00", patients: 500 },
    {  date:"2020/03/01 00:00:00", patients: 400 },
    {  date:"2020/04/01 00:00:00", patients: 500 },
    {  date:"2020/05/01 00:00:00", patients: 300 },
    {  date:"2020/06/01 00:00:00", patients: 100 },
    {  date:"2020/07/01 00:00:00", patients: 50  },
    {  date:"2020/08/01 00:00:00", patients: 500 },
    {  date:"2020/09/01 00:00:00", patients: 550 },
    {  date:"2020/10/01 00:00:00", patients: 550 },
        ];
data=data.map(d => ({
   date: new Date(d.date),
   patients: d.patients
   }))        
var xscale = d3.scaleTime()
                  .domain(d3.extent(data, d=>d.date))
                  .range([0,width]);
var yscale= d3.scaleLinear()                         // drawing  y scale
           .domain([0,600])
           .range([height,0])                   
var chart=svg.append('g')
   .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
   .attr('width', width)
   .attr('height', height)
chart.append('g')
   .call(d3.axisBottom(xscale).tickFormat(d3.timeFormat("%b")))
   .attr('transform', 'translate(0,' + height + ')')
chart.append('g')
   .call(d3.axisLeft(yscale))
svg.append("text")                                  // labelling x-axis
    .text("Month")          
    .attr("transform","translate(350,680)");
svg.append("text")                                 // labelling y-axis
    .text("Number of patients")
    .attr('transform', "translate(40,400) rotate(-90)");   
var generator = d3.line()
    .x(function (d) { return xscale(d.date); })
    .y(function (d) { return yscale(d.patients); });      
chart.append('path')
    .datum(data)
    .attr("d", generator)
    .attr("fill","none")
    .attr("stroke","blue");

【问题讨论】:

  • 这有点令人困惑。他们可以定义svgWidth=700svgHeight=700。他们减去边距为内部图创建空间。我会定义innerWidth = svgWidth - margin.left - margin.right,与innerHeight = svgHeight - margin.top - margin.bottom 相同
  • 为什么有人做某事不一定由我们在这里回答;但是,对于width,使用 d3 来指代绘图区域的宽度(x 比例域为 [0,width])并不是非常罕见的做法,尽管使用 d3 的更多 standard convention 将使用宽度作为 svg宽度,绘图区域的宽度减去边距([margin.left,width-margin.right] 的 x 比例域)。无论哪种方式,您都需要知道绘图区域和 SVG 区域。

标签: d3.js


【解决方案1】:

这是 D3 的标准做法,至少可以追溯到版本 3。Mike Bostock 在他的示例中使用了这个约定。我一直觉得它很有用。您引用了一个相当简单的示例,但是随着您的 d3 代码变得越来越复杂,您需要更频繁地引用该绘图宽度而不是总 svg 宽度。

【讨论】:

    猜你喜欢
    • 2011-11-29
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多