RaphaelJS是一個矢量繪圖包,用來在瀏覽器中繪制圖形。
 
          
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Raphael Test</title> </head> <body> <div id="my-canvas" style="width:140px;padding:0px;margin:0px;"> </div> <!--some html doms--> <!--some scripts--> <script type="text/javascript" src="../js/lib/raphael.js"> </script> </body> </html>
代碼和原書細節可能不同,是我自己測試用例,總體按照原書來寫的。
【注意這里,此書里面講解了為什么要把引用raphael.js 放置在html元素的最下方。因為瀏覽器執行html的代碼是順序執行的。你如果把引用放在前面,瀏覽器會先加載它,導致中間有段時間頁面會停滯,這里推薦你先加載dom元素再導入這個js包。】
到此位置,我們的下載和搭建就已經完成了。
在瀏覽器視口創建畫布
創建raphael物體(對象),依賴於raphael的方法和function,如下所示:
var raphaelObj = Raphael(x,y,width,height);
Raphael function中4個參數分別是x坐標、y坐標、寬度、高度。
因為這個是在瀏覽器視口里面來創建的,所以畫布的位置是絕對定位。因此,它會在所有html元素下面重疊。
比如:
// 在瀏覽器視口中創建畫布
var paper = Raphael(20, 30, 650, 400);
這里的Raphael對象被初始化並且分配一個變量稱為paper。這個變量被賦予RaphaelJS的所有權利。它從此以后成為Raphael畫布對象。
在元素中創建Raphael對象(推薦)
要在一個元素中初始化一個Raphael對象,我們必須把這個元素的ID或者這個元素本身加入到坐標系(x,y)中。
我們舉個例子:
//元素本身作為參數
//This line creates a Raphael paper inside 'my-canvas', which is 650pxin width and 400px in height
var elm= document.getElementById("my-canvas");
var paper = Raphael(elm, 650, 400);
//or
// 直接傳遞元素的ID作為參數
//This line also creates a Raphael paper inside 'my-canvas', which is 650px in width and 400px in height
var paper = Raphael("my-canvas", 650, 400);
這樣我們就可以啟動引擎開始跑了!
第二步--繪制圓形
Raphael可以繪制的基本圖形有圓形、矩形和橢圓等。
圓形可以通過調用circle()來發來進行。我們使用剛才的paper對象來進行調用。
語法如下:
var cir = paper.circle(x,y,r);
// x and y are the positioning co-ordinates, and "r" is the radius of the circle
//Here the circle is assigned to a variable called cir.
//Example
var cir = paper.circle(35,25,20);
// This will create a circle of 20 pixels in radius at 35,25 (X & Y axis).
circle()方法一共3個參數,分別是x,y坐標和半徑。我們在剛才的代碼中添加上面的操作。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Raphael Test</title> </head> <body> <div id="my-canvas" style="width:140px;padding:0px;margin:0px;"> </div> <!--some html doms--> <!--some scripts--> <script type="text/javascript" src="../js/lib/raphael.js"> </script> <script type="text/javascript"> var paper = Raphael("my-canvas", 650, 400); var cir = paper.circle(30, 30, 10); </script> </body> </html>
 
效果如上圖所示,由於沒有賦予paper和cir其它屬性,所以沒有顏色之類的屬性,我們看起來不直觀。下面將介紹attr()方法。
attr() 方法
attr()方法,將我們要添加或者修改的屬性作為參數,屬性其實就是鍵值對。如果你熟悉jQuery的話,你就明白attr()的語法與jquery的完全一致。進一步講,就是JSON格式數據。做過js的童鞋們,或多或少應該接觸過JSON。沒接觸過的,建議去翻閱一下資料。比XML更快的數據傳遞方式,以后肯定會大放異彩。
語法如下:
element.attr({ 
"Property1":value1, 
"Property2":value2
})
//加入如下屬性的鍵值對
var coloredCircle = paper.circle(35,25,20).attr({ 
"fill":"#17A9C6", 
"stroke":"#2A6570", 
"stroke-width":2
});
剛才這個例子添加到我們的Script里面就行了,這里不再截圖和添加代碼了。效果是:在坐標(35,25)位置出現一個半徑為20的顏色為深綠的圓(本人色弱,顏色認錯大家莫怪)。
當然,還有其它非常多的屬性可以添加。有興趣大家可以自己去查閱一下資料,這里暫不提及。本書最后部分會有涉及。
下面我們要講的部分是本書的重點,也是學習Raphael.js的重點。上面講了那么多其實不過是三兩行代碼就可以搞定的事情,前提是你正確的下載了包並引用了正確的路徑。接下來我們要講的是創建、操作、轉換、動畫、事件響應等內容,是Raphael的核心部分,也是工作涉及到的重要部分。
你需要了解的重要特性
創建一個Raphael的元素非常容易。為了更加方便,有些已經定義好的方法供生成一些基本的幾何圖形。
基本圖形
RaphaelJS有3個基本圖形,分別是 圓、橢圓和矩形。前面已經講過圓形,這里我就不再贅述圓形了。
矩形
我們可以使用rect()方法來創建一個矩形。這個方法一共有4個必須參數和一個可選參數。5個參數按順序分別是x坐標、y坐標、矩形寬度、矩形高度、圓角半徑。
圓角半徑默認為0,為可選參數。
語法如下:
paper.rect(X,Y,Width,Height,border-radius(optional));
var rect = paper.rect(35,25,170,100).attr({ 
"fill":"#17A9C6", //filling with background color 
"stroke":"#2A6570", // border color of the rectangle 
"stroke-width":2 // the width of the border
});
var rect = paper.rect(35,25,170,100,20).attr({ 
"fill":"#17A9C6", //filling with background color 
"stroke":"#2A6570", // border color of the rectangle 
"stroke-width":2 // the width of the border
});
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Raphael Test</title> </head> <body> <div id="my-canvas" style="width:140px;padding:0px;margin:0px;"> </div> <!--some html doms--> <!--some scripts--> <script type="text/javascript" src="../js/lib/raphael.js"> </script> <script type="text/javascript"> var paper = Raphael("my-canvas", 650, 400); var cir = paper.circle(30, 30, 10); var coloredCircle = paper.circle(55, 45, 20).attr({ "fill": "#17A9C6", "stroke": "#2A6570", "stroke-width": 2 }); var rect = paper.rect(65, 65, 120, 80).attr({ "fill": "#17A9C6", //filling with background color "stroke": "#2A6570", // border color of the rectangle "stroke-width": 2 // the width of the border }); var rect1 = paper.rect(190, 65, 120, 80,20).attr({ "fill": "#17A9C6", //filling with background color "stroke": "#2A6570", // border color of the rectangle "stroke-width": 2 // the width of the border }); </script> </body> </html>
效果如下:
 
paper.ellipse(X,Y,rX,rY);
var ellipse = paper.ellipse(195,125,170,100).attr({
"fill":"#17A9C6", // background color of the ellipse
"stroke":"#2A6570", // ellipse's border color 
"stroke-width":2 // border width
});
Paper.path([pathString])
- pathString SVG格式的路徑字符串。
 
路徑字符串由一個或多個命令組成。每個命令以一個字母開始,隨后是逗號(“,”)分隔的參數。例如:"M10,20L30,40"
我們看到兩個命令:“M”與參數(10, 20)和“L”與參數(30, 40)大寫字母的意思是命令是絕對的,小寫是相對的。
這里是可用命令的簡表,詳細內容請參照:SVG路徑字符串格式 。
| 命令 | 名稱 | 參數 | 
|---|---|---|
| M | 移動到(moveTo) | (x y)+ | 
| Z | 閉合路徑(closepath) | (none) | 
| L | 直線(lineTo) | (x y)+ | 
| H | 水平直線 | x+ | 
| V | 垂直直線 | y+ | 
| C | 曲線(curveto) | (x1 y1 x2 y2 x y)+ | 
| S | 平滑曲線 | (x2 y2 x y)+ | 
| Q | 二次貝賽爾曲線 | (x1 y1 x y)+ | 
| T | 平滑二次貝塞爾曲線 | (x y)+ | 
| A | 橢圓弧 | (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ | 
| R | Catmull-Rom 曲線* | x1 y1 (x y)+ | 
* “Catmull-Rom 曲線”不是標准SVG命令,在2.0版時被加入。 注:有種特殊情況,路徑只包含三個命令:“M10,10R…z”。在這種情況下,路徑將平滑連接到它的起點。
語法如下:
paper.path("pathString");
var tri = paper.path("M0,0L26,0L13,18L0,0").attr({
 "fill":"#17A9C6", // filling the background color 
"stroke":"#2A6570", // the color of the border 
"stroke-width":2 // the size of the border
});
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Raphael Test</title> </head> <body> <div id="my-canvas" style="width:140px;padding:0px;margin:0px;"> </div> <!--some html doms--> <!--some scripts--> <script type="text/javascript" src="../js/lib/raphael.js"> </script> <script type="text/javascript"> var paper = Raphael("my-canvas", 700, 600); //1、直線使用path命令L paper.path("M20,20L100,20z").attr({ "fill": "#5DDEF4", "stroke": "#2A6570", "stroke-width": 2 }); //2、三角形使用Path命令L paper.path("M130,30 L200,30 L160,90 z").attr({ "fill": "#5DDEF4", "stroke": "#2A6570", "stroke-width": 2 }); //3、T形使用Path命令H,V paper.path("M 40,40 H 90 V 60 H 70 V 110 H 60 V 60 H 40 z").attr({ "fill": "#5DDEF4", "stroke": "#2A6570", "stroke-width": 2 }); //4、2次貝塞爾曲線形,使用path命令Q paper.path("M240,40L300,40L300,100"); paper.path("M240,40Q300,40 300,100").attr('stroke', 'red'); //5、2次貝塞爾曲線形,使用path命令Q和T(第一個是正常繪制,第二個光滑連接) paper.path('M10,250 L90,130 L160,160 L250,190 L250,70'); paper.path('M10,250 Q90,130 160,160 T250,70').attr('stroke', 'red'); //6、繪制3次貝賽爾曲線,使用命令C,平滑畫線使用命令S paper.path('M320,120 L350,180 L450,260 L480,140'); paper.path('M320,120 C350,180 450,260 480,140').attr('stroke', 'red'); paper.path('M320,120 S450,260 480,140').attr('stroke', 'yellow'); </script> </body> </html>
代碼里面刪除了上面文字里面的基本圖形的繪制代碼。為了節省空間,這里就使用這些繪制path的代碼。上面代碼中一共6個小模塊,使用了path命令中最后2個之外的其它所有命令。最后兩個待會兒解釋。先解釋上面幾個。代碼運行效果圖如下:
 
paper.path("M20,20L100,20z")
這里,pathString為M20,20L100,20z,我們查看上面的path命令表。發現執行情況是這樣的:我們的筆移動到坐標(20,20)的位置,連一條線到(100,20),閉合path。也就是上面6個圖形中的最左上角的那個線段。
接下來是那個三角形:
 
           paper.path("M130,30 L200,30 L160,90 z")
三角形這個命令和上面線段是一致的,只是多連了一次,構成了一個三角形。這里我們是可以明白,只要你不斷的用L命令去連接,其實可以構成任意復雜的圖形。下面我們繼續講解第三個代碼塊:
paper.path("M 40,40 H 90 V 60 H 70 V 110 H 60 V 60 H 40 z")
這里我們用到了H和V命令,這倆命令我們通過查看path命令表可知道它們分別是橫着和豎着連線。所以剛才上面那行代碼的執行情況是:我們的筆移動到(40,40),水平線連接到x坐標90,垂直線連接到60,水平線······如此反復,需要注意H和V后面跟的不是線的長度而是坐標,最后我們閉合path得到一個T的圖形。這個其實使用上面那個L命令也可以做到,但是水平和垂直命令名對於這種0角度或者90度的線處理起來更加容易。
第四塊代碼如下:
paper.path("M240,40L300,40L300,100"); paper.path("M240,40Q300,40 300,100");
這里我們第一行代碼是畫兩條線段,上面講解到了,只不過這里沒有z結尾來閉合path。第二行代碼使用的坐標與第一個完全一致,只不過兩個L命令換成了Q,我們查看命令表,Q表示二次貝塞爾曲線,效果大家可以看靠上位置的那個曲線和曲線附着的的線段。Q命令的后的坐標含義可以通過上面線段的坐標來得知。
第五個代碼塊如下:
paper.path('M10,250 L90,130 L160,160 L250,190 L250,70'); paper.path('M10,250 Q90,130 160,160 T250,70');
這里的效果圖是上面圖形中最大那個圖形。其實如果理解了第四個圖形,這個很好理解。唯一的不同就是這里使用了T命令,這個T和接下來的S命令很相似,就是分別對應Q和S的平滑曲線畫法,生活他們中間的那個坐標,而直接使用后一(兩)個坐標即可。
第六個代碼塊如下:
paper.path('M320,120 L350,180 L450,260 L480,140'); paper.path('M320,120 C350,180 450,260 480,140').attr('stroke', 'red'); paper.path('M320,120 S450,260 480,140').attr('stroke', 'yellow');
看到最后一幅圖,我們看的到一條紅色曲線和一條黃色,兩個圖形的區別就是命令中缺省第一個坐標的區別。上面第5個圖形也可以做成類似第六幅圖的曲線對比圖,大家可以稍微修改一下代碼就能搞定了。當然這里其實曲線的每個附着的線段是不是必要存在,為了加深理解,我們將它畫了出來。
關於橢圓曲線,這里我直接引用http://lblovesnow-163-com.iteye.com/blog/1485388這個博客博主的測試用例吧。這個博主寫的這些測試用例非常到位,我就借花獻佛了。代碼如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Raphael Test</title> </head> <body> <div id="my-canvas" style="width:140px;padding:0px;margin:0px;"> </div> <!--some html doms--> <!--some scripts--> <script type="text/javascript" src="../js/lib/raphael.js"> </script> <script type="text/javascript"> var paper = Raphael("my-canvas", 700, 600); //繪制左上的橢圓 paper.ellipse(130,40,60,30); paper.ellipse(70,70,60,30); paper.path('M70,40 A60,30 0 0,0 130,70').attr('stroke','yellow'); paper.text(40,30,'start(70,40)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(160,80,'end(130,70)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(70,120,'large-arc-flag=0\nsweep-flag=0') .attr({ 'font-size': 11, 'fill': 'green', 'text-anchor': 'start' }); //繪制右上的橢圓 paper.ellipse(330,40,60,30); paper.ellipse(270,70,60,30); paper.path('M270,40 A60,30 0 0,1 330,70').attr('stroke','yellow'); paper.text(240,30,'start(270,40)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(360,80,'end(330,70)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(270,120,'large-arc-flag=0\nsweep-flag=1') .attr({ 'font-size': 11, 'fill': 'green', 'text-anchor': 'start' }); //繪制左下的橢圓 paper.ellipse(130,240,60,30); paper.ellipse(70,270,60,30); paper.path('M70,240 A60,30 0 1,0 130,270').attr('stroke','yellow'); paper.text(40,230,'start(70,240)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(160,280,'end(130,270)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(70,320,'large-arc-flag=1\nsweep-flag=0') .attr({ 'font-size': 11, 'fill': 'green', 'text-anchor': 'start' }); //繪制右下的橢圓 paper.ellipse(330,240,60,30); paper.ellipse(270,270,60,30); paper.path('M270,240 A60,30 0 1,1 330,270').attr('stroke','yellow'); paper.text(240,230,'start(270,240)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(360,280,'end(330,270)') .attr({ 'font-size':11, 'fill':'blue' }); paper.text(270,320,'large-arc-flag=1\nsweep-flag=1') .attr({ 'font-size': 11, 'fill': 'green', 'text-anchor': 'start' }); </script> </body> </html>
其中有個paper.text方法正好我們解析來要講解的內容,這里也算提前預覽一下。
A(a)elliptical arc(rx ry x-axis-rotation large-arc-flag sweep-flag x y) ;
參數含義:
rx:橫軸的長度;
ry:縱軸的長度;
x-axis-rotation:橢圓的橫軸與x軸的角度;
large-arc-flag:區分弧度的大小(0表示小角度弧度,1表示大角度弧度);
sweep-flag:繪制弧度圍繞橢圓中心的方向(0表示逆時針方向,1表示順時針方向);
x y:橢圓曲線終點坐標;
效果圖如下:
 
圖畫上面有個A命令的參數含義,其實加上這位博主的參數含義的解釋還是很好理解的。注意圖中的黃色曲線,每個下面有2個參數的解釋,忽略4組圖形的開始和結束坐標,其實他們的區別就是在larget-arc-flag和sweep-flag的參數設置不同。
large-arc-flag:區分弧度的大小(0表示小角度弧度,1表示大角度弧度);
sweep-flag:繪制弧度圍繞橢圓中心的方向(0表示逆時針方向,1表示順時針方向);
是不是一目了然?larget-arc-flag就是畫小弧還是大弧的區別、sweep-flag是逆時針還是順時針。
“Catmull-Rom 曲線”不是SVG標准命令,這里不再贅述,有興趣的可以自己去研究測試一下。
接下來我們講解的方法是text方法。上例中出現了paper.text(),是用來顯示文字內容的方法。語法其實很簡單,就是x,y坐標和文字內容。
paper.text(X,Y,"Raphael JS Text");
var text = paper.text(40,55,"Raphael Text").attr({
"fill":"#17A9C6", // font-color
"font-size":75, // font size in pixels
"text-anchor":"start",
"font-family":"century gothic" // font family of the text
});
//text-anchor屬性表明文字與坐標的關系,是從這個坐標開始、為中心還是為結尾。屬性值可以設置 "start", "middle" or "end" 默認"middle"。
到此位置,我們已經講解了創建畫布、創建基本圖形、創建復雜圖形、text文本內容等方法。到現在位置其實我們都是在做靜態圖畫的編輯,我們如果想要操作和添加事件,需要學習接下來的知識。接下來的內容將在下一篇博文中講述。
