如何使 react-D3-library 可拖动?

问题描述

我正在尝试使我的 D3 图表可拖动,但是当我拖动应用程序时崩溃了。

使用 d3-3d 使其拖动。

错误

enter image description here

代码

let sum;

      var j = 10,scale = 8,scatter = [],xLine = [],yLine = [],zLine = [],beta = 0,alpha = 0,key = function (d) {
          return d.id;
        },startAngle = Math.PI / 4,h = 300,w = 367,backgroundDots = [];
      var origin = [w * 0.4,h / 2];
      var svg = d3
        .select(node)
        .append("svg")
        .attr("class","nnsContainer")
        .attr("width",w)
        .attr("height",h)
        .on("mouSEOver",hoverStart)
        .on("mouSEOut",hoverEnd)
        .call(
          d3.drag()
            .on("drag",(event) => dragged(event))
            .on("start",(event) =>  dragStart(event))
            .on("end",(event) => dragEnd(event))
        )
        .append("g");
      var mx,my,mouseX,mouseY;

      var borderPath = svg
        .append("rect")
        .attr("x",0)
        .attr("y",0)
        .attr("height",h)
        .attr("width",w)
        .style("stroke","black")
        .style("fill","none")
        .style("stroke-width",0.3);

      // center origin at target word or centroid of points
      var center;
      if (!this.state.query_word) {
        center = {};
        for (const dim of ["x","y","z"]) {
          sum = radarChartData.query[dim];
          for (const nn of radarChartData.neighbors) {
            sum += nn[dim];
          }
          center[dim] = sum / (radarChartData.neighbors.length + 1);
        }
      } else {
        center = {
          x: radarChartData.query.x,y: radarChartData.query.y,z: radarChartData.query.z,};
      }
      for (const dim of ["x","z"]) {
        radarChartData.query[dim] -= center[dim];
        for (var i = 0; i < radarChartData.neighbors.length; i++) {
          radarChartData.neighbors[i][dim] -= center[dim];
        }
      }

      var cursorStatus = {
        hovering: false,dragging: false,};
      var cursorUpdate = function (cursorStatus) {
        if (cursorStatus.dragging) {
          document.querySelector("html,body").style.cursor = "grabbing";
        } else if (cursorStatus.hovering) {
          document.querySelector("html,body").style.cursor = "grab";
        } else {
          document.querySelector("html,body").style.cursor = "auto";
        }
      };

      // scale zoom level for size of viz,and range of data
      var query_magnitude = Math.sqrt(
        this.state.radarChartData.query.x ** 2 +
          this.state.radarChartData.query.y ** 2 +
          this.state.radarChartData.query.z ** 2
      );
      var mag_max = query_magnitude;
      for (var i = 0; i < this.state.radarChartData.neighbors.length; i++) {
        var pt = this.state.radarChartData.neighbors[i];
        var magnitude = Math.sqrt(pt.x ** 2 + pt.y ** 2 + pt.z ** 2);
        if (magnitude > mag_max) {
          mag_max = magnitude;
        }
      }
      var zoom_scale = d3.scaleLinear().domain([100,300]).range([50,150]);
      scale = zoom_scale(h) / mag_max;

      // scale dots & labels for size of viz and distance from camera
      var minFontScale = d3.scaleLinear().domain([80,160]).range([7,10]);
      minFontScale.clamp(true);
      var maxFontScale = d3.scaleLinear().domain([80,208]).range([11,19]);
      maxFontScale.clamp(true);
      var zToFont = d3
        .scaleLinear()
        .domain([-mag_max,mag_max])
        .range([minFontScale(h),maxFontScale(h)]);
      // 100 is just arbitrary high val,we just need to clamp min size
      var positive = d3.scaleLinear().domain([0.5,100]).range([0.5,100]);
      positive.clamp(true);
      var fontSize = function (d) {
        return positive(zToFont(d.rotated.z));
      };
      var pointSize = function (d) {
        return fontSize(d) / 3;
      };


      var point3d = _3d()
        .x(function (d) {
          return d.x;
        })
        .y(function (d) {
          return d.y;
        })
        .z(function (d) {
          return d.z;
        })
        .origin(origin)
        .rotateY(startAngle)
        .rotateX(-startAngle)
        .scale(scale);

      var yScale3d = _3d()
        .shape("LINE_STRIP")
        .origin(origin)
        .rotateY(startAngle)
        .rotateX(-startAngle)
        .scale(scale);


      function processData(data,tt) {
        console.log(data)

        /* ----------- POINTS ----------- */

        var points = svg.selectAll("circle.main").data(data[0],key);

        points
          .enter()
          .append("circle")
          .attr("class","_3d main")
          .attr("opacity",0)
          .attr("cx",posPointX)
          .attr("cy",posPointY)
          .merge(points)
          .attr("r",function (d) {
            return pointSize(d) + "px";
          })
          .style("fill",function (d) {
            if (d.id == "point_0") {
              return "#8525e5";
            } else {
              return "#4e3864";
            }
          })
          .attr("opacity",0.7)
          .attr("cx",posPointY);

        points.exit().remove();

        /* ----------- GRAY BG POINTS ----------- */

        var pointsBG = svg.selectAll("circle.bg").data(data[4],key);

        pointsBG
          .enter()
          .append("circle")
          .attr("class","_3d bg")
          .attr("opacity",posPointY)
          .merge(pointsBG)
          .attr("r",function (d) {
            return pointSize(d) + "px";
          })
          .attr("fill","#4e3864")
          // disappear the points if they're closer than origin
          .attr("opacity",function (d) {
            if (d.rotated.z < 0) {
              return 0.25;
            } else {
              return 0;
            }
          })
          .attr("cx",posPointY);

        pointsBG.exit().remove();

        /* ----------- POINT TEXT ----------- */

        var pointText = svg.selectAll("g.pointText").data(data[0]);

        pointText
          .enter()
          .append("g")
          .attr("class","_3d pointText")
          .merge(pointText)
          .attr("transform",function (d) {
            return "translate(" + d.projected.x + "," + d.projected.y + ")";
          })
          .selectAll("*")
          .remove();

        pointText
          .append("text")
          .attr("dx",function (d) {
            return pointSize(d) * 1.2 + "px";
          })
          .attr("dy",function (d) {
            return pointSize(d) * 1.2 + "px";
          })
          .attr("class","shadow")
          .text(function (d) {
            return d.label;
          })
          .attr("font-size",function (d) {
            return fontSize(d) + "px";
          });

        pointText
          .append("text")
          .attr("dx",function (d) {
            return pointSize(d) * 1.2 + "px";
          })
          .text(function (d) {
            return d.label;
          })
          .attr("font-size",function (d) {
            return fontSize(d) + "px";
          })
          .style("fill","#fff");

        pointText.exit().remove();

        /* ----------- x-Scale ----------- */

        var xScale = svg.selectAll("path.xScale").data(data[1]);

        xScale
          .enter()
          .append("path")
          .attr("class","_3d xScale")
          .merge(xScale)
          .attr("stroke","red")
          .attr("stroke-width",0.75)
          .attr("opacity",0.5)
          .attr("d",yScale3d.draw);

        xScale.exit().remove();

        /* ----------- y-Scale ----------- */

        var yScale = svg.selectAll("path.yScale").data(data[2]);

        yScale
          .enter()
          .append("path")
          .attr("class","_3d yScale")
          .merge(yScale)
          .attr("stroke","green")
          .attr("stroke-width",yScale3d.draw);

        yScale.exit().remove();

        /* ----------- z-Scale ----------- */

        var zScale = svg.selectAll("path.zScale").data(data[3]);

        zScale
          .enter()
          .append("path")
          .attr("class","_3d zScale")
          .merge(zScale)
          .attr("stroke","blue")
          .attr("stroke-width",yScale3d.draw);

        zScale.exit().remove();

        svg.selectAll("._3d").sort(_3d().sort);
      }

      function posPointX(d) {
        return d.projected.x;
      }

      function posPointY(d) {
        return d.projected.y;
      }

      function init() {
        var cnt = 0,yLine = [];

        console.log(radarChartData,"init2");

        scatter.push({
          x: radarChartData.query.x,label: radarChartData.query.word,id: "point_0",});

        for (var i = 0; i < radarChartData.neighbors.length; i++) {
          scatter.push({
            x: radarChartData.neighbors[i].x,y: radarChartData.neighbors[i].y,z: radarChartData.neighbors[i].z,label: radarChartData.neighbors[i].word,id: "point_" + (i + 1),});
        }

        backgroundDots = [];

        function backgroundDotRange() {
          return (Math.random() * mag_max * 2 - mag_max) * 4;
        }

        for (var i = 0; i < 10; i++) {
          backgroundDots.push({
            x: backgroundDotRange(),y: backgroundDotRange(),z: backgroundDotRange(),});
        }

        xLine = [
          [0,0],[j,];
        yLine = [
          [0,[0,-j,];
        zLine = [
          [0,j],];

        var data = [
          point3d(scatter),yScale3d([xLine]),yScale3d([yLine]),yScale3d([zLine]),point3d(backgroundDots),];

        processData(data,1000);
        processData(data,1000);
        // text wasn't appearing until dragged,so added this extra rotate
        point3d.rotateY(startAngle).rotateX(startAngle)(scatter);
      }

      function hoverStart() {
        cursorStatus.hovering = true;
        cursorUpdate(cursorStatus);
      }

      function hoverEnd() {
        cursorStatus.hovering = false;
        cursorUpdate(cursorStatus);
      }

      function dragStart(event) {
        mx = d3.event.x;
        my = d3.event.y;
        console.log(event,'event1')
        cursorStatus.dragging = true;
        cursorUpdate(cursorStatus);
      }

      function dragged(event) {
        let mouseX = mouseX || 0;
        let mouseY = mouseY || 0;
        let beta = ((d3.event.x - mx + mouseX) * Math.PI) / 230;
        let alpha = (((d3.event.y - my + mouseY) * Math.PI) / 230) * -1;
        console.log(beta,alpha)
        var data = [
          point3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)(scatter),yScale3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)([xLine]),yScale3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)([yLine]),yScale3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)([zLine]),point3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)(backgroundDots)
        ];
        processData(data,0);
      }

      function dragEnd(event) {
        mouseX = d3.event.x - mx + mouseX;
        mouseY = d3.event.y - my + mouseY;
        cursorStatus.dragging = false;
        cursorUpdate(cursorStatus);
      }

      init();

向组件添加图表:<RD3Component data={this.state.d3} />

我猜问题与 React 有关,因为我正在传输纯 JS 代码效果很好。

也许有人遇到过上述问题?

版本:

  • D3 4.0.0
  • 反应 16
  • React-D3-Library 1.1.8

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)