前端绘图用的最多的就是svg和canvas,现在有许多基于这两种技术的图形框架,比如基于svg的D3 和基于canvas的echarts 。今天要讲的是基于svg的Raphael Javascript ,它是一个 Javascript的矢量库。
首先你要在HTML中引入RaphaelJS
然后你就可以在js中使用这个包了
我是先建了一个名为master.js的文件,在这个文件中写js,注意两个文件的放置顺序,由于要在master.js中使用RaphaelJS,所以raphael.js的引用要放在前面
创建画布
1.以坐标点定义画布位置
var paper = Raphael(20, 30, 650, 400); 分别为横坐标,纵坐标,宽度,高度
2.以节点定义画布位置
var width = 600;
var height = 200;
var paper = Raphael("mySvg",width,height); //定义svg绘图节点,及宽度,高度
封装绘图函数
1.画矩形
function drawRect(x,y,w,h,radius){
var rect = paper.rect(x,y,w,h); //若绘圆角矩形加上圆角参数(横坐标,纵坐标,宽,高,圆角)
rect.attr({
"fill": "red", //填充颜色
"stroke": "lime", //边框颜色
"stroke-width": 2 // 边框宽度
});
}
2.画圆
function drawCircle(x,y,r){
var cir = paper.circle(x,y,r); //(圆心横坐标,圆心纵坐标,半径)
cir.attr({
"fill": "blue",
"stroke": "lime",
"stroke-width": 2
})
}
3.画椭圆
function drawEllipse(x,y,rx,ry){ //水平半径和垂直半径其实就是椭圆的rx和ry
var ellipse = paper.ellipse(x,y,rx,ry);
ellipse.attr({
"fill": "yellow",
"stroke": "lime",
"stroke-width": 2
})
}
4.画上五边形
function drawDownFive(x,y,w,h){ // 传起点坐标,宽和高
// 若要使边框完整,从起始坐标到起始坐标,仅填充的话不需在后面加起始坐标或加闭合路径
// var DownFive = paper.path('M'+x+','+y+'H'+(w+x)+'V'+(h+y)+'L'+(w/2+x)+','+(h+h/2+y)
// +'L'+x+','+(y+h)+'L'+x+','+y);
// var DownFive = paper.path('M'+x+','+y+'H'+(w+x)+'V'+(h+y)+'L'+(w/2+x)+','+(h+h/2+y)
// +'L'+x+','+(y+h)+'Z');
var DownFive = paper.path('m'+x+','+y+'h'+w+'v'+h+'l'+(-w/2)+','+(h/2)+'l'+(-w/2)+','+(-h/2)+'Z');//相对坐标
DownFive.attr({
"fill": 'orangered',
"stroke": 'lime',
"stroke-width": 2
});
}
5.添加文字
function drawText(x,y,txt){ // 横坐标+纵坐标+文本
var tip = paper.text(x,y,txt);
tip.attr({
"font-size": 16, //字体大小
"fill": 'brown', //字体颜色
"text-anchor":"middle", // 字体对齐样式
});
}
drawText(200,140,"椭圆弧的使用");
Raphael元素的变换
// T 平移
// S 缩放 Sx,y 横向缩放x倍,纵向缩放y倍
// R 按角度旋转
// M 变换矩阵
// 每个字母是一个命令 t是平移,r是旋转,s是缩放,m是矩阵
// 也有另类的“绝对”平移、旋转和缩放:T、R和S。他们不会考虑到以前的变换
var rect1 = paper.rect(20,300,100,50);
rect1.attr({
"transform": 'r90T100,0s0.5'
});
Raphael图形的动画效果
// 语法如下:Element.animate({动画属性的键值对},动画时间,缓动类型,回调函数);
// 缓动类型其实就是动画过渡公式,是哪种类型的。主要有以下这些类型:
// “linear”(线性)
// “<”或“easeIn”或“ease-in” (由慢到快)
// “>”或“easeOut”或“ease-out”(又快到慢)
// “<>”或“easeInOut”或“ease-in-out”(由慢到快再到慢)
// “backIn”或“back-in”(开始时回弹)
// “backOut”或“back-out”(结束时回弹)
// “elastic”(橡皮筋)
// “bounce”(弹跳)
rect1.animate({transform: "r90t100,0s1.5"}, 1000,"bounce",function(){console.log("finish");});
事件绑定
var rect2 = paper.rect(60,300,100,50,10);
rect2.attr('fill', 'blue');
rect2.mouseover(function() { //绑定鼠标悬浮事件,其他事件类似
rect2.attr({
"transform": 'T0,50s2',
"fill": '#000'
});
});
rect2.mouseout(function() {
rect2.attr({
"fill": 'blue',
"transform": 'T0,0s1'
});
});
clone() 复制一个
var rect3 = rect2.clone().attr({
"x": 400,
"y": 400
});
画布的方法
// 画布的方法
// paper.clear(); // paper.clear()方法清空画布
// 加载图片 paper.image()
// 参数 说明
// src 图片的路径,对经常写前台的童鞋们来说这个小菜一碟
// X 图片摆放位置的x坐标
// Y 图片摆放位置的y坐标
// width 图片的宽度
// height 图片的高度
// 例:paper.image("images/testimage.png",10,10,200,150);将在画布的(10,10)位置摆放一个宽200,长150的图片。
// paper.setSize()用来重新设置画布的大小。你以在发现画布大小不合适时调整画布的大小
// 而不是需要从头建立画布然后重复原来的工作。方法有2个参数:宽和高
paper.setSize(1000,1000);// 我们将画布的大小修改为宽100px,1000px。
// paper.set()方法是个很重要的方法。它帮助我们对Raphael元素进行分组然后进行批量管理
var rect4 = paper.rect(300,600,100,50,10);
var circle1 = paper.circle(400,680,50);
var set = paper.set();
set.push(circle1,rect4);
// set.clear();
// set.exclude(circle1);
// set.attr('fill', 'green');
// 我们想要清空set,可不要用remove()而是用clear(),remove()会把所有set里面的元素remove掉。
// clear()只是清除set里的内容,并不会对里面的内容本身有影响
// set.exclude(rect);还记得我前面的代码里面将rect添加进入raphaelSet里面吗?
// 现在你可以试一试在在执行raphaelSet.attr()之前使用raphaelSet.exclude(rect);
// 试一试。效果和我们想象的一样,第一个矩形没有被填充红色,因为它被从set里面剔除出来了。
// set.forEach()就是去循环我们创建的set对象,然后通过遍历对set内的元素进行操作。
// 这个功能是差不多算是set里面最重要的方法了,我们使用set大部分业务都需要这个循环了
set.forEach(function(ele){
ele.attr({"fill":"red"});
});
// set.pop(); 清除最后一个添加进去的元素
// set.splice()方法 它有3个参数index,count,element set.splice(1,2,rect),
// 我从set里面index为1的位置开始往后删除2个元素,然后把rect添加进来。所以slice可以同时删除和添加元素
透明度
// 元素透明度键名opacity,取值范围为0(完全不透明)到1(完全透明),也可以分别设置stroke-opacity和fill-opacity
var circle2 = paper.circle(600,680,50);
circle2.attr({
"fill": 'blue',
"stroke": 'lime',
"stroke-width":5,
"fill-opacity":0.5
});
// Raphael支持通过clip-rect属性来进行元素的矩形切割,它允许我们将图形切割出一部分下来
circle2.attr('clip-rect', '545,625,50,50');
Raphael支持线性和梯度渐变去填充图形,要达到这个效果,而不是直接用一个颜色的字符串去设置fill属性。
我们需要指定了下面这种字符串的格式去做到线性渐变:
<angle>-<color>[-<color>[:<offset>]]-<color>
下面的语法就是达到径向渐变的效果:
r[(<fx>,<fy>)]<color>[-<color>[:<offset>]]-<color>
1.线性渐变 <angle>-<color1>-<color2>
var rect5 = paper.rect(760,600,100,80);
rect5.attr('fill', '0-red-blue');
rect5.attr('fill', '45-red-yellow');
2.径向渐变 r<color>-<color>
var circle3 = paper.circle(940,650,50);
circle3.attr('fill', 'rblack-white-black');
circle3.attr('fill', 'rblack-white:80-black'); //以半径的80%处为第二阶段的渐变分割点
3.偏离圆心的渐变
var circle4 = paper.circle(70,900,50);
var circle5 = paper.circle(200,900,50);
var circle6 = paper.circle(330,900,50);
var circle7 = paper.circle(460,900,50);
var circle8 = paper.circle(590,900,50);
circle4.attr('fill', 'r(0.1,0.5)#fff-#000'); //r(0.5,o.5)是正圆心
circle5.attr('fill', 'r(0.5,0.1)#fff-#000');
circle6.attr('fill', 'r(0.9,0.5)#fff-#000');
circle7.attr('fill', 'r(0.5,0.9)#fff-#000');
circle8.attr('fill', 'r(0.5,0.5)#c8c8c8-#000');
给线条加箭头
路径的末尾显示箭头。字符串格式是<type>[-<width>[-<length>]]。
可能的类型:classic、block、open、oval、diamond、none
宽:wide、narrow、midium,长:long 、short、midium。
var arrow = paper.path("M20,960L120,960").attr('stroke', 'lime'); //绘一条直线
arrow.attr({
"arrow-end":'classic-wide-midium', //加箭头属性
"stroke-width":3
});
线条虚化
stroke-dasharray string [“”, “-”, “.”, “-.”, “-..”, “.”, “- ”, “--”, “- .”, “--.”, “--..”]
var dottedLine = paper.path("M200,960,L300,960");
dottedLine.attr({
"stroke": 'blue', //先给个颜色
"stroke-dasharray": '-.'
});
线段端点处理
stroke-linecap string [“butt”, “square”, “round”]
var lineCap = paper.path("M320,960L420,960");
lineCap.attr({
"stroke": 'red',
"stroke-linecap": 'butt',
"stroke-width": 10
});
stroke-linejoin 属性指明路径的转角处使用的形状或者绘制的基础形状。
stroke-linejoin string [“bevel”, “round”, “miter”]
var linejoin = paper.path("M440,960L500,960L500,1000");
linejoin.attr({
"stroke": 'orangered',
"stroke-linejoin": 'bevel',
"stroke-width": 5
});