D3js 无法显示渐变面积图

D3js unable to show gradient area chart

我有一个项目需要重新创建渐变图表。我在网上找到了一些关于如何用渐变重新创建面积图的文档:Documentation.

主要问题是我无法使这段代码工作。我已将其更改为使用我的数据,但图表不会显示。轴被正确渲染。但是图表本身没有显示。

我已将 var x = d3.scaleTime().range([0, width]); 替换为 var x = d3.scaleBand().range([0, width]);,因为在文档中他们在 x 轴上使用 Date 对象。

没有控制台错误,但图表不会简单地显示出来。该代码看起来非常简单,但我似乎无法理解它有什么问题。我是 D3.js 的新手,仍然对图书馆了解很多。

<!DOCTYPE html>
    <html>
      <head>
        <title></title>
        <script src="https://unpkg.com/vue"></script>
        <script src="https://d3js.org/d3.v6.js"></script>
      </head>
      <body>
        <div class="p-3 flex flex-col" id="one">
          <div class="w-full flex-1">
            <div id="chart"></div>
          </div>
        </div>

        <script>
          new Vue({
            el: '#one',
            data: {
              type: Array,
              required: true,
            },
  mounted() {
    // set the dimensions and margins of the graph
    var margin = { top: 20, right: 20, bottom: 30, left: 50 },
      width = 960 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    // append the svg obgect to the body of the page
    // appends a 'group' element to 'svg'
    // moves the 'group' element to the top left margin
    var svg = d3
      .select("#chart")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var data = [
      {
        date: "Jan",
        value: 1507
      },
      {
        date: "Feb",
        value: 1600
      },
      {
        date: "Mar",
        value: 1281
      },
      {
        date: "Apr",
        value: 1898
      },
      {
        date: "May",
        value: 1749
      },
      {
        date: "June",
        value: 1270
      },
      {
        date: "July",
        value: 1712
      },
      {
        date: "Aug",
        value: 1270
      },
      {
        date: "Sept",
        value: 1257
      },
      {
        date: "Oct",
        value: 1257
      },
      {
        date: "Nov",
        value: 1257
      },
      {
        date: "Dec",
        value: 1257
      }
    ];

    // set the ranges
    var x = d3.scaleBand().range([0, width]);

    var y = d3.scaleLinear().rangeRound([height, 0]);

    // define the area
    var area = d3
      .area()
      .x(function(d) {
        console.log(d.date);
        console.log(x.domain());
        return x(d.date);
      })

      .y(function(d) {
        console.log(d.value);
        console.log(y.domain());
        return y(d.value);
      });

    x.domain(
      data.map(function(d) {
        return d.date;
      })
    );

    y.domain([
      0,
      d3.max(data, function(d) {
        return d.value;
      })
    ]);

    // set the gradient
    svg
      .append("linearGradient")
      .attr("id", "area-gradient")
      .attr("gradientUnits", "userSpaceOnUse")
      .attr("x1", 0)
      .attr("y1", y(0))
      .attr("x2", 0)
      .attr("y2", y(1000))
      .selectAll("stop")
      .data([
        { offset: "0%", color: "red" },
        { offset: "30%", color: "red" },
        { offset: "45%", color: "black" },
        { offset: "55%", color: "black" },
        { offset: "60%", color: "lawngreen" },
        { offset: "100%", color: "lawngreen" }
      ])
      .enter()
      .append("stop")
      .attr("offset", function(d) {
        return d.offset;
      })
      .attr("stop-color", function(d) {
        return d.color;
      });

    // Add the area.
    svg
      .append("path")
      .datum(data)
      .attr("class", "area")
      .attr("d", area);

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

    // Add the Y Axis
    svg.append("g").call(d3.axisLeft(y));
  }
          });
        </script>
      </body>
    </html>

两件事。

首先,您错过了设置 path 以使用渐变填充的 css

.area {                         
  fill: url(#area-gradient);                    
  stroke-width: 0px;            
}

其次,为了绘制“区域”,d3.area 生成器需要 .y0.y1 accessors。就是从这里到那里填充。

var area = d3
 .area()
 .x(function (d) {
   return x(d.date);
 })
 .y1(function (d) {
   return y(d.value);
 })
 .y0(height);

运行 片段:

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://d3js.org/d3.v6.js"></script>
    <style>
      .area {
        fill: url(#area-gradient);
        stroke-width: 0px;
      }
    </style>
  </head>
  <body>
    <div class="p-3 flex flex-col" id="one">
      <div class="w-full flex-1">
        <div id="chart"></div>
      </div>
    </div>

    <script>
      new Vue({
        el: '#one',
        data: {
          type: Array,
          required: true,
        },
        mounted() {
          // set the dimensions and margins of the graph
          var margin = { top: 20, right: 20, bottom: 30, left: 50 },
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

          // append the svg obgect to the body of the page
          // appends a 'group' element to 'svg'
          // moves the 'group' element to the top left margin
          var svg = d3
            .select('#chart')
            .append('svg')
            .attr('width', width + margin.left + margin.right)
            .attr('height', height + margin.top + margin.bottom)
            .append('g')
            .attr(
              'transform',
              'translate(' + margin.left + ',' + margin.top + ')'
            );

          var data = [
            {
              date: 'Jan',
              value: 1507,
            },
            {
              date: 'Feb',
              value: 1600,
            },
            {
              date: 'Mar',
              value: 1281,
            },
            {
              date: 'Apr',
              value: 1898,
            },
            {
              date: 'May',
              value: 1749,
            },
            {
              date: 'June',
              value: 1270,
            },
            {
              date: 'July',
              value: 1712,
            },
            {
              date: 'Aug',
              value: 1270,
            },
            {
              date: 'Sept',
              value: 1257,
            },
            {
              date: 'Oct',
              value: 1257,
            },
            {
              date: 'Nov',
              value: 1257,
            },
            {
              date: 'Dec',
              value: 1257,
            },
          ];

          // set the ranges
          var x = d3.scaleBand().range([0, width]);

          var y = d3.scaleLinear().rangeRound([height, 0]);

          // define the area
          var area = d3
            .area()
            .x(function (d) {
              return x(d.date);
            })
            .y1(function (d) {
              return y(d.value);
            })
            .y0(height);

          x.domain(
            data.map(function (d) {
              return d.date;
            })
          );

          y.domain([
            0,
            d3.max(data, function (d) {
              return d.value;
            }),
          ]);

          // set the gradient
          svg
            .append('linearGradient')
            .attr('id', 'area-gradient')
            .attr('gradientUnits', 'userSpaceOnUse')
            .attr('x1', 0)
            .attr('y1', y(0))
            .attr('x2', 0)
            .attr('y2', y(1000))
            .selectAll('stop')
            .data([
              { offset: '0%', color: 'red' },
              { offset: '30%', color: 'red' },
              { offset: '45%', color: 'black' },
              { offset: '55%', color: 'black' },
              { offset: '60%', color: 'lawngreen' },
              { offset: '100%', color: 'lawngreen' },
            ])
            .enter()
            .append('stop')
            .attr('offset', function (d) {
              return d.offset;
            })
            .attr('stop-color', function (d) {
              return d.color;
            });

          // Add the area.
          svg.append('path').datum(data).attr('class', 'area').attr('d', area);

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

          // Add the Y Axis
          svg.append('g').call(d3.axisLeft(y));
        },
      });
    </script>
  </body>
</html>