Raphaël.js学习笔记
Rapheal.js 是一个矢量图绘图库。对于支持HTML5 SVG的浏览器使用SVG绘图,不支持SVG的IE(ie6,7,8)使用VML绘图。所以Raphael.js的兼容性非常好。
Raphael.js的作者是前端大师Dmitry Baranovskiy。目前Raphael.js是ExtJS图表功能的基本绘图库,所以代码质量与维护性也会比较有保证。
Raphael.js本身的拼写是Raphaël.js,这里为了方便,所以写作Raphael.js。
下载Raphael.js
Raphael.js开源遵循MIT协议。
下载后,创建一个简单的HTML文件,引入Raphael.js。
<html> <head> <script type="text/javascript" src="Raphael.js"></script> <style type="text/css"> #canvas_container {border: 1px solid black;} </style> </head> <body> <div id="canvas_container"></div> </body> </html>
画布
创建Rapheal对象,即画布对象。所有绘图方法都绑定在画布对象中。
两种方式:
var paper = new Raphael(x, y, width, height); // 画布绝对定位。同时指定宽高。 var paper = new Raphael(element, width, height); // 在一个元素内画图。
参数x, y, width, height,都是paper对象的大小,与div无关。
例:在canvas_container中创建画布。
window.onload = function() { var paper = new Raphael(document.getElementById('canvas_container'), 500, 500); }
说明:
绘图用的div包含paper,可以把paper看作一种block元素。div的大小与paper的大小没有绝对关系。
在画布中绘图
计算机绘画需要建立坐标系。绘图原点(0,0),是画布的左上角。所有点坐标(x,y)都是相对于此点(0,0)。
raphael的内置绘图API如下,参数均容易理解,不作解释:
Paper.circle(x, y, r)
Paper.ellipse(x, y, rx, ry)
Paper.rect(x, y, width, height, [r])
Paper.path([pathString])
Paper.image(src, x, y, width, height)
Paper.text(x, y, text)
Raphael的内置图形
圆
例:画一个圆,圆心(100,100),半径80。
window.onload = function() { var paper = new Raphael(document.getElementById('canvas_container'), 500, 500); var circle = paper.circle(100, 100, 80); }
例:画5个圆。
for(var i = 0; i < 5; i+=1) { var multiplier = i*5; paper.circle(250 + (2*multiplier), 100 + multiplier, 50 - multiplier); }
矩形
使用rect()方法,参数为,矩形左上角坐标和矩形的宽高。
var rectangle = paper.rect(200, 200, 250, 100);
椭圆
参数与圆类似。
例:椭圆中心位于200,400,x-radius = 100, y-radius = 50
var ellipse = paper.ellipse(200, 400, 100, 50);
例:综合绘制图形。
window.onload = function() { var paper = new Raphael(document.getElementById('canvas_container'), 500, 500); // 定义画布 var circle = paper.circle(100, 100, 80); // 画圆 for(var i = 0; i < 5; i+=1) { // 画5个同心圆 var multiplier = i*5; paper.circle(250 + (2*multiplier), 100 + multiplier, 50 - multiplier) } var rectangle = paper.rect(200, 200, 250, 100); // 画矩形 var ellipse = paper.ellipse(200, 400, 100, 50); // 画椭圆 }
可以看到如下图像:
绘制路径
任何路径都是从画布的原点开始绘制的。
路径字符串
用字符串表示一连串命令。
例:移动光标至(250,250)。
"M 250 250"
M表示,需要从 0,0 移动到x,y 。不会留下轨迹线。
画线使用小写"L"命令,"l" 。
"M 250 250 l 0 -50"
0 -50 表示沿y轴反方向话50px长的线。
"M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z"
z命令表示,封闭路径。该命令使线条与开始点连接起来。
绘制线条
使用Raphael 对象 path() 方法绘制。
window.onload = function() { var paper = new Raphael(document.getElementById('canvas_container'), 500, 500); var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z"); }
效果如下:
通过路径字符串可以绘制非常复杂的图形。甚至是非常复杂的地图。
使用路径字符串可以绘制不同类型的曲线:
命令 | 名称 | 参数 |
---|---|---|
M | moveto 移动到 | (x y)+ |
Z | closepath 封闭路径 | (none) |
L | lineto 直线 | (x y)+ |
H | horizontal lineto 水平线 | x+ |
V | vertical lineto 垂直线 | y+ |
C | curveto 曲线 | (x1 y1 x2 y2 x y)+ |
S | smooth curveto 平滑曲线 | (x2 y2 x y)+ |
Q | quadratic Bézier curveto 二次贝塞尔曲线 | (x1 y1 x y)+ |
T | smooth quadratic Bézier curveto 二次贝塞尔平滑曲线 | (x y)+ |
A | elliptical arc 椭圆弧 | (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ |
R | Catmull-Rom curveto* | x1 y1 (x y)+ |
属性样式
通过图形对象的属性,可以设定图形对象的基本样式。使用attr()方法设置对象属性参数。
Element.attr(…)
该方法的使用与jQuery的attr方法类似
e.attr("fill") 返回元素的fill属性。
e.attr("fill","#ff00ff") 设置元素的fill属性。
e.attr({fill:"#ff00ff",fill-opacity,0.3}) 设置一组元素的属性。
e.attr(["fill","fill-opacity"]) 返回指定属性名的当前值组成的数组。
属性说明:
arrow-end string 路径的末尾显示箭头。字符串格式是<type>[-<width>[-<length>]]。可能的类型:classic、block、open、oval、diamond、none,宽:wide、narrow、midium,长:long 、short、midium。 clip-rect string 剪贴矩形。逗号或空格分隔的值:x,y,宽度和高度 cursor string 光标的CSS类型 cx number 圆或椭圆的圆心的x轴坐标 cy number 圆或椭圆的圆心的y轴坐标 fill string 填充。颜色、渐变或图像 fill-opacity number 填充不透明度 font string 文本特性 font-family string 字体 font-size number 字体大小(像素) font-weight string 字体粗细 height number 高度 href string URL。指定时,元素表现为超链接 opacity number 透明度。范围是[0,1],0为完全透明,1为完全不透明。 path string SVG的路径字符串格式 r number 圆、椭圆或圆角矩形的半径 rx number 椭圆的横向半径 rynumber椭圆的垂直半径 sr cstring 图像的URL,只适用于Element.image元素 stroke string 笔触颜色 stroke-dasharray string [“”, “-”, “.”, “-.”, “-..”, “.”, “- ”, “--”, “- .”, “--.”, “--..”] stroke-linecap string [“butt”, “square”, “round”] stroke-linejoin string [“bevel”, “round”, “miter”] stroke-miterlimit number stroke-opacity number stroke-width number 笔触宽度(像素,默认为1) target string 与 href 一起使用 text string 文本元素的内容。使用\n换行 text-anchor string [“start”, “middle”, “end”],默认为 “middle” title string 工具提示内容 transform string 请参照:Element.transform width number x number y number
例:attr()方法可以对于path()方法是一个链式方法。
window.onload = function(){ var paper = new Raphael(document.getElementById('canvas_container'), 500, 500); var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z"); tetronimo.attr({fill: '#9cf', stroke: '#ddd', 'stroke-width': 5}); }
显示如图:
例:对以上例子的加工。
window.onload = function() { var paper = new Raphael(document.getElementById('canvas_container'), 500, 500); var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z"); tetronimo.attr( { gradient: '90-#526c7a-#64a0c1', stroke: '#3b4449', 'stroke-width': 10, 'stroke-linejoin': 'round', rotation: -90 } ); };
显示如图:
动画
Raphael使用animate()方法,产生动画效果。该方法非常好用,jQuery的动画函数类似。
Raphael.animation(params, ms, [easing], [callback])
创建一个动画对象可以传递给Element.animate或Element.animateWith方法。请参照:Animation.delay和Animation.repeat。
参数
- params object 元素的最终属性,请参照:Element.attr
- ms number 动画持续的时间,单位毫秒ms
- easing string 缓动类型。接受Raphael.easing_formulas其中之一,或CSS格式: cubic-bezier(XX, XX, XX, XX)
- callback function 回调函数。动画结束时将被调用。
说明:对于同一个对象设置多个动画方法。几个不同动画动作是同时发生的。弱需要控制动画的先后顺序,可以使用animate()的回调方法,在回调方法中设置第二个动画动作。
animation方法返回动画对象。
Animation.delay(delay)
创建现有的动画对象的副本,并且可以指定延迟时间。
参数
- delay number 动画延迟执行的时间,单位:毫秒ms。
例:
var anim = Raphael.animation({cx: 10, cy: 20}, 2e3); circle1.animate(anim); // 立即执行 circle2.animate(anim.delay(500)); // 0.5秒之后再执行
Animation.repeat(repeat)
创建现有动画对象的副本,并指定重复频率。
参数
- repeat number 动画迭代次数。如果传入 0,表示动画会一直执行。
元素的动画同步方法
Element.animateWith(…)
作用与 Element.animate 类似,但保证动画与另一元素的同步执行。
参数
- el object 要同步的元素
- anim object 要同步的动画
- params object 元素的最终属性,请参照:Element.attr
- ms number 动画持续的时间,单位毫秒ms
- easing string 缓动类型。接受Raphael.easing_formulas或CSS格式: cubic‐bezier(XX, XX, XX, XX)
- callback function 回调函数。动画结束时将被调用。
或
- element object 要同步的元素
- anim object 要同步的动画
- animation object 动画对象,请参照:Raphael.animation
例:旋转360度。动画将持续2s,之后回复原有状态。
window.onload = function() { var paper = new Raphael(document.getElementById('canvas_container'), 500, 500); var tetronimo = paper.path("M 250 250 l 0 -50 l -50 0 l 0 -50 l -50 0 l 0 50 l -50 0 l 0 50 z"); tetronimo.attr( { gradient: '90-#526c7a-#64a0c1', stroke: '#3b4449', 'stroke-width': 10, 'stroke-linejoin': 'round', rotation: -90 } ); tetronimo.animate({rotation: 360}, 2000, 'bounce'); }
例:使用回调方法。在第一个动画完成后,回调方法执行第二个动画。
tetronimo.animate({rotation: 360, 'stroke-width': 1}, 2000, 'bounce', function() { this.animate({ rotation: -90, stroke: '#3b4449', 'stroke-width': 10 }, 1000); } );
图形元素的属性
Element.id 元素的唯一的ID。当你要监听元素的事件时尤其有用。因为所有的事件被以下面的格式触发:<module>.<action>.<id> 。对Paper.getById方法也有用。
Element.matrix 矩阵对象,它代表元素的变换
Element.next 层次结构中的下一个元素的引用。
Element.node DOM对象的引用。
Element.paper 绘制对象的"画布"的内部引用。主要用于插件和元素扩展。
用法:
Raphael.el.cross = function () { this.attr({fill: "red"}); this.paper.path("M10,10L50,50M50,10L10,50").attr({stroke: "red"}); }
Element.prev 层次结构中前一个元素的引用。
Paper.bottom 指向画布上的底层元素
Element.raphael Raphael对象的内部引用。即使它目前不可用。
使用
Raphael.el.red = function () { var hsb = this.paper.raphael.rgb2hsb(this.attr("fill")); hsb.h = 1; this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex}); }
Paper.ca Paper.customAttributes的引用
Paper.customAttributes 可以添加自定义属性来方便设置一批属性:
使用:自定义属性
// 自定义属性 "hue" 会改变填充。得到固定的色相与饱和度和亮度。 paper.customAttributes.hue = function (num) { num = num % 1; return {fill: "hsb(" + num + ", 0.75, 1)"}; }; // 使用自定义属性: var c = paper.circle(10, 10, 10).attr({hue: .45}); c.animate({hue: 1}, 1e3); // 创建自定义属性,也可以多个参数。 paper.customAttributes.hsb = function (h, s, b) { return {fill: "hsb(" + [h, s, b].join(",") + ")"}; }; c.attr({hsb: "0.5 .8 1"}); c.animate({hsb: [1, 0, 0.5]}, 1e3);
事件处理
Element.click(handler) 为元素添加click事件的处理程序。
Element.dblclick(handler) 为元素添加dblclick事件的处理程序。
Element.mousedown(handler) 为元素添加mousedown事件的处理程序。
Element.mousemove(handler) 为元素添加mousemove事件的处理程序。
Element.mouseout(handler) 为元素添加mouseout的事件的处理程序。
Element.mouseover(handler) 为元素添加mouseover事件的处理程序。
Element.mouseup(handler) 为元素添加mouseup事件的处理程序。
Element.drag(onmove, onstart, onend, [mcontext], [scontext], [econtext]) 为元素添加drag事件的处理程序。
参数
-
- onmove 移动处理函数
- onstart 拖拽开始的处理函数
- onend 拖拽结束处理函数
- mcontext 移动处理函数环境(上下文)
- scontext 拖拽开始处理函数环境
- econtext 拖拽结束处理函数环境
下面额外的drag事件会被触发:开始时drag.start.<id>;结束时drag.end.<id>;每次移动时drag.move.<id>。当元素被拖入了另一个元素drag.over.<id>将被触发。
拖拽开始事件和拖拽开始处理函数将在指定的环境内调用,或在包含以下元素的环境内调用:
-
- x:鼠标的x轴位置
- y:鼠标的y轴位置
- event:DOM事件对象
移动事件和移动处理函数将在指定的环境内调用,或在包含以下元素的环境内调用:
-
- dx:相对起始点的x位移
- dy:相对起始点的y位移
- x:鼠标的x轴位置
- y:鼠标的y轴位置
- event:DOM事件对象
拖拽结束事件和拖拽结束处理函数将在指定的环境内调用,或在包含以下元素的环境内调用:
-
- event:DOM事件对象
Element.hover(f_in, f_out, [icontext], [ocontext]) 为元素增加hover事件的处理程序。
参数
-
- f_in 悬停进入处理句柄
- f_out 悬停离开处理句柄
- icontext 悬停进入处理句柄环境
- ocontext 悬停离开处理句柄环境
点击事件示例
例:一个可点击的rect。必须为rect填充,否则点击事件无法被响应。
<html> <head> <script type="text/javascript" src="raphael.js"></script> <style type="text/css"> #canvas_container {border: 1px solid black;} </style> <script type="text/javascript"> window.onload = function(){ var canvas = document.getElementById("canvas_container"); var paper = new Raphael(canvas, 500, 500); var rect = paper.rect(50,50,150,100); rect.attr("fill","blue"); rect.click(function(){ window.console.log("click"); }) } </script> </head> <body> <div id="canvas_container"></div> </body> </html>
拖动事件示例
例:一个可拖动的rect。
<html> <head> <script type="text/javascript" src="raphael.js"></script> <style type="text/css"> #canvas_container {border: 1px solid black;} </style> <script type="text/javascript"> window.onload = function(){ var canvas = document.getElementById("canvas_container"); var paper = new Raphael(canvas, 500, 500); var rect = paper.rect(50,50,150,100); rect.attr("fill","blue"); rect.x0 = 0; //自定义额外属性x0 rect.y0 = 0; //自定义额外属性y0 rect.drag( function(dx,dy){ this.attr({x: this.x0 + dx, y: this.y0 + dy}); }, function(){ var box = this.getBBox(); this.x0 = box.x; this.y0 = box.y; }, function(){} ); } </script> </head> <body> <div id="canvas_container"></div> </body> </html>
访问DOM
使用元素的node属性,获取图形对象所对应的DOM对象。
Element.node DOM对象的引用。
可以通过DOM对象对元素添加事件处理,或样式设置。
例:在画布上,画一个圆,圆心坐标为:X:10 , Y:10 ,半径:10,并绑定点击事件。
var c = paper.circle(10, 10, 10); c.node.onclick = function () { c.attr("fill", "red"); };
一些常用方法
Element.hide() 隐藏指定元素。
Element.show() 使元素可见。
Element.toBack() 使元素后置。
Element.transform([tstr]) 为元素增加变换,这是独立于其他属性的变换,即变换不改变矩形的x或y。
变换字符串跟路径字符串的语法类似: "t100,100r30,100,100s2,2,100,100r45s1.5"
每个字母是一个命令。有四个命令:t是平移,r是旋转,s是缩放,m是矩阵。
也有另类的"绝对"平移、旋转和缩放:T、R和S。他们不会考虑到以前的变换。例如:...T100,0总会横向移动元素100px,而...t100,0会移动垂直移动如果之前有r90。比较以下r90t100,0和r90T100,0的结果。
所以,上面的例子可以读作"平移100,100;围绕100,100旋转30°;围绕100,100缩放两倍;围绕中心旋转45°;相对中心缩放1.5倍"。正如你可以看到旋转和缩放命令的原点坐标为可选参数,默认的是该元素的中心点。
矩阵接受六个参数。
例:
var el = paper.rect(10, 20, 300, 200); // 转换 100, 100, 旋转 45°, 转换 -100, 0 el.transform("t100,100r45t-100,0"); // 可以追加,或者预先转换 el.transform("...t50,50"); el.transform("s2..."); // 或者包裹 el.transform("t50,50...t-50-50"); // 重置转换 el.transform(""); // 获取不带参数的当前值 console.log(el.transform());
这里只是总结了一些基本概念与部分函数的使用,更多Raphael.js的API请参考:
http://raphaeljs.com/reference.html
http://lab.julying.com/raphael-js/docs/