snap.svg制作一个完美的圆圈指针"

时间:2016-02-05 21:55:43

标签: javascript jquery svg snap.svg

首先,抱歉主题名称。我无法用一句话来解释我想要做的事情。

然后!我想要做的是一个圆圈,其笔划上有一个正方形,其中将有6" hoverable"正方形。

以下是我所做的测试:

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度。 但是我不知道如何让它表现得那么好,因为我并不擅长数学......

2 个答案:

答案 0 :(得分:3)

您只需要确定两个可能方向中的哪一个具有最短距离。然后将最小的差异添加到累积的旋转值。

<强>演示

&#13;
&#13;
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;
});
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

<强>已更新

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

  1. 当指针先前位于底部正方形(rotate值= 0 )时,鼠标会悬停一个旋转值大于 180 ,我们需要通过 -1 * (360 - rotate) 逆时针移动指针。然后使用回调函数,我们使用动态时间 rotate .animate()函数将旋转度立即设置为原始0

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

  3. 当指针先前位于rotate值为 300 的方格上时,鼠标悬停在rotate值<的方格上强> 60 ,我们需要从 300 转到 420 300 + (360-300) + 60 ),然后使用回调函数将旋转值重置为 60

  4. 当指针先前在方格上且rotate 60 时,我们需要将其设置为正方形,其中rotate 300 ,我们需要从 60 动画到 -60 ,然后立即再次使用回调函数将旋转设置为 300

  5. 最后,我们需要更新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);
        }); 
    }