初識SVG

最近遇到一個關于彩票中獎號碼展示的項目,里面有很多技術難點,其中一個就是把各開獎號碼之間用線段連接起來,這是一個典型網頁圖形繪制問題。本文嘗試講解如何利用SVG技術實現折線圖形的繪制。

我們知道,在網頁中繪制圖形有很多種方式,如canvas、svg、vml等都可以繪制優秀的矢量圖形。關于它們的區別和適用性比較,可以參考這篇文章,本文只介紹如何使用SVG的基礎知識實現我的工作目的。

首先分析下問題和解決方案

彩票號碼一般都顯示為圓形的小球,上面疊加一個阿拉伯數字。要把一系列小球用直線連接,需要知道每個小球的位置信息,然后用SVG的line方法畫出來。

那么問題來了,我們怎么才能得到小球的位置信息呢?

一般計算機的坐標系都是以左上角為原點,橫向為X軸,縱向為Y軸。SVG坐標系也不例外。

此外,我們把小球都放表格中,并規定好單元格的寬高。以表格的左上角為原點,就能輕松得到每個單元格的XY軸信息,進而得到圓心的坐標。very nice!

svg坐標系

但實際上我們只得到圓心的坐標是不行的,因為SVG層疊加在表格上面,如果用Line方法把各個圓心連接起來,會把小球上面的文字蓋住。所以Line的起止坐標必須在小球的邊緣上。而且,除了第一個和最后一個小球外,每個小球都要有一個畫入點和一個畫出點,分別指向它的上一個小球和下一個小球。

那么問題又來了,怎樣才能得到這些出入點的坐標呢?

思前想后,終于把這個問題抽象為一道數學題:已知一個圓的圓心坐標和半徑,有一條從圓心發出的直線,假設直線與X軸的夾角為a,求該直線與圓相交的點的坐標。

Oh My Dog!這特么解析幾何啊!哥中學課本早燒香了,咋辦?
zzz...


沒辦法,自己畫吧。在紙上算啊算,電腦上測啊測,終于憋出一個公式!

想要草稿紙的自行來取

寫成函數如下:
<code>
function calcPointCoor(cx,cy,r,alpha){
//cx,cy: coordination of the circle
//r: radius
//alpha: angle of line and X axis
return {x:cx + r * Math.cos(alpha),y:cy + r * Math.sin(alpha)};
}
</code>
其中cx,cy是圓心坐標,r是半徑,alpha為角度。

然而如何計算兩個小球之間的角度呢?

還解析幾何啊!想到腦細胞會燒壞一坨,還是算了。我考慮用Snap SVG組件的angle方法來做,這個方法只要兩個點的x,y坐標,就能返回他們之間的夾角。

要注意的是,給angle方法傳入的參數順序不同,得出的角度會有差別。經過測試,angle方法得出的角度值是自X軸正向順時針增加的。這樣,如果要按解析幾何平面坐標系來計算的話,就需要加入或減去一個π周期來修正。

另外,還需要把角度值轉換為弧度值。因為JS中Math對象的正余弦函數只接受弧度值。

經過上帝測試,最終得出以下方法:
<pre><code>
//radius , coordinations of current cicle and next circle
var r,cur_cx,cur_cy,next_cx,next_cy;

//.....

var ang = Snap.angle(next_cx,next_cy,cur_cx,cur_cy) * Math.PI / 180;

var coor1 = calcPointCoor(cur_cx,cur_cy,r, ang);

var coor2 = calcPointCoor(next_cx,next_cy,r, ang + Math.PI);

var c = svg.path("M" + coor1.x + " " + coor1.y + "L" + coor2.x + " " + coor2.y).attr({stroke:stroke_color,strokeWidth:1.5});</code></pre>

這里面的coor1是當前小球到下一個小球的畫出點坐標,coor2是下一個小球的畫入點坐標。

再往下就簡單了,SVG中有Line方法,只要循環一下某一組中所有中獎號碼的小球圓心坐標,就可以搞定一切。

但實際應用中,Path方法比Line方法更高效。因為畫一段線條就得用一個Line,而Path方法只要給出d屬性的M和L值,就可以在一個標簽中實現N段線條,然后你就能方便地切換顯示了。哈哈!

svg實現折線

總結:

  • SVG可以像使用其他HTML標簽一樣來靈活生成,不管你是用PHP還是JavaScript。
  • 對CSS有效的標簽同樣適用于SVG標簽。
  • 能用組件或庫的盡量用,否則死很多腦細胞

文中涉及的技術和組件哥也是現學現賣,歡迎批評指正。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在React Native中使用ARTReact Native ART 究竟是什么?所謂ART,是一個在React...
    JackfengGG閱讀 9,576評論 2 50
  • 一:什么是SVG? 對于SVG的定義如下: ①:SVG 指的是可伸縮矢量圖形 (Scalable Vector G...
    GreenHand1閱讀 828評論 0 1
  • 一.什么是SVG? SVG 指的是可伸縮矢量圖形 (Scalable Vector Graphics),它用來定義...
    nightZing閱讀 17,108評論 11 62
  • SVG 學習筆記 SVG是什么 SVG 指可伸縮矢量圖形 (Scalable Vector Graphics) S...
    Penn_Xu閱讀 1,007評論 0 1
  • 既然了解了運營就是做好產品與用戶之間的橋梁,那么什么樣的“術”可以幫我們思考的更全面,將工作做得更細致,數據更好看...
    桔次郎閱讀 456評論 2 2