2014-09-20 43 views
0

我正在製作一個腳本,可以讓我在兩個或多個具有相同數值的關鍵幀之間製作一個簡單的svg路徑補間(平滑變形動畫)。我輸入的形狀應該將橢圓形(關鍵幀[0])變形爲對話泡泡形狀(關鍵幀[1])。SVG路徑計算結果在所有零點座標

我遇到的問題是,當我嘗試調試,它告訴我,svg元素具有值都爲0。

<path d="M0, 0, Q0, 0, 0, 0, L0, 0, Q0, 0, 0, 0, L0, 0, Q0, 0, 0, 0, L0, 0, Q0, 0, 0, 0, L0, 0, L0, 0, L0, 0, Z" fill="#ffffff" stroke="#000000"></path> 

當控制檯顯示我的價值就應該

M-68.39999999999999, -18.787499999999998, Q-72.9, 0, -97.2, -4.5, L-97.2, -258.525, Q-121.5, -263.02500000000003, -116.99999999999999, -281.8125, L68.39999999999999, -281.8125, Q72.9, -300.59999999999997, 97.2, -296.1, L97.2, -42.075, Q121.5, -37.574999999999996, 116.99999999999999, -18.787499999999998, L48.6, -18.787499999999998, L24.3, 18.787499999999998, L0, -18.787499999999998, ZM-70.93333333333334, -19.483333333333334, Q-75.60000000000001, 0, -100.8, -4.666666666666666, L-100.8, -268.09999999999997, Q-126, -272.76666666666665, -121.33333333333333, -292.25, L70.93333333333334, -292.25, Q75.60000000000001, -311.73333333333335, 100.8, -307.06666666666666, L100.8, -43.63333333333333, Q126, -38.96666666666667, 121.33333333333333, -19.483333333333334, L50.4, -19.483333333333334, L25.2, 19.483333333333334, L0, -19.483333333333334, Z 

必須有我的地方是有一個錯誤,但我留下抓我的頭,爲什麼這是行不通的。

JS:

$(function() { 

    var sponsorBubble = function(el, html, cornerRad) { 
     this.html = html, 
     this.width = el.parent().width(), 
     this.height = el.parent().height(), 
     this.arrowWidth = el.parent().width()/4, 
     this.arrowHeight = el.parent().height()/8, 
     this.cornerRad = cornerRad; 


     //ENSURE SAME NUMBER OF PATH SEGMENTS IN ALL KEYFRAMES (START TO END) 
     this.keypaths = []; 

     this.keypaths[0] = [ 
      "M", 
      (this.width/2) - (this.arrowWidth/2), this.height - (this.arrowHeight/2), 
      "Q", 
      (this.width/2) - (this.arrowWidth/2), this.height - this.arrowHeight, 
      (this.width/2), this.height - this.arrowHeight, 
      "L", 
      (this.width/2), this.height - this.arrowHeight, 
      "Q", 
      (this.width/2) + (this.arrowWidth/2), this.height - this.arrowHeight, 
      (this.width/2) + (this.arrowWidth/2), this.height - (this.arrowHeight/2), 
      "L", 
      (this.width/2) + (this.arrowWidth/2), this.height - (this.arrowHeight/2), 
      "Q", 
      (this.width/2) + (this.arrowWidth/2), this.height, 
      (this.width/2), this.height, 
      "L", 
      (this.width/2), this.height, 
      "Q", 
      (this.width/2) - (this.arrowWidth/2), this.height, 
      (this.width/2) - (this.arrowWidth/2), this.height - (this.arrowHeight/2), 
      "L", 
      (this.width/2) - (this.arrowWidth/2), this.height - (this.arrowHeight/2), 
      "L", 
      (this.width/2) - (this.arrowWidth/2), this.height - (this.arrowHeight/2), 
      "L", 
      (this.width/2) - (this.arrowWidth/2), this.height - (this.arrowHeight/2), 
      "Z" 
     ]; 

     this.keypaths[1] = [ 
      "M", //STARTS AT BOTTOM LEFT, GOING CLOCKWISE 
      this.cornerRad, this.height-this.arrowHeight, 
      "Q", 
      0, this.height-this.arrowHeight, 
      0, this.height-this.arrowHeight-this.cornerRad, 
      "L", 
      0, this.cornerRad, 
      "Q", 
      0,0, 
      this.cornerRad, 0, 
      "L", 
      this.cornerRad+(this.width - (this.cornerRad*2)), 0, 
      "Q", 
      this.width, 0, 
      this.width, this.cornerRad, 
      "L", 
      this.width, this.cornerRad+(this.height-this.arrowHeight-(this.cornerRad*2)), 
      "Q", 
      this.width, this.height-this.arrowHeight, 
      this.width-this.cornerRad, this.height-this.arrowHeight, 
      "L", 
      (this.width/2)+(this.arrowWidth/2), this.height-this.arrowHeight, 
      "L", 
      this.width/2, this.height, 
      "L", 
      (this.width/2)-(this.arrowWidth/2), this.height-this.arrowHeight, 
      "Z" 
     ]; 


    }; 

    sponsorBubble.prototype.getFrame = function(frame, total_steps, current_step) { 

    if (this.keypaths[frame + 1]) { //IF THERES FRAMES AFTER 
     for (var i = 0; i <= this.keypaths[frame].length; i++) { 
      //IF IS A LETTER 
      if (isNaN(this.keypaths[frame][i])) { 
       if (this.newpath && i < this.keypaths[frame].length - 1) { 
        this.newpath = this.newpath + this.keypaths[frame][i]; 
       } 
       else if (!this.newpath) { 
        this.newpath = this.keypaths[frame][i]; 
       } 
       else if (this.newpath && i == this.keypaths[frame].length - 1) { 
        this.newpath = this.newpath + this.keypaths[frame][i]; 
       } 
      } 

      //IF IS A NUMBER 
      else { 
       if (this.newpath && i < this.keypaths[frame].length - 1) { 
        this.newpath = this.newpath + (((this.keypaths[frame + 1][i] - this.keypaths[frame][i])/total_steps) * current_step) + ", "; 
       } 
       else { 
        this.newpath = this.newpath + this.keypaths[frame][i]; 
       } 
      } 
     } 
    } 

    else { //NO FRAMES AFTER 
     for (var i = 0; i <= this.keypaths[frame].length; i++) { 
      //IF IS A LETTER 
      if (isNaN(this.keypaths[frame][i])) { 
       if (this.newpath && i < this.keypaths[frame].length - 1) { 
        this.newpath = this.newpath + this.keypaths[frame][i]; 
       } 
       else if (!this.newpath) { 
        this.newpath = this.keypaths[frame][i]; 
       } 
       else if (this.newpath && i === this.keypaths[frame].length - 1) { 
        this.newpath = this.newpath + this.keypaths[frame][i]; 
       } 
      } 

      //IF IS A NUMBER 
      else { 
       if (this.newpath && i < this.keypaths[frame].length - 1) { 
        this.newpath = this.newpath + this.keypaths[frame][i] + ", "; 
       } 
       else { 
        this.newpath = this.newpath + this.keypaths[frame][i]; 
       } 
      } 
     } 
    } 

     current_step++; 

     if (current_step < total_steps) { 
       console.log(this.newpath); 
      requestAnimationFrame(function() { 
       bub.getFrame(frame, total_steps, current_step); 
      }); 
     } 
} 

snapper = Snap('#svg'); 
var bub = new sponsorBubble($('#svg'), 'test', 5, 20); 
bub.getFrame(0, 30, 0); 

var test = snapper.path(bub.newpath); 
    test.attr({ 
     fill: 'white', 
     stroke: 'black' 
    }); 
}); 

HTML:

<!DOCTYPE html> 
<html> 
    <head> 
     <link type="text/css" rel="stylesheet" href="bubble.css" /> 
     <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
     <script type="text/javascript" src="snap.svg-min.js"></script> 
     <script type="text/javascript" src="bubble.js"></script> 
    </head> 

    <body> 
     <div id="inset"> 
      <div id="inset2"> 
       <svg id="svg" width="100%" height="100%"></svg> 
      </div> 
     </div> 
    </body> 

</html> 

CSS:

body, html { 
    width: 100%; 
    height: 100%; 
    border: 0; 
    padding: 0; 
    margin: 0; 
} 

#inset { 
width: 20%; 
height: 50%; 
position: absolute; 
bottom: 0; 
left: 50%; 
} 

#inset2 { 
width: 80%; 
height: 100%; 
} 

的jsfiddle: http://jsfiddle.net/bmjkz1rf/

回答

1

你的插值算法是錯誤。

要兩個值x0x1之間進行插值,計算公式爲:當前

x0 + ((x1 - x0) * current_step/total_steps) 

的代碼丟失的第一x0術語。

我認爲還有更多需要解決的問題。現在,this.newpath是一個字符串,隨着遞歸的進行而增長和增長,在「Z」之後和下一個「M」之前沒有任何劃定。我不知道究竟需要什麼,但我不認爲這是正確的。即使你修正了「... ZM ...」的描述,你仍然會得到一個怪物字符串,而我想你想要一個單獨的幀(一個數組?)。

即使我錯了,你確實需要一個怪物字符串,最好是拋棄.getFrame()的遞歸併迭代地調用它,在每次迭代中返回一個幀的數據值,從而建立最終的數據結構在調用函數中。

+0

哦,你是對的。甚至沒有注意到這一點。這個想法是迭代地調用每一幀,我只是沒有意識到它是添加而不是替換路徑數據。無論哪種方式,謝謝很多人 – tomc 2014-09-21 05:46:50

+1

我假設你的情況需要別的東西,但我認爲我會提到Snap將已經變成相同數量的點之間的路徑,http://stackoverflow.com/questions/22987836/how -an-animate-path-morphs-using-snap-svg – Ian 2014-09-21 08:54:09

+0

@Ian,很好!正如你可能知道的那樣,我對SVG知之甚少。我只是從javaScript和簡單的數學知識中進行調試。 – 2014-09-21 09:13:12