首页 > 解决方案 > D3.JS 和 Vue 如何创建一个基本的圆环图

问题描述

我有一个 Vue 项目,我尝试在其中绘制一个简单的圆环图。我尝试创建的图表显示在 D3.js 的文档中:Donut Chart

但是当我尝试在 Vue 中创建它时,我似乎无法让它工作。我继续得到一个 [Vue warn]: Error in mounted hook: "TypeError: _ is not iterable".

还有一种方法可以使 SVG 填充父 div,以便它响应父级的宽度和高度。

<template>
  <div class="p-3 flex flex-col">
    <div class="w-full flex-1">
      <div id="my_dataviz"></div>
    </div>
  </div>
</template>
<script>
import * as d3 from "d3";

export default {
  name: "DoughnutChartItem",
  props: {
    data: {
      type: Array,
      required: true
    }
  },
  mounted() {
    // set the dimensions and margins of the graph
    var width = 450;
    var height = 450;
    var margin = 40;

    // The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
    var radius = Math.min(width, height) / 2 - margin;

    // append the svg object to the div called 'my_dataviz'
    var svg = d3
      .select("#my_dataviz")
      .append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    // Create dummy data
    var data = { a: 9, b: 20, c: 30, d: 8, e: 12 };

    // set the color scale
    var color = d3
      .scaleOrdinal()
      .domain(data)
      .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]);

    // Compute the position of each group on the pie:
    var pie = d3.pie().value(function(d) {
      return d.value;
    });
    var data_ready = pie(d3.entries(data));

    // Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
    svg
      .selectAll("whatever")
      .data(data_ready)
      .enter()
      .append("path")
      .attr(
        "d",
        d3
          .arc()
          .innerRadius(100) // This is the size of the donut hole
          .outerRadius(radius)
      )
      .attr("fill", function(d) {
        return color(d.data.key);
      })
      .attr("stroke", "black")
      .style("stroke-width", "2px")
      .style("opacity", 0.7);
  }
};
</script>

标签: javascriptvue.jsd3.js

解决方案


你的问题是.domain(data)

// set the color scale
var color = d3
  .scaleOrdinal()
  .domain(data) //<-- domain function is expecting an array not an object
  .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]);

你需要的是:

// set the color scale
var color = d3
  .scaleOrdinal()
  .domain(Object.keys(data)) //<-- set domain to ['a','b','c','d','e']
  .range(['#98abc5', '#8a89a6', '#7b6888', '#6b486b', '#a05d56']);

工作示例:

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

    <script>
      new Vue({
        el: '#one',
        data: {
          type: Array,
          required: true,
        },
        mounted() {
          // set the dimensions and margins of the graph
          var width = 450;
          var height = 450;
          var margin = 40;

          // The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
          var radius = Math.min(width, height) / 2 - margin;

          // append the svg object to the div called 'my_dataviz'
          var svg = d3
            .select('#my_dataviz')
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .append('g')
            .attr(
              'transform',
              'translate(' + width / 2 + ',' + height / 2 + ')'
            );

          // Create dummy data
          var data = { a: 9, b: 20, c: 30, d: 8, e: 12 };

          // set the color scale
          var color = d3
            .scaleOrdinal()
            .domain(Object.keys(data))
            .range(['#98abc5', '#8a89a6', '#7b6888', '#6b486b', '#a05d56']);

          // Compute the position of each group on the pie:
          var pie = d3.pie().value(function (d) {
            return d.value;
          });
          var data_ready = pie(d3.entries(data));

          // Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
          svg
            .selectAll('whatever')
            .data(data_ready)
            .enter()
            .append('path')
            .attr(
              'd',
              d3
                .arc()
                .innerRadius(100) // This is the size of the donut hole
                .outerRadius(radius)
            )
            .attr('fill', function (d) {
              return color(d.data.key);
            })
            .attr('stroke', 'black')
            .style('stroke-width', '2px')
            .style('opacity', 0.7);
        }
      });
    </script>
  </body>
</html>

基于评论的新片段:

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

    <script>
      new Vue({
        el: '#one',
        data: {
          type: Array,
          required: true,
        },
        mounted() {
          // set the dimensions and margins of the graph
          var width = 450;
          var height = 450;
          var margin = 40;

          // The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
          var radius = Math.min(width, height) / 2 - margin;

          // append the svg object to the div called 'my_dataviz'
          var svg = d3
            .select('#my_dataviz')
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .append('g')
            .attr(
              'transform',
              'translate(' + width / 2 + ',' + height / 2 + ')'
            );

          // Create dummy data
          var data = { a: 9, b: 20, c: 30, d: 8, e: 12 };

          // set the color scale
          var color = d3
            .scaleOrdinal()
            .domain(Object.keys(data))
            .range(['#98abc5', '#8a89a6', '#7b6888', '#6b486b', '#a05d56']);

          // Compute the position of each group on the pie:
          var pie = d3.pie().value(function (d) {
            return d[1];
          });
                   
          var data_ready = pie(Object.entries(data));

          // Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
          svg
            .selectAll('whatever')
            .data(data_ready)
            .enter()
            .append('path')
            .attr(
              'd',
              d3
                .arc()
                .innerRadius(100) // This is the size of the donut hole
                .outerRadius(radius)
            )
            .attr('fill', function (d) {
              return color(d.data[0]);
            })
            .attr('stroke', 'black')
            .style('stroke-width', '2px')
            .style('opacity', 0.7);
        }
      });
    </script>
  </body>
</html>


推荐阅读