【问题标题】:Beautify scaleBand美化 scaleBand
【发布时间】:2020-05-24 08:47:24
【问题描述】:

我刚刚试用了 d3js 几天,我想美化我的图表的 x 和 y 比例,使其像这样

但这就是我目前所得到的。

我尝试从 scaleBand() 更改为 scaleLinear() 并将通常的 bandwidth() 方法修复为恒定值,但图表不会显示。

这是代码

  mounted () {
    this.generateChart()
  },
  methods: {
    generateChart () {
      // set the dimensions and margins of the graph
      const margin = { top: 20, right: 20, bottom: 30, left: 30 }
      const width = 1850 - margin.left - margin.right
      const height = 200 - margin.top - margin.bottom

      // make the area for the graph to stay
      const svg = d3.select('#heatmap')
        .append('svg') // svg area can include headers and color scales
        .attr('width', width + margin.left + margin.right) // set width
        .attr('height', height + margin.top + margin.bottom) // set height
        .append('g') // new g tag area for graph only
        .attr('transform', `translate(${margin.left}, ${margin.bottom})`)
        // stick g tag to the bottom

      // range function generate graph scales
      // TODO: make a range using date and time
      const xLabel = d3.range(259)
      const yLabel = d3.range(23, -1, -1)

      // create x, y scales and axes
      const x = d3.scaleBand()
        .domain(xLabel)
        .range([0, width])
        .padding(0.05)

      svg.append('g')
        .attr('transform', `translate(0, ${height})`)
        .call(d3.axisBottom(x))

      const y = d3.scaleBand()
        .domain(yLabel)
        .range([height, 0])
        .padding(0.05)
      svg.append('g').call(d3.axisLeft(y))

      d3.json('../predictions.json').then(function (data) {
        svg.selectAll()
          .data(data.heatmaps.kw.Sand_Heads)
          .enter()
          .append('rect')
          .attr('x', function (d) {
            return x(d[1]) // return cell's position
          })
          .attr('y', function (d) {
            return y(d[0])
          })
          .attr('cx', 1)
          .attr('cy', 1)
          .attr('width', x.bandwidth()) // return cell's width
          .attr('height', y.bandwidth()) // return cell's height
          .style('fill', function (d) {
            return rgbaToHex(0, 128, 255, 100 * d[2])
          })
          .on('mouseover', function () { // box stroke when hover
            d3.select(this)
              .style('stroke', 'black')
              .style('opacity', 1)
          })
          .on('mouseout', function () { // fade block stroke when mouse leave the cell
            d3.select(this)
              .style('stroke', 'none')
              .style('opacity', 0.8)
          })
      })
    }

注意:我以后也必须让它与日期选择一起使用。

这是我正在处理的数据的结构。

{
  "days": ["2019-04-11", "2019-04-12", ..., "2019-12-25"],
  "heatmaps": {
    "kw": {
      "Tilly_Point": [[5, 112, 0.0012], [6, 112, 0.0016], ...],
      "Mouat_Point": [...]
    },
    "hw": {
      ...
    }
  }
}

说明: Tilly_Point 中子数组的第一个元素是鲸鱼的发现时间。范围从 0 到 23(午夜到下一个午夜),5 表示 05:00 A.M.到早上 06:00

第二个元素是操作的第 n 天。它是 112 表示这是手术的第 112 天。这是 2019 年 8 月 1 日

最后一个元素是绘制在图表上的真实数据。较高 -> 较暗的颜色接近真实颜色,不透明度为 1

【问题讨论】:

    标签: javascript typescript d3.js


    【解决方案1】:

    通过查看所需的设计,我们可以理解您所说的 “美化” 是指减少滴答数。你是绝对正确的:在极少数和特定的情况下,我们需要展示所有这些;大多数情况下,如果我们选择要显示的刻度,设计会更简洁,并且用户可以从更整洁的数据可视化中受益。

    如果我们看一下我写的这个模拟你的轴的基本示例,那就很清楚了:

    const svg = d3.select("svg");
    const yScale = d3.scaleBand()
      .domain(d3.range(25))
      .range([10, 80])
      .paddingInner(1);
    const xScale = d3.scaleBand()
      .domain(d3.range(261))
      .range([25, 490])
      .paddingInner(1);
    d3.axisLeft(yScale)(svg.append("g").attr("transform", "translate(25,0)"));
    d3.axisBottom(xScale)(svg.append("g").attr("transform", "translate(0,80)"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <svg width="500" height="100"></svg>

    这里有不同的方法来减少刻度数:您可以明确选择按值显示的刻度,或者就像我将在此答案中所做的那样,您可以简单地选择要显示的刻度数。在这里,我将使用余数运算符 (%) 过滤尺度的域并将其传递给 tickValues(因为你有一个波段尺度,我们不能使用 ticks),例如显示每 6 个值y轴:

    .tickValues(yScale.domain().filter((_, i) => !(i % 6)))
    

    结果如下:

    const svg = d3.select("svg");
    const yScale = d3.scaleBand()
      .domain(d3.range(25))
      .range([10, 80])
      .paddingInner(1);
    const xScale = d3.scaleBand()
      .domain(d3.range(261))
      .range([25, 490])
      .paddingInner(1);
    d3.axisLeft(yScale).tickValues(yScale.domain().filter((_, i) => !(i % 6)))(svg.append("g").attr("transform", "translate(25,0)"));
    d3.axisBottom(xScale).tickValues(xScale.domain().filter((_, i) => !(i % 20)))(svg.append("g").attr("transform", "translate(0,80)"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <svg width="500" height="300"></svg>

    【讨论】:

    • 有什么办法可以像示例一样将它们完全更改为日期?否则数据不会同步
    • 这是一个不同的问题(顺便说一句,这是一个重复的问题)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    相关资源
    最近更新 更多