HTML/JS/D3.js:鼠标悬停在画布的某些部分滞后?

问题描述

我最近开始尝试使用 D3.js 创建基于 HTML/JS 的交互式图形。在我最近的实验中,我想创建一个图形,根据鼠标当前悬停的位置沿 x 轴移动函数。

我目前的草案在原则上很好,但结果图的行为很奇怪。如果鼠标悬停在主画布(图形内的区域)上,更新速度会减慢到几乎无功能的程度。但是,当您将鼠标水平移动到 x 轴下方(跨 x 刻度标签)时,代码会按预期顺利运行。

我不知道可能导致这种滞后差异的原因。您对可能导致这种情况的原因有什么建议吗?

要重现我在此处报告的内容,请运行下面的代码片段,然后将鼠标移到结果图上。该代码几乎不会在 x 和 y 轴跨越的矩形内响应,但在 x 轴下方移动鼠标时会平滑响应。

<!DOCTYPE html>
<html>

  <head>
    <script src="https://unpkg.com/mathjs/lib/browser/math.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>  
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://d3js.org/d3-hsv.v0.1.min.js"></script>
    <script src="https://d3js.org/d3-contour.v1.min.js"></script>
    <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
    
    <style>

    </style>
  </head>

<!-- Create a div where the graph will take place -->
<div id="my_datavisualization">
  <svg id="click" xmlns="http://www.w3.org/2000/svg">
      <defs>
          <g id="pointer" transform="scale(0.5)">
              <circle cx="0" cy="0" r="20" id="dragcircle" />
          </g>
      </defs>
  </svg>
</div>



  <body style='overflow:hidden'>
  
    
    <script>
    
        // Get the viewport height and width
      const vw = Math.max(document.documentElement.clientWidth || 0,window.innerWidth || 0)
      const vh = Math.max(document.documentElement.clientHeight || 0,window.innerHeight || 0)
      
      // Fit to viewport
      var height            = math.min([vw,vh])*0.7;
      var width             = math.min([vw,vh]);
      
      // Create the canvas. We will use only part of it for the main plot
      var svg = d3.select("#click") // This selects the div
          .attr("width",width) // This defines the canvas' width
          .attr("height",height) // This defines the canvas' height
      
      // Prepare the contour grid
      var conc          = linspace(0,60,101);
      var obs           = 24;
      var obs_sd        = 2;
      
      //print(conc_short)
      
      // Get the initial likelihood
      var likeli = likelihood(
        y       = conc,x       = obs,std     = obs_sd)
      
      var x_limits  = [0,60];
      var y_limits  = [0,d3.max(likeli)*1.2];
      
      // Get scaling functions for the x scale and the y_scale
      const xScale = d3.scaleLinear()
        .domain([x_limits[0],x_limits[1]])
        .range([width*0.05,width*0.95])
      const xScale_inverse = d3.scaleLinear()
        .domain([width*0.05,width*0.95])
        .range([x_limits[0],x_limits[1]])
      const yScale = d3.scaleLinear()
        .domain([y_limits[0],y_limits[1]])
        .range([height*0.92,height*0.08])
        
      
      // Draw the x axis
      svg
        .append("g")
        .attr("transform","translate(0,"+(height*0.92).toString()+")")
        .call(d3.axisBottom(xScale))
        .style("font-size",(16*width/600).toString()+"px")
      svg.append("text")             
          .attr("transform","translate("+(width*0.625).toString()+","+(height*0.055).toString()+")")
          .style("text-anchor","middle")
          .text("value of random variable x")
          .style("font-family","arial")
          .style("font-size",(16*width/600).toString()+"px")
          
      
      // Draw the y axis
      svg
        .append("g")
        .attr("transform","translate("+(width*0.05).toString()+",0)")
        .attr("id","mainxaxis")
        .call(d3.axisLeft(yScale))
        .style("font-size",(16*width/600).toString()+"px");
        //.call(d3.axisLeft(yScale).tickFormat(""));
      svg.append("text")             
          .attr("transform","translate("+(width*0.95).toString()+","+(height*0.5).toString()+") rotate(270)")
          .style("text-anchor","middle")
          .text("value of random variable y")
          .style("font-family",(16*width/600).toString()+"px")
        
      // Get the data for the path
      var data  = [];
      for (i = 0; i < conc.length; i++) {
        data.push({
            x: conc[i],y: likeli[i]})
      }

      // Add a realization of the marker
      svg.append("use")
          .attr("href","#pointer")
          .attr("x",xScale(24))
          .attr("y",yScale(0.2))
          .attr("fill","blue") // "#c3e7f9"
          .attr("stroke-width",5)
          .attr("id","point1");
      
      // Add the x coordinate tracker
      svg
        .append('line')
        .attr('x1',xScale(obs))
        .attr('y1',yScale(y_limits[0]))
        .attr('x2',xScale(obs))
        .attr('y2',yScale(y_limits[1]))
        .attr("stroke-width",2*height/600)
        .attr("stroke","#666666")
        .attr("id","vline");
        
      var valueline = d3.svg.line()
          .x(function(d) { return xScale(d.x); })
          .y(function(d) { return yScale(d.y); });
      
      svg.append("path")
        .attr("class","line")
        .attr("d",valueline(data))
        .attr("fill","none")
        .attr("stroke-width",3*height/600)
        .attr("stroke","#4794c1")
        .attr("id","thatline")
      
      
      // Shift the marker around on mouseover; restrict it to the contour
      var movex
      var movey

      svg
        .on("mouseover",function () {
            // Get the current mouseover coordinates
            movex = d3.event.x;
            movey = d3.event.y;

            if (movex < 0.05*width) {
            movex = 0.05*width;
          } else if (movex > width*0.95) {
            movex = width*0.95;
          }
            if (movey > 0.95*height) {
            movey = 0.95*height;
          } else if (movey < height*0.05) {
            movey = height*0.05;
          }
          // Shift the point to this position
            d3.select("#point1")
            .attr("x",movex)
            .attr("y",movey);
            d3.select("#vline")
            .attr("x1",movex)
            .attr("x2",movex)
            
          likeli = likelihood(
            y       = conc,x       = xScale_inverse(movex),std     = obs_sd)
            
          for (i = 0; i < data.length; i++) {
            data[i].y = likeli[i]
          }
            
          // Select the section we want to apply our changes to
          // Make the changes
              d3.select("#thatline")   // change the line
                  .attr("d",valueline(data));
            
          });

      
      
     
      // ============================================================
      // Helper function: Printing function for troubleshooting
      // ============================================================
      function print(value) {
        var precision = 14;
        document.write(math.format(value,precision) + '<br>');
      }
      
      // ============================================================
      // Helper function: Linspace
      // ============================================================
      function linspace(start,end,resolution) {
        var spacing = [];
        // Go through a for-loop
        var i;
        for (i = 0; i < resolution; i++) {
            spacing.push(start + (end-start)*i/(resolution-1))
        }
        return spacing; // The function returns the linspace between p1 and p2
      }
      
            // ============================================================
      // Helper function: likelihood
      // ============================================================
      function likelihood(y,x,std) {
      
        mean        = x;
        std         = std;
        
        // Create a dummy variable
        var result  = [];
        
        normalize = math.dotDivide(
          1,math.sqrt(
            math.dotMultiply(
              math.dotMultiply(
                2,math.PI),std)));
        
        var i;
        for (i = 0; i < y.length; i ++) {
        
          // Evaluate the first element of the Gaussian mixture

          expon         = math.exp(
            -math.dotDivide(
              math.pow(
                y[i]-mean,2),math.dotMultiply(
                2,math.pow(
                    std,2))))
          temp  = math.dotMultiply(
            normalize,expon)

          result.push(temp)
          
        }
        

        return result
        
      }
      
  
    </script>
  </body>

</html>

解决方法

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

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

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...