Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/389.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 为什么动画d3 svg线在IE9中不与轴移动同步,但在IE11和Chrome中同步?_Javascript_Animation_Svg_Timer_D3.js - Fatal编程技术网

Javascript 为什么动画d3 svg线在IE9中不与轴移动同步,但在IE11和Chrome中同步?

Javascript 为什么动画d3 svg线在IE9中不与轴移动同步,但在IE11和Chrome中同步?,javascript,animation,svg,timer,d3.js,Javascript,Animation,Svg,Timer,D3.js,以下是两个JSIDdle: 调用勾号的代码: 调用勾号的代码: 进行测试1: 使用IE 11或Chrome浏览器打开JSFiddle 1和JSFiddle 2 观察动画svg行 进行测试2: 使用IE9浏览器打开JSFiddle 1和JSFiddle 2 观察动画svg行 在测试1中,我观察到动画svg线的起点与轴移动一起移动,因此它在视觉上看起来是同步的。因此,您将看到一条平滑的动画线 在测试2中,我观察到svg线的起点并没有随着轴的移动而移动,因此它在视觉上看起来是不同步的。因此,您会看到一

以下是两个JSIDdle:

调用勾号的代码:

调用勾号的代码:

进行测试1:

  • 使用IE 11Chrome浏览器打开JSFiddle 1和JSFiddle 2
  • 观察动画svg行
  • 进行测试2:

  • 使用IE9浏览器打开JSFiddle 1和JSFiddle 2
  • 观察动画svg行
  • 在测试1中,我观察到动画svg线的起点与轴移动一起移动,因此它在视觉上看起来是同步的。因此,您将看到一条平滑的动画线

    在测试2中,我观察到svg线的起点并没有随着轴的移动而移动,因此它在视觉上看起来是不同步的。因此,您会看到一条有点奇怪的抖动线

    有人知道是什么原因导致了这种情况吗?如何在IE9中解决这个问题?

    我上传了一段视频,演示了这个问题:

    编辑

    根据Amelia的回答,我上传了带有
    自定义tween函数的改进版本


    我对她的答案做了一些小的调整,用x(t-n+2)代替x(t-n+1)。即使线条不平滑,但至少现在与轴偏移同步:

    我怀疑问题只是IE9不支持该方法。D3使用requestAnimationFrame(如果可用)

    这是有区别的,因为requestAnimationFrame方法将一系列连续调用捆绑到一个“frame”中,并将所有调用传递给相同的时间戳值。如果没有requestAnimationFrame方法,每个转换将获得不同的时间戳,延迟时间取决于浏览器完成上一个任务所用的时间

    不幸的是,对于坚持使用过时浏览器的人来说,没有简单的解决方案来解决这个问题

    您所能做的就是尽可能提高代码的效率。例如,当前正在创建单独的变换,以按相同的变换量移动每条路径。如果您创建了一个
    元素并绘制了其中的所有路径,那么您只需要一个变换和一个转换

    var graph = g.append("svg")
         .attr("width", width)
         .attr("height", height + margin.top + margin.bottom);
    
    var plot = graph.append("g").attr("class", "plot");
    
    var path1 = plot.append("g").append("path")
    
    /* etc for the other paths */
    
    然后在
    tick()
    函数中:

    • 重新绘制线时,不要在路径元素上设置任何变换,而是使用清除打印变换

      plot.attr("transform", null);
      
    • 将所有路径转换替换为

       plot.transition()
           .duration(duration)
           .ease("linear")
           .attr("transform", "translate(" + x(t - n + 1) + ")");
      

    (让我知道这是否是IE9中的一个显著改进——IE11仿真工具没有真正显示问题,因此我无法有效地进行测试。)

    顺便说一下,您还可以通过使用selection&datajoin来绘制不同的代码行,从而大大缩短代码。查看d3中有关选择和联接的更多信息

    编辑 感谢您的反馈,很抱歉仍然没有改进。下面的方法更复杂,如果您是d3新手,可能很难遵循,但它应该强制同步。请注意,动画可能仍会跳跃,但直线和轴应同时跳跃

    其思想是只使用一个过渡,然后在过渡的每个滴答声同时更新绘图平移和轴。这是用一个简单的方法完成的。它假定您已经进行了上述更改

    特别是,我没有使用默认轴函数为每个子组件创建单独的过渡,而是使用与直线相同的方法:绘制不带过渡的轴,然后使用变换将其侧向移动。两种变换都应用于同一tween函数中

     plot.attr("transform", null);
    
     // redraw the axis, without transition
     axis.call(xAxis).attr("transform", null);
    
     // slide the line left
     plot.transition()
         .duration(duration)
         .ease("linear")
         .attrTween("transform", 
           function(){
               //this function is run for every element 
               //in the selection (which only has one element).
    
               //create an interpolator function
               var inter = d3.interpolateString("translate(0,0)", 
                        "translate(" + x(t - n + 1) + ")");
    
               return function(t) {
                   //this function is called at every "tick"
                   //of the transition
    
                   //transition the axis
                   axis.attr("transform", inter(t) );
    
                   //return the value to transition the plot
                   return inter(t);
               };
           })
         .each("end", tick); //loop
    
    还有一个额外的复杂性:x轴
    元素已经有了一个transform属性,将其向下移动到图形的底部。我可以每次都重复这个转换,这样转换后的属性看起来像是
    axis.attr(“transform”,“translate(0,+height+)”+inter(t))。但是,我决定通过为轴使用嵌套的
    元素来保持简单:垂直变换应用于外部组,水平变换应用于内部组:

    var xAxis = d3.svg.axis().scale(x)
             .orient("bottom")
             .outerTickSize(0);
    
     var axis = graph.append("g") //outer group handles the vertical transform
         .attr("class", "x axis")
         .attr("transform", "translate(0," + height + ")")
         .append("g") 
              //this nested <g> will be stored in the `axis` variable!
              //and therefore will get the horizontal transform attribute
         .call(x.axis = xAxis);
    
    var xAxis=d3.svg.axis().scale(x)
    .orient(“底部”)
    .outerTickSize(0);
    var axis=graph.append(“g”)//外部组处理垂直变换
    .attr(“类”、“x轴”)
    .attr(“变换”、“平移(0)”、“高度+”)
    .附加(“g”)
    //此嵌套将存储在'axis'变量中!
    //因此将获得水平变换属性
    .调用(x.axis=xAxis);
    
    请注意,我还将
    .outerTickSize(0)
    添加到轴定义中。这可以防止轴在域的开始和结束处绘制额外的记号标记——外部记号在Y轴的底部显示为一条奇怪的闪烁线,每次重新绘制轴时都会出现,然后随着轴的移动立即消失


    另外,如果您的客户仍然感到失望,请冷静、礼貌地提醒他或她IE9是一款过时的浏览器,它不具备最新浏览器生成平滑动画的功能。如果有人想要最新最好的网站,他们需要使用最新最好的浏览器

    你的回答让我的一天充满活力,但建议的解决方案在视觉上没有任何区别。IE11 emulator无法模拟该问题。但在真正的IE9版本中,问题确实存在。(我今天将IE11降级为IE9,并验证了问题。我用youtube演示更新了我的问题,这样可以帮助您更好地理解问题。@jhyap:让我知道新版本的外观。令人印象深刻的改进,但在任何路径到达轴末端时都会出现轻微的后移问题。请参阅我为上传的
    视频2
    de>x(t-n+1)
    问题。因此,我调整了
    d3.interpo
    
     plot.attr("transform", null);
    
     // redraw the axis, without transition
     axis.call(xAxis).attr("transform", null);
    
     // slide the line left
     plot.transition()
         .duration(duration)
         .ease("linear")
         .attrTween("transform", 
           function(){
               //this function is run for every element 
               //in the selection (which only has one element).
    
               //create an interpolator function
               var inter = d3.interpolateString("translate(0,0)", 
                        "translate(" + x(t - n + 1) + ")");
    
               return function(t) {
                   //this function is called at every "tick"
                   //of the transition
    
                   //transition the axis
                   axis.attr("transform", inter(t) );
    
                   //return the value to transition the plot
                   return inter(t);
               };
           })
         .each("end", tick); //loop
    
    var xAxis = d3.svg.axis().scale(x)
             .orient("bottom")
             .outerTickSize(0);
    
     var axis = graph.append("g") //outer group handles the vertical transform
         .attr("class", "x axis")
         .attr("transform", "translate(0," + height + ")")
         .append("g") 
              //this nested <g> will be stored in the `axis` variable!
              //and therefore will get the horizontal transform attribute
         .call(x.axis = xAxis);