Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Vue D3JS创建交互式甜甜圈图表_Javascript_Vue.js_Animation_D3.js_Charts - Fatal编程技术网

Javascript Vue D3JS创建交互式甜甜圈图表

Javascript Vue D3JS创建交互式甜甜圈图表,javascript,vue.js,animation,d3.js,charts,Javascript,Vue.js,Animation,D3.js,Charts,我有一个项目,我需要重新创建一个特定的甜甜圈图表。此图表由蓝色部分组成,在悬停时需要弹出并更改颜色。我在网上找到了一些关于如何重新创建此动画的文档: 问题是,我曾尝试在我的Vue组件中实现此解决方案,但当我在图表中徘徊时,它会不断抛出错误 当我将鼠标悬停在图表中时,我得到以下错误:无法读取下一行未定义的属性'startAngle':path.transition().attr(“d”,d3.arc().innerRadius(半径*0.7)。outerRadius(半径*1.08))。我似乎无法

我有一个项目,我需要重新创建一个特定的甜甜圈图表。此图表由蓝色部分组成,在悬停时需要弹出并更改颜色。我在网上找到了一些关于如何重新创建此动画的文档:

问题是,我曾尝试在我的Vue组件中实现此解决方案,但当我在图表中徘徊时,它会不断抛出错误

当我将鼠标悬停在图表中时,我得到以下错误:
无法读取下一行未定义的属性'startAngle'
path.transition().attr(“d”,d3.arc().innerRadius(半径*0.7)。outerRadius(半径*1.08))。我似乎无法理解为什么会发生此错误,因为我没有使用
startAngle
函数

当我将鼠标从图表中移出时,如果(!thisPath.classed(“clicked”){
,则在
行中,我还得到以下错误
node.getAttribute不是函数

这是我第一次使用D3.JS,我仍在努力了解这个库的很多内容。我喜欢你能用它创建多少不同的图形

这是我的组件的完整代码:

<template>
  <div class="p-3 flex flex-col items-center h-full">
    <div class="w-full flex-1 h-full">
      <div ref="chart" class="flex justify-center h-full"></div>
    </div>
  </div>
</template>
<script>
import * as d3 from "d3";

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

    // 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(this.width, this.height) / 2 - margin;

    // append the svg object to the div called 'chart'
    var svg = d3
      .select(this.$refs["chart"])
      .append("svg")
      .attr("width", "100%")
      .attr("height", "100%")
      .attr("viewBox", `0 0 ${this.width} ${this.height}`)
      .append("g")
      .attr(
        "transform",
        "translate(" + this.width / 2 + "," + this.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(this.data))
      .range(["#206BF3"]);

    // 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(this.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);

    svg.on("mouseover", () => {
      this.pathAnim(radius, d3.select(this), 1);
    });
    svg.on("mouseout", () => {
      var thisPath = d3.select(this);
      if (!thisPath.classed("clicked")) {
        this.pathAnim(radius, thisPath, 0);
      }
    });
  },
  methods: {
    pathAnim(radius, path, dir) {
      switch (dir) {
        case 0:
          path
            .transition()
            .duration(500)
            .ease("bounce")
            .attr(
              "d",
              d3
                .arc()
                .innerRadius(radius * 0.7)
                .outerRadius(radius)
            );
          break;

        case 1:
          console.log(
            path.transition().attr(
              "d",
              d3
                .arc()
                .innerRadius(radius * 0.7)
                .outerRadius(radius * 1.08)
            )
          );
          // path.transition().attr(
          //   "d",
          //   d3
          //     .arc()
          //     .innerRadius(radius * 0.7)
          //     .outerRadius(radius * 1.08)
          // );
          break;
      }
    }
  }
};
</script>

</script>


从“d3”导入*作为d3;
导出默认值{
名称:“DoughnutChartItem”,
道具:{
数据:{
类型:数组,
必填项:true
},
高度:{
类型:数字,
必填项:true
},
宽度:{
类型:数字,
必填项:true
}
},
安装的(){
////设置图形的尺寸和边距
//var宽度=450;
//var高度=450;
var保证金=50;
//pieplot的半径是宽度的一半或高度的一半(最小的一个)。我减去一点边距。
var radius=数学最小值(this.width,this.height)/2-边距;
//将svg对象附加到名为“chart”的div中
var svg=d3
.选择(此.$refs[“图表”])
.append(“svg”)
.attr(“宽度”、“100%”)
.attr(“高度”、“100%”)
.attr(“viewBox”`0${this.width}${this.height}`)
.附加(“g”)
艾特先生(
“转化”,
翻译(“+this.width/2+”,“+this.height/2+”)
);
////创建虚拟数据
//变量数据={a:9,b:20,c:30,d:8,e:12};
//设置颜色比例
var color=d3
.scaleOrdinal()
.domain(Object.keys(this.data))
.范围([“#206BF3]”);
//计算每个组在饼图上的位置:
var pie=d3.pie().value(函数(d){
返回d[1];
});
var data_ready=pie(Object.entries(this.data));
//构建饼图:基本上,饼图的每个部分都是我们使用arc函数构建的路径。
svg
.selectAll(“任意”)
.数据(数据准备就绪)
.输入()
.append(“路径”)
艾特先生(
“d”,
d3
.arc()
.innerRadius(100)//这是甜甜圈孔的大小
.外部(半径)
)
.attr(“填充”,功能(d){
返回颜色(d.data[0]);
})
.attr(“笔划”、“黑色”)
.style(“笔划宽度”、“2px”)
.样式(“不透明度”,0.7);
svg.on(“鼠标悬停”,()=>{
this.pathAnim(半径,d3.select(this),1);
});
svg.on(“mouseout”,()=>{
var thisPath=d3。选择(此);
如果(!thisPath.classed(“单击”)){
this.pathAnim(半径,thisPath,0);
}
});
},
方法:{
路径动画(半径、路径、方向){
交换机(dir){
案例0:
路径
.transition()
.持续时间(500)
.轻松(“反弹”)
艾特先生(
“d”,
d3
.arc()
.内半径(半径*0.7)
.外部(半径)
);
打破
案例1:
console.log(
path.transition().attr(
“d”,
d3
.arc()
.内半径(半径*0.7)
.外表面(半径*1.08)
)
);
//path.transition().attr(
//“d”,
//d3
//.arc()
//.内半径(半径*0.7)
//.外表面(半径*1.08)
// );
打破
}
}
}
};
三个问题

首先,将“mouseover”(和“mouseout”)事件分配给整个
SVG
。您希望将其分配给每个
路径

其次,您在
这方面遇到了问题

svg.on("mouseover", () => {
  this.pathAnim(radius, d3.select(this), 1);
});
这里的
this
变量是VUE组件(因此this.pathAnim是可调用的)。但是当您执行
d3.select(this)
时,您选择的是整个VUE组件,而不是要设置动画的
path
元素(请参见第1点)

您可以将其改写为:

var paths = svg //<-- hold reference to selection of paths
    .selectAll('whatever')
    .data(data_ready)
    .enter()
    .append('path')
    .attr(
      'd',
      d3
       .arc()
       .innerRadius(100)
       .outerRadius(radius)
    )
    .attr('fill', function (d) {
      return color(d.data[0]);
    })
    .attr('stroke', 'black')
    .style('stroke-width', '2px')
    .style('opacity', 0.7);

    paths.on('mouseover', (d,i,j) => { //<-- operate on paths
        this.pathAnim(radius, d3.select(j[i]), 1); //<-- use alternate way to select path without needing this variable
    });
运行代码:


新Vue({
el:'一',
数据:{
类型:数组,
要求:正确,
},
安装的(){
//设置图形的尺寸和边距
var宽度=450;
var高度=450;
var保证金=40;
//pieplot的半径是宽度的一半或高度的一半(最小的一个)。我减去一点边距。
变量半径=数学最小值(宽度、高度)/2-裕度;
//将svg对象附加到名为“my_dataviz”的div中
var svg=d3
.选择(“#我的数据VIZ”)
.append('svg')
.attr('width',width)
.attr('height',height)
.append('g')
艾特先生(
“转换”,
'平移('+width/2+','+height/2+')'
);
//创建虚拟数据
变量数据={a:9,b:20,c:30,d:8,e:12};
//设置颜色比例
var color=d3
.scaleOrdinal()
.domain(对象.键(数据))
.范围(['98abc5'、'8a89a6'、'7b6888'、'6b486b'、'
path
    .transition()
    .duration(500)
    .ease(d3.easeBounce) //<-- ease function
    .attr(
        'd',
        d3
         .arc()
         .innerRadius(radius * 0.7)
         .outerRadius(radius)
     );