【问题标题】:snap.svg making a perfect "circle pointer"snap.svg 制作完美的“圆形指针”
【发布时间】:2016-02-05 21:55:42
【问题描述】:

首先,抱歉主题名称。我真的无法用一句话准确地解释我想要做什么。

那么!我想要做的是一个笔划上有一个正方形的圆圈,里面会有6个“可悬停”的正方形。

这是我所做的测试:

var s = Snap(500, 500);

var thecircle = s.circle(250,250,100).attr({fill:'none',stroke:'red','stroke-width':'2'});
var pointer = s.rect(240,340,20,20);
var william = s.g(thecircle, pointer);

var hover1 = s.rect(240,290,20,20).attr({'value':'0'}).addClass('hovering');
var hover2 = hover1.clone().transform('r60,250,250').attr({'value':'60'}).addClass('hovering');
var hover3 = hover1.clone().transform('r120,250,250').attr({'value':'120'}).addClass('hovering');
var hover4 = hover1.clone().transform('r180,250,250').attr({'value':'180'}).addClass('hovering');
var hover5 = hover1.clone().transform('r240,250,250').attr({'value':'240'}).addClass('hovering');
var hover6 = hover1.clone().transform('r300,250,250').attr({'value':'300'}).addClass('hovering');

var $ = jQuery;

$('.hovering').mouseenter(function(){
  var rotate = $(this).attr('value');
  william.animate({transform:'r'+rotate+',250,250'},300,mina.ease);
});

这是一个小提琴,您可以检查动画的外观:JSfiddle

现在,看看当您将鼠标悬停在第 6 个方格(300 度)然后悬停在第 2 个方格(60 度)时会发生什么。指针会在第 5、第 4 和第 3 条前面一直移动,然后到达第 2 条(行程 240 度)。

我想让我的指针以最快的路线到达目的地,在本例中,它是 420 度。 但我不知道如何让它表现得那样,因为我的数学不太好......

【问题讨论】:

    标签: javascript jquery svg snap.svg


    【解决方案1】:

    您只需要计算出两个可能方向中的哪个方向的距离最短。然后将最小的 diff 添加到累积的旋转值中。

    演示

    var s = Snap(500, 500);
    
    var thecircle = s.circle(250,250,100).attr({fill:'none',stroke:'red','stroke-width':'2'});
    var pointer = s.rect(240,340,20,20);
    var william = s.g(thecircle, pointer);
    
    var hover1 = s.rect(240,290,20,20).attr({'value':'0'}).addClass('hovering');
    var hover2 = hover1.clone().transform('r60,250,250').attr({'value':'60'}).addClass('hovering');
    var hover3 = hover1.clone().transform('r120,250,250').attr({'value':'120'}).addClass('hovering');
    var hover4 = hover1.clone().transform('r180,250,250').attr({'value':'180'}).addClass('hovering');
    var hover5 = hover1.clone().transform('r240,250,250').attr({'value':'240'}).addClass('hovering');
    var hover6 = hover1.clone().transform('r300,250,250').attr({'value':'300'}).addClass('hovering');
    
    var $ = jQuery;
    // What rotate currently is
    var lastRotate = 0;
    // Actual transform rotate accumulates up or down depending
    // on which direction we have been going in.
    var accumulatedRotation = 0;
    
    $('.hovering').mouseenter(function(){
      // Make sure 'rotate' is a number not a string
      var rotate = parseInt($(this).attr('value'), 10);
      // rotateAlt is the alternative version of rotate (either >360 or <0)
      var rotateAlt = (lastRotate < 180) ? (rotate - 360) : (360 + rotate); 
      // Work out the diff value for each alt
      var diffA = rotate - lastRotate;
      var diffB = rotateAlt - lastRotate;
      // Add the smaller diff to the accumulated rotation
      if (Math.abs(diffA) < Math.abs(diffB))
        accumulatedRotation += diffA;
      else
        accumulatedRotation += diffB;
      william.animate({transform:'r'+accumulatedRotation+',250,250'},300,mina.ease);
      // Remember the last value of 'rotate'
      lastRotate = rotate;
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    【讨论】:

    • 我认为这是我一直在寻找的完美答案,非常感谢!我会彻底研究你的所作所为!
    【解决方案2】:

    更新

    要解决这个问题,首先我们需要创建一个变量prevRotate -最初设置为 0- 来记录指针之前位置的值,然后我们需要处理四种特殊情况(1) 以及正常情况,如下所示:

    1. 当指针之前在底部方块(rotate值=0),鼠标悬停在旋转值大于180的方块时,我们需要将指针逆时针移动-1 * (360 - rotate)。然后使用回调函数,我们使用动画时间为 0.animate() 函数将旋转度 立即 设置为原始 rotate 值。

    2. 当指针最初位于rotate值大于180的正方形上,并将鼠标悬停在旋转值为0的底部正方形上,动画指向360 CW方向的指针,然后使用我们的回调函数将其重置为0

    3. 当指针之前在rotate值为300的方块上时,鼠标悬停在rotate值为60的方块上,我们需要通过从300旋转到420300 + (360-300) + 60)来绘制短路径,然后使用将旋转值重置为 60 的回调函数。

    4. 当指针先前位于 60rotate 值的正方形上时,我们需要用 rotaterotate 将其动画成正方形 strong>,我们需要从 60 动画到 -60 然后立即 将旋转设置为 300 再次使用回调函数。

    最后我们需要更新prevRotate的值来做进一步的比较。

    JS Fiddle 1 - updated 2

    var $ = jQuery,
        prevRotate = 0; // The variable used to store the previous location of the pointer.
    
    $('.hovering').mouseenter(function(){
        var rotate = $(this).attr('value');
    
        // Special case 1, moving the pointer CCW following the short route.
        if( prevRotate == 0){
            var tempR = rotate;
            rotate = rotate > 180 ? -1 * (360 - rotate) : rotate;
            william.animate({transform:'r' +rotate+ ',250,250'},300,mina.ease, function(){
                myCB(tempR);
            });   
        }else{
    
            // Normal case.
            william.animate({transform:'r'+ rotate +',250,250'},300,mina.ease);
        }
    
        if(rotate == 0){
    
            // Special Case 2, animating to 360 instead of 0, then to 0 immediately.
            if(prevRotate > 180){
                william.animate({transform:'r360,250,250'},300,mina.ease,function(){
                    myCB(0);
                }); 
            }
    
        }else if(rotate == 60 && prevRotate == 300){
    
            // Special Case 3, animating from 300 to 60 following the short route.
            william.animate({transform:'r420,250,250'},300,mina.ease, function(){
                myCB(60);
            });          
        }else if(rotate == 300 && prevRotate == 60){
    
            // Special Case 4, animating from 60 to 30 following short route.
            william.animate({transform:'r-60,250,250'},300,mina.ease, function(){
                myCB(300);
            });
        }
    
        // Update the value of the pointer's previous location
        prevRotate = $(this).attr('value');        
    });
    
    // The Callback function to reset rotate values.
    function myCB(theAngle){
        william.animate({transform:'r' +theAngle+ ',250,250'},0);
    }
    

    (1) 请注意,您可以像这样将特殊情况 3 和 4 代码块合并为一个:

    JS Fiddle 2 - Updated

    if((rotate == 60 || rotate == 300) && prevRotate == 360 - rotate){
    
        // Define the destination angle depending on value of rotate
        var newR = (rotate == 60) ? 420 : -60;
        william.animate({transform:'r' +newR+ ',250,250'},300,mina.ease,function(){
            myCB(prevRotate);
        }); 
    }
    

    【讨论】:

    • 这确实是一个有趣的想法!但问题还是一样:指针没有走最快的路线(如果我将鼠标悬停在正方形 1 上,悬停在外面,然后再次悬停,它将完全旋转)。但我认为你让我朝着正确的方向前进!谢谢!
    • @ken,看看这个jsfiddle.net/Mi_Creativity/k8zwnLuz/3,这是你要找的吗?
    • 这是完美的正确方式,但是当在不同的方块之间悬停太快时会出现问题..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 2016-09-25
    • 2011-03-14
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多