Raphaël.js学习笔记

时间:2022-05-09 10:03:50

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

http://raphaeljs.com/

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); // 画椭圆
}

可以看到如下图像:

Raphaël.js学习笔记

绘制路径

任何路径都是从画布的原点开始绘制的。

Raphaël.js学习笔记

路径字符串

用字符串表示一连串命令。

例:移动光标至(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");
}

效果如下:

Raphaël.js学习笔记

通过路径字符串可以绘制非常复杂的图形。甚至是非常复杂的地图。

Raphaël.js学习笔记Raphaël.js学习笔记

使用路径字符串可以绘制不同类型的曲线:

命令 名称 参数
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});
}

显示如图:

Raphaël.js学习笔记

例:对以上例子的加工。

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
}
);
};

显示如图:

Raphaël.js学习笔记

动画

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.toFront()    使元素置顶。

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/