在千分表

时间:2018-04-12 23:52:06

标签: snap.svg

我想模拟千分表。仪表需要有多个框架才能显示不同的值。在这个jsfiddle示例中,仪表从30开始到80和150.我想运行各种各样的角度(30,80,150,200,90,24 ....)。不幸的是,代码将需要多个不可扩展的功能。

var s = Snap("#svg836");


var textval=s.select("#text846");

var canvasSize = 400,
    centre = canvasSize/2,
    radius = canvasSize*0.8/2,
    s = Snap('.gauge'),
    path = "",
    startY = centre-radius,
    arc = s.path(path);

function fill1(startpoint, endpoint) {
    console.log("FILL1");
    Snap.animate(startpoint, endpoint,   function (val) {
        console.log(path);
        arc.remove();
        var d = val,
          dr = d-180;
          radians = Math.PI*(dr)/180,
          endx = centre + radius*Math.cos(radians),
          endy = centre + radius * Math.sin(radians),
          largeArc = d>180 ? 1 : 0;
          path = "M"+startY+","+centre+" A"+radius+","+radius+" 0 "+largeArc+",1 "+endx+","+endy;
          arc = s.path(path);
          if (endpoint<=45)
          {
              arc.attr({
                stroke: 'green',
                fill: 'none',
                strokeWidth: 44,
              });
          } else if (endpoint<=90){
                 arc.attr({
                stroke: 'blue',
                fill: 'none',
                strokeWidth: 44,
              });
          } else if (endpoint<=135){
                 arc.attr({
                stroke: 'yellow',
                fill: 'none',
                strokeWidth: 44,
              });
          } else {
                 arc.attr({
                stroke: 'red',
                fill: 'none',
                strokeWidth: 44,
              });
          }
    }, 1500, mina.backout, function (){
    fill2(80,150);
    });


}


function fill2(startpoint, endpoint) {
   console.log("FILL2");

    Snap.animate(startpoint, endpoint,   function (val) {

        arc.remove();
        var d = val,
          dr = d-180;
          radians = Math.PI*(dr)/180,
          endx = centre + radius*Math.cos(radians),
          endy = centre + radius * Math.sin(radians),
          largeArc = d>180 ? 1 : 0;
          path = "M"+startY+","+centre+" A"+radius+","+radius+" 0 "+largeArc+",1 "+endx+","+endy;
          console.log(path);
          arc = s.path(path);
          if (endpoint<=45)
          {
              arc.attr({
                stroke: 'green',
                fill: 'none',
                strokeWidth: 44,
              });
          } else if (endpoint<=90){
                 arc.attr({
                stroke: 'blue',
                fill: 'none',
                strokeWidth: 44,
              });
          } else if (endpoint<=135){
                 arc.attr({
                stroke: 'yellow',
                fill: 'none',
                strokeWidth: 44,
              });
          } else {
                 arc.attr({
                stroke: 'red',
                fill: 'none',
                strokeWidth: 44,
              });
          }
    }, 1500, mina.backout);


}


startpoint=30;
endpoint=80;
fill1(startpoint, endpoint);

似乎有一种alternate方法来对动画进行排序。但是,我不清楚如何设置多个帧以使用该方法。

更新

基于this代码,jsfiddle已更新为this。我们的想法是创建一个函数数组(称为myFrames),每个函数代表一个序列。不幸的是,myFrames [0]确实运行如console.log所示,但myFrames [1]会立即被触发,因此永远不会绘制myFrames [0]的动画。

任何提示?

Snap.plugin( function( Snap, Element, Paper, global ) {

function nextSequence ( sequenceArray,  whichSequence ) {

    // we're finished
    if( whichSequence >= sequenceArray.length ) { return }

    // If we've just got one object and not an array of animations, place it in an array to iterative over. If 2nd param is number, its simple array form
    var animations = ((sequenceArray[ whichSequence ].constructor === Array) && ( isNaN(parseFloat(sequenceArray[ whichSequence ][1]))) ) ? sequenceArray[ whichSequence ] : [ sequenceArray[ whichSequence ] ];

    // Lets go through the next animation sequence, deal with concurrent/synced animations within a sequence
    for( var animCount = 0; animCount < animations.length; animCount++) {        
      var thisEl = this;

      // closure for multiple animations, as we don't want to call the next sequence more than one time
      (function(){  
          var animation = animations[ animCount ];
          var el = animation.el || thisEl;
          var lastConcurrentAnim = animCount == animations.length - 1 ? 1 : 0;

          // deal with a function call returning Snap.animate(0,1....) or something, just must have a dur 
          if( typeof animation === 'function') { 
              var animFunc = animation.call( el );
              var duration = ( animFunc && animFunc.dur ) ? animFunc.dur : 0;
              if( lastConcurrentAnim ) // finally call the next main sequence
                setTimeout( nextSequence.bind( el, sequenceArray, whichSequence + 1 ), duration )

          } else { // all the other standard possible animation objects and arrays            
              if( typeof animation.onStart === 'function' ) animation.onStart.call(sequenceArray[ whichSequence ].el)               

              el.animate(
                  animation.attr || animation[0],
                  animation.dur  || animation[1],
                  animation.easing || animation[2] || mina.linear,
                  function() {
                      var callback = animation.callback || animation[3];
                      if( callback ) callback.call( el ) 
                      if( lastConcurrentAnim ) // finally call the next main sequence
                        nextSequence.call( el, sequenceArray, whichSequence + 1 ) // callback after each
                  }
              );                                                
          };

      })();          
    }; // end for loop
    thisEl = el = null;  

};

// Takes an array of sequences..these contain either a Snap animation OR 
// el: element (optional), attrs: animations to change (required), dur: duration (required), onStart: function to perform on start, onEnd: function to perform on end
Element.prototype.animateSequence = function( animSequence ) {
    nextSequence.call( this, animSequence, 0 );
};

});






var s = Snap("#svg836");

var textval=s.select("#text846");

var canvasSize = 400,
    centre = canvasSize/2,
    radius = canvasSize*0.8/2,
    s = Snap('.gauge'),
    path = "",
    startY = centre-radius,
    arc = s.path(path);
        var d = 20,
          dr = d-180;
          radians = Math.PI*(dr)/180,
          endx = centre + radius*Math.cos(radians),
          endy = centre + radius * Math.sin(radians),
          largeArc = d>180 ? 1 : 0;
          path = "M"+startY+","+centre+" A"+radius+","+radius+" 0 "+largeArc+",1 "+endx+","+endy;
          arc = s.path(path);

var dur = 2000;

//Create function to draw an arc
function drawarc(startpoint,endpoint) { return Snap.animate( startpoint,endpoint, function (val) {

        arc.remove();
        var d = val,
          dr = d-180;
          radians = Math.PI*(dr)/180,
          endx = centre + radius*Math.cos(radians),
          endy = centre + radius * Math.sin(radians),
          largeArc = d>180 ? 1 : 0;
          path = "M"+startY+","+centre+" A"+radius+","+radius+" 0 "+largeArc+",1 "+endx+","+endy;
          arc = s.path(path);
          if (endpoint<=45)
          {
              arc.attr({
                stroke: 'green',
                fill: 'none',
                strokeWidth: 44,
              });
          } else if (endpoint<=90){
                 arc.attr({
                stroke: 'blue',
                fill: 'none',
                strokeWidth: 44,
              });
          } else if (endpoint<=135){
                 arc.attr({
                stroke: 'yellow',
                fill: 'none',
                strokeWidth: 44,
              });
          } else {
                 arc.attr({
                stroke: 'red',
                fill: 'none',
                strokeWidth: 44,
              });
          }
    }, dur, function() {
    console.log("animation step complete with " + endpoint);
    }

    );
}


//Embed drawarc in another function to create an array of functions
function func(startpoint,endpoint){
  return function(){
    drawarc(startpoint,endpoint);
  }
}

//Create an array of functions
var mypoints=[0,30,150];
var myFrames =[];
var i;
for (i = 1; i < mypoints.length; i++) 
{
   var startpoint=mypoints[i-1];
   var endpoint=mypoints[i];
   myFrames.push(func(startpoint, endpoint));
}

 var sequence = [
   myFrames[0],
   myFrames[1]


];


arc.animateSequence( sequence );

1 个答案:

答案 0 :(得分:0)

原始的序列代码会占用很多位,而且你能给它的东西并不明显。

如果它是一个函数,它需要至少返回一个带有dur(持续时间)的对象,例如

return { dur: 2000 }

如果是一个Snap.animation调用,这已经返回一个持续时间的对象,所以我认为没有必要。

但是,如果它是一个Snap.animate()调用,我们只通过执行它来知道持续时间。如果我们执行它,动画已经在运行,这是不行的。

因此,如果你想使用一个函数,你需要做类似......

的事情
function func2(startpoint,endpoint) { 
    return function(){ drawarc(startpoint,endpoint); 
                       return { dur: dur };
                      } 
}

它可能看起来不直观,因为动画本身已经有了持续时间,但由于你在函数中做其他事情(例如调用drawarc),它不知道这个持续时间。

jsfiddle