jQuery动画沿着圆形路径运动

3
我正在使用jQuery动画创建一个UI。目标是拥有一个圆形菜单,当我们点击链接时,一个对象将沿着圆形菜单的外部路径移动。 嗯...不清楚吗?让我给你展示我的fiddle: 这是我的第一次尝试: Fiddle one
function driveTo(new_value){
  pre_value = document.getElementById("pre_value").value;
  var arc_params = {
      center: [180,180],
      radius: 180,
      start: pre_value,
      end: new_value,
      dir: -1
   }
$(".car").animate({path : new $.path.arc(arc_params)})
document.getElementById("pre_value").value = new_value;

}

这个尝试存在一个问题...如果绿点在90度,你点击270度会出现一些我不理解的疯狂行为,但最终仍会停在正确的位置?!
还有我的第二个: Fiddle two
function driveTo(new_value){
  pre_value = document.getElementById("pre_value").value;

  // catch if the new position is bigger than the previous one
  if (new_value > pre_value) {
    var arc_params = {
            center: [180,180],
               radius: 180,
               start: pre_value,
               end: 0,
               dir: -1
            }
      $(".car").animate({path : new $.path.arc(arc_params)})
    var arc_params = {
            center: [180,180],
               radius: 180,
               start: 0,
               end: new_value,
               dir: -1
            }
      $(".car").animate({path : new $.path.arc(arc_params)})
  }
  else{
    var arc_params = {
            center: [180,180],
               radius: 180,
               start: pre_value,
               end: new_value,
               dir: -1
            }
      $(".car").animate({path : new $.path.arc(arc_params)})
  }

document.getElementById("pre_value").value = new_value;

}

在这个版本中,我试图通过检查新值是否大于先前的值来解决我在第一个命题中遇到的问题。如果是真的,对象必须首先到达位置0,然后继续到新值。
但是,问题在于显然当物体到达零时会减速,然后再次加速以达到原始目标。
我认为这不是很好...我希望我可以避免这种情况!
我正在使用jQuery arc path plugin,但关于它的文档非常少...
有什么建议吗?
更新
这里有一个更好的fiddle,基于形状需要行进的距离,具有实际的线性速度。甚至还有一个可以设置的速度因素:)
2个回答

2

我不明白为什么会出现这种疯狂的情况,但是这里有一些解决方法:

  1. If you can tolerate going counter-clockwise, you can just remove the dir param, or set it to dir: 1 and it seems to "behave".

  2. If you just want the shortest distance regardless of direction, you could do something like:

    var value_sub = pre_value - new_value;
    var which_dir = value_sub == 90 || value_sub == -270 ? -1 : 1;
    

    then set dir: which_dir in the params. This seems to avoid the craziness.

  3. If you must have clockwise (and I'm guessing you might, since you have dir set to -1 all your examples), you could use your two-animation work-around (clever, BTW) and avoid the slow-down at 0 by overriding .animate()'s default "easing" setting, which is "swing". For example, at http://jsfiddle.net/2mhynskz/8/, I've changed your animations to look like

    $(".car").animate({path : new $.path.arc(arc_params)},400,"linear")
    

    I just used 400 since it's apparently the default duration setting. (Of course, you could make that variable too, if you wanted it to appear to have a constant velocity.) If you still need a swing-like effect, you could probably fake it by making the second .animate()'s duration longer.


我刚刚意识到,不同长度的遍历有时会重复进行,每次间隔400毫秒,这样会产生不均匀的缓动效果,因此您可能需要根据特定的遍历情况使400成为可变量。 - Max Starkenburg
太好了,非常有帮助!!!是的,我必须使用选项3,因为我的动画是一辆汽车 :) - Valentincognito
我将致力于寻找一种更稳定的方式来获得真正的线性动画效果,并发布最终答案。 - Valentincognito
很好。很高兴我能提供一些帮助(我只是惊讶于这样的插件存在)。我想知道你最初的问题是否值得在插件的GitHub页面上报告错误。目前太累了,无法调查这种行为是否实际上是一个“特性”,哈哈。 - Max Starkenburg

1

几年前我曾经制作过一个插件,它叫做jQuery Vortex

我没有使用弧形路径插件或任何其他插件,所以我的方法可能会有所不同。以下是代码片段,其中元素在圆(或椭圆)周围等距离定位:

            originalKidsSize[i] = {
                width: $(this).width(),
                height: $(this).height()
            };

            var kidHalfHeight = $(this).height() / 2;
            var kidHalfWidth = $(this).width() / 2;

            var kidPositions = [];

            for (var j = 0; j < positionsCount; j += 1) {

                kidPositions.push({
                    top: ((1 + Math.sin(offsetPosition + (j / radiantFactor))) * vortexHalfHeight) - kidHalfHeight,
                    left: vortexHalfWidth * (1 + Math.cos(offsetPosition + (j / radiantFactor))) - kidHalfWidth
                });

            }

            var positionIndex = i * Math.round(positionsCount / kids.length);

            kidsPositionIndexes[i] = positionIndex;

            var radiantVariable = (Math.sin(offsetPosition + positionsRadiants[positionIndex]) * settings.deepFactor);
            var resizeFactor = (1 + radiantVariable);

            var newWidth = originalKidsSize[i].width * resizeFactor;
            var newHeight = originalKidsSize[i].height * resizeFactor;

            $(this)
                .css({
                    "width": newWidth,
                    "height": newHeight,
                    "top": kidPositions[positionIndex].top - ((newHeight - (originalKidsSize[i].height)) / 2),
                    "left": kidPositions[positionIndex].left - ((newWidth - (originalKidsSize[i].width)) / 2),
                    "z-index": 200 + Math
                        .round(100 * (Math
                            .sin(offsetPosition + positionsRadiants[positionIndex])))
                });

当时CSS3硬件加速的过渡在不同的浏览器上并不成熟,因此应用了CSS2过渡。

随意尝试集成CSS3过渡:这是 github存储库中的链接


虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - Kousik
1
好的,我添加了更多信息和与问题相关的代码片段。 - Luca Fagioli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接