首页 > 解决方案 > 使用 D3.interval() 的翻译动画略有滞后

问题描述

我创建了一个时间序列动画。本质上,我每 20 毫秒生成一个随机数据,时间轴以一秒的间隔连续向左滑动。D3.interval() 创建我想要的,但图表似乎“不稳定”。我认为它与网络浏览器或 D3 有关?这是我的代码(展开片段窗口以获得更好的视图):

    ////////////////////////////////////////////////////////////
    ////////////////////// Set-up  /////////////////////////////
    ////////////////////////////////////////////////////////////

    const margin = { left: 80, right: 80, top: 30, bottom: 165},
          TIME_MEASUREMENT = 20,
          TIME_INTERVAL = 1000,
          TIME_FRAME = 10000;

    let width = $("#chart").width() - margin.left - margin.right,
        height = $("#chart").height() - margin.top - margin.bottom;

    let date1 = 0,
        date2 = TIME_FRAME;

    let accuracy = 20,
        precision = 20,
        aF = 2, //accuracyFactor 
        pF = 1; //precisionFactor
                
    let random = d3.randomUniform(-(pF * precision), pF * precision), 
        count = TIME_FRAME/TIME_MEASUREMENT + 1;

    let data = d3.range(count).map((d,i) => random() + accuracy ); 

    const yDomain = [0, 50],
          yTickValues = [0, 10, 20, 30, 40, 50];


    ////////////////////////////////////////////////////////////
    ///////////////////////// SVG //////////////////////////////
    //////////////////////////////////////////////////////////// 

    const svg = d3.select("#chart")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom);

    const g = svg.append("g")
      .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");

    ////////////////////////////////////////////////////////////
    ///////////////////// Axes & Scales ////////////////////////
    ////////////////////////////////////////////////////////////

    //X axis - dynamic
    let xAxisGroup = g.append("g")
      .attr("class", "x-axis")
        .attr("transform", "translate(0," + (height) + ")");

    let xScale = d3.scaleTime();

    const xAxis = d3.axisBottom(xScale)
      .ticks(d3.timeSecond.every(1))
      .tickSizeInner(15)
      .tickFormat(d3.timeFormat("%M:%S"));

    //Y axis - static
    let yAxisGroup = g.append("g")
      .attr("class", "y-axis");

    let yScale = d3.scaleLinear()
      .domain(yDomain)
      .range([height, 0]);

    const yAxis = d3.axisLeft()
      .scale(yScale)
      .tickValues(yTickValues)
      .tickFormat(d3.format(".0f"));

    yAxisGroup.call(yAxis); 

    //Data points - static
    let dataScale = d3.scaleTime()
        .domain([date1,date2])
        .range([0,width]);


    ////////////////////////////////////////////////////////////
    /////////////////////// Functions //////////////////////////
    ////////////////////////////////////////////////////////////


    function drawData(){
        
        xScale.domain([date1, date2])
        .range([0, width]);
        
      xAxisGroup
        .transition()
            .duration(TIME_MEASUREMENT)
            .ease(d3.easeLinear)
            .call(xAxis); 

        g.selectAll("circle")
        .data(data)
        .join(
            function(enter){
                enter.append("circle")
                    .attr("cx", (d,i) => dataScale(i*TIME_MEASUREMENT))
                    .attr("cy", (d,i) => yScale(d))
                    .attr("fill", "black")
                    .attr("r","3");
                },
            function(update){
                update
                    .attr("cx", (d,i) => dataScale(i*TIME_MEASUREMENT))
                    .attr("cy", (d,i) => yScale(d))
                    .transition()
                        .ease(d3.easeLinear)
                        .attr("transform", "translate(" + dataScale(-TIME_MEASUREMENT) + ", 0)");   
            }
        );  
        data.push(random() + accuracy);
        data.shift();
        
        date1 += TIME_INTERVAL/50;
        date2 += TIME_INTERVAL/50;
    };


    ////////////////////////////////////////////////////////////
    ///////////////////////// Main /////////////////////////////
    ////////////////////////////////////////////////////////////

    d3.interval(drawData, TIME_MEASUREMENT);
    x-axis,
    .y-axis {
      font-size: 0.8em;
      stroke-width: 0.06em;
    }

#chart {
  width: 600px;
  height: 500px;
}
       <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script src="//d3js.org/d3.v6.min.js"></script>
    <div id="chart"></div>

当我使用 d3.timer 或 setInterval 时,我没有得到这种“断断续续的效果”,但是每一秒都在滑动,好像它是 ~850 毫秒。谢谢您的意见!

标签: javascriptgoogle-chromeanimationd3.jssetinterval

解决方案


推荐阅读