如何创建了解可观察图的宽度、边距等的独立比例

问题描述 投票:0回答:1

如何创建独立的比例尺来了解可观察图的宽度、边距等?

  • 我需要创建一个独立的秤才能使用其
    scale.apply()
    方法。
  • 但是,生成的比例尺的
    apply()
    函数返回 [0,1] 范围内的值,而不是绘图的尺寸(宽度、边距等)。
  • plot.scale
    相比,后者根据绘图的维度返回值。
  • 我无法使用
    plot.scale
    ,因为需要
    scale.apply()
    函数来定义创建绘图时作为选项一部分的标记。 (有点像先有鸡还是先有蛋的问题。)
  • 我尝试在创建比例时添加绘图尺寸选项,但这些选项被忽略。
  • 理想情况下,可以从使用该比例尺的回调中访问该比例尺,但这似乎不可能。
  • 目前,我的解决方法是创建绘图两次:首先创建
    plot.scale
    ,然后再次定义使用
    plot.scale
  • 的绘图
  • 有趣的是,如果多次使用 (Svelte) 组件,则只有第一个组件需要上述解决方法。因此,可以隐藏“一次性”组件。
  • 另一种解决方法可能是首先生成一个简单的比例图,然后将其用于“真实”图。

我创建了一个简单的示例来演示以下问题:

const data = [{
    text: 'Weekend',
    utc: new Date('2024-06-16'), end: new Date('2024-06-17'),
  },{
    text: 'Weekdays',
    utc: new Date('2024-06-17'), end: new Date('2024-06-22'),
  }, {
    text: 'Weekend',
    utc: new Date('2024-06-22'), end: new Date('2024-06-23'),
  }]
  
  // Construct scale:
  const scale = Plot.scale({x: {domain: [new Date('2024-06-16'), new Date('2024-06-23')]}})
  
  // Simple plot:
  const plot = Plot.plot({
    height: 150,
    width: 800,
    marginRight: 12,
    marginLeft: 12,
    marks: [
      Plot.rectY(data, {
        x1: (d) => d.utc,
        x2: (d) => d.end,
        y: 1,
        fill: (d) => d.text == 'Weekend' ? 'lightgray': 'beige'
      }),
      Plot.text(data, {
        x: (d) => (Number(d.utc) + Number(d.end))/2,
        text: 'text'
      }),
    ],
  });
  
  function compareScales(value) {
    console.log({
      value,
      '     scale': scale.apply(value),
      'plot.scale': plot.scale('x').apply(value)
    })
  }
  
  compareScales(new Date('2024-06-16')) 
  compareScales(new Date('2024-06-17')) 
  compareScales(new Date('2024-06-23')) 
  

  const div = document.querySelector('#myplot');
  div.append(plot);
#myplot {
  height: 200px;
}
<!DOCTYPE html>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="https://cdn.jsdelivr.net/npm/@observablehq/[email protected]"></script>

<div id="myplot"></div>

javascript observable-plot
1个回答
0
投票

当您创建“独立”比例时,只需给它与您的绘图相同的

range
即可。

const width = 800,
      marginLeft = 12,
      marginRight = 12;

// construct scale
const scale = Plot.scale({
  x: { 
    domain: [ new Date('2024-06-16'), new Date('2024-06-23') ],
    range: [ marginLeft, width - marginRight ] //<-- range matching plot
  },
});

运行示例:

<!DOCTYPE html>

<html>

<head>
  <style>
    #myplot {
      height: 200px;
    }
  </style>
</head>

<body>
  <script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
  <script src="https://cdn.jsdelivr.net/npm/@observablehq/[email protected]"></script>

  <div id="myplot"></div>

  <script>
    const data = [{
        text: 'Weekend',
        utc: new Date('2024-06-16'),
        end: new Date('2024-06-17'),
      },
      {
        text: 'Weekdays',
        utc: new Date('2024-06-17'),
        end: new Date('2024-06-22'),
      },
      {
        text: 'Weekend',
        utc: new Date('2024-06-22'),
        end: new Date('2024-06-23'),
      },
    ];

    const width = 800,
      marginLeft = 12,
      marginRight = 12;

    // Construct scale:
    const scale = Plot.scale({
      x: {
        domain: [new Date('2024-06-16'), new Date('2024-06-23')],
        range: [marginLeft, width - marginRight]
      },
    });

    // Simple plot:
    const plot = Plot.plot({
      height: 150,
      width: width,
      marginRight: marginRight,
      marginLeft: marginLeft,
      marks: [
        Plot.rectY(data, {
          x1: (d) => d.utc,
          x2: (d) => d.end,
          y: 1,
          fill: (d) => (d.text == 'Weekend' ? 'lightgray' : 'beige'),
        }),
        Plot.text(data, {
          x: (d) => (Number(d.utc) + Number(d.end)) / 2,
          text: 'text',
        }),
      ],
    });

    function compareScales(value) {
      console.log({
        value,
        '     scale': scale.apply(value),
        'plot.scale': plot.scale('x').apply(value)
      })
    }

    compareScales(new Date('2024-06-16'))
    compareScales(new Date('2024-06-17'))
    compareScales(new Date('2024-06-23'))

    const div = document.querySelector('#myplot');
    div.append(plot);
  </script>
</body>

</html>

© www.soinside.com 2019 - 2024. All rights reserved.