Canvas入门到高级详解(下)
四、 Canvas 开发库封装
4.1 封装常用的绘制函数
4.1.1 封装一个矩形
//思考:我们用到的矩形需要哪些绘制的东西呢?
- 矩形的 x、y坐标
- 矩形的宽高
- 矩形的边框的线条样式、线条宽度
- 矩形填充的样式
- 矩形的旋转角度
- 矩形的缩小放大
//下面是把上面所有的功能进行封装的代码:
function ItcastRect( option ) {//矩形构造函数
this._init(option);
}
ItcastRect.prototype = { //矩形的原型对象
_init: function( option ) { //初始化方法
option = option || {};
this.x = option.x === 0 ? 0 : option.x || 100;
this.y = option.y === 0 ? 0 : option.y || 100;
this.w = option.w || 100;
this.h = option.h || 100;
this.angle = option.angle === 0 ? 0 : option.angle || 0;
this.fillStyle = option.fillStyle || 'silver';
this.strokeStyle = option.strokeStyle || 'red';
this.strokeWidth = option.strokeWidth || 4;
this.scaleX = option.scaleX || 1;
this.scaleY = option.Y || 1;
},
render: function( ctx ) {//把矩形渲染到canvas中
ctx.save();
ctx.translate( this.x, this.y );//位移画布
ctx.rotate( this.angle * Math.PI / 180 );//旋转角度
ctx.scale( this.scaleX, this.scaleY );//缩放
ctx.fillStyle = this.fillStyle;
ctx.fillRect( 0, 0, this.w, this.h ); //填充矩形
ctx.lineWidth = this.strokeWidth; //线宽
ctx.strokeStyle = this.strokeStyle; //填充样式
ctx.strokeRect( 0,0,this.w,this.h ); //描边样式
ctx.restore();
},
constructor: ItcastRect
};
- 4.1.2 作业:尝试着封装一个圆形?
//封装圆形的代码的答案:不要偷看
function ItcastCircle(option) {
this._init(option);
}
ItcastCircle.prototype = {
_init: function(option) {
option = option || {};
this.x = option.x === 0 ? 0 : option.x || 100;
this.y = option.y === 0 ? 0 : option.y || 100;
this.w = option.w || 100;
this.h = option.h || 100;
this.angle = option.angle === 0 ? 0 : option.angle || 0;
this.fillStyle = option.fillStyle || 'silver';
this.strokeStyle = option.strokeStyle || 'red';
this.strokeWidth = option.strokeWidth || 4;
this.scaleX = option.scaleX || 1;
this.scaleY = option.Y || 1;
this.opactity = option.opactity || 1;
this.counterclockwise =
option.counterclockwise === true
? true
: option.counterclockwise || false;
this.startAngle = option.startAngle == 0 ? 0 : option.startAngle || 0;
this.endAngle = option.endAngle == 0 ? 0 : option.endAngle || 0;
this.startAngle = (this.startAngle * Math.PI) / 180;
this.endAngle = (this.endAngle * Math.PI) / 180;
this.r = option.r || 100;
},
render: function(ctx) {
ctx.save();
ctx.translate(this.x, this.y);
ctx.scale(this.scaleX, this.scaleY);
ctx.rotate((this.agnle * Math.PI) / 180);
ctx.globalAlpha = this.opacity;
ctx.fillStyle = this.fillStyle;
ctx.strokeStyle = this.strokeStyle;
ctx.moveTo(0, 0);
ctx.arc(
0,
0,
this.r,
this.startAngle,
this.endAngle,
this.counterclockwise
);
ctx.fill();
ctx.stroke();
ctx.restore();
},
constructor: ItcastCircle
};
4.2 第三方库使用
- Rgraph vs 百度的 echart
https://roopons.com.au/wp-content/plugins/viral-optins/js/rgraph/
- 国产的 egret 引擎
http://www.egret-labs.org/
- 比较火的 3d 引擎:treejs
http://threejs.org/
- Konva
官网:http://konvajs.github.io/
特点:
* 小巧、使用方便、适合移动端和pc端
* 支持丰富的事件处理操作
* 支持类似JQuery的操作方式(顺带能复习jQueyr)
* 开源,可以随意更改
* 社区更新比较活跃,github托管源码
* 性能也不错
- 其他的还有很多,希望以后能用到你们的库。
五、Konva 的使用快速上手
5.1 Konva 的整体理念
- 舞台的概念的引入。整个视图看做是一个舞台 stage
- 舞台中可以绘制很多个层 layer
- layer 下面可以有很多的 group
- group 下面可以有 矩形、图片、其他形状等
- 参看:快速上手文档---查看翻译文档
Stage
|
+------+------+
| |
Layer Layer
| |
+-----+-----+ Shape
| |
Group Group
| |
+ +---+---+
| | |
Shape Group Shape
|
+
|
Shape
5.2 Konva 矩形案例
5.2.1 创建一个矩形: Konva.Rect(option);
//Konva使用的基本案例
//第一步:创建舞台
var stage = new Konva.Stage({
container: 'container', //需要存放舞台的Dom容器
width: window.innerWidth, //设置全屏
height: window.innerHeight
});
//第二步:创建层
var layer = new Konva.Layer(); //创建一个层
stage.add(layer); //把层添加到舞台
//第三步: 创建矩形
var rect = new Konva.Rect({ //创建一个矩形
x: 100, //矩形的x坐标,相对其父容器的坐标
y: 100,
width: 100, //矩形的宽度
height: 100, //矩形高度
fill: 'gold', //矩形填充的颜色
stroke: 'navy', //矩形描边的颜色
strokeWidth: 4, //填充宽度
opactity: .2, //矩形的透明度
scale: 1.2, //矩形的缩放 1:原来大小
rotation: 30, //旋转的角度,是deg不是弧度。
cornerRadius: 10, //圆角的大小(像素)
id: 'rect1', //id属性,类似dom的id属性
name: 'rect',
draggable: true //是否可以进行拖拽
});
//创建一个组
var group = new Konva.Group({
x: 40,
y: 40,
});
group.add( rect ); //把矩形添加到组中
//第四步: 把形状放到层中
layer.add( group ); //把组添加到层中
layer.draw(); //绘制层到舞台上
5.3 Konva 的动画系统
5.3.1 tween 对象(重点)
- tween,英文意思:两者之间, 英 [twiːn] 美 [twin]
- tween 是控制 Konva 对象进行动画的核心对象。
- tween 可以控制所有数字类型的属性进行动画处理,比如:x, y, rotation, width, height, radius, strokeWidth, opacity, scaleX 等
//案例:
var tween = new Konva.Tween({
node: rect, //要进行动画的Konva对象
x: 300, //要进行动画的属性
opacity: .8,
duration: 1, //持续时间
easing: Konva.Easings.EaseIn, //动画的动画效果
yoyo: true, //是否进行循环播放的设置
onFinish: function() {
//动画执行结束后,执行此方法
}
});
tween.play(); //启动动画
-
tween 的控制方法
- tween.play(), //播放动画
- tween.pause(), //暂停动画
- tween.reverse(), //动画逆播放
- tween.reset(), //重置动画
- tween.finish(), //立即结束动画
- seek:英文:寻找 英 [siːk] 美 [sik]
-
tween 的缓动控制选项
- Konva.Easings.Linear //线性
- Konva.Easings.EaseIn //缓动,先慢后快
- Konva.Easings.EaseOut //先快后慢
- Konva.Easings.EaseInOut //两头慢,中间快
- Konva.Easings.BackEaseIn //往回来一点,然后往前冲,汽车启动类似...
- Konva.Easings.BackEaseOut
- Konva.Easings.BackEaseInOut
- Konva.Easings.ElasticEaseIn //橡皮筋 英 [ɪ'læstɪk] 美 [ɪ'læstɪk]
- Konva.Easings.ElasticEaseOut
- Konva.Easings.ElasticEaseInOut
- Konva.Easings.BounceEaseIn //弹跳;弹起,反跳;弹回 英 [baʊns] 美 [baʊns]
- Konva.Easings.BounceEaseOut
- Konva.Easings.BounceEaseInOut
- Konva.Easings.StrongEaseIn //强力
- Konva.Easings.StrongEaseOut
- Konva.Easings.StrongEaseInOut
-
动画效果参考: 29Konva 动画缓动效果案例.html
5.3.2 动画 to 的使用
- to 就是对 tween 的封装,比较简单好用。
//案例:
var rect = new Konva.Rect({
x: 10,
y: 10,
width: 100,
height: 100,
fill: 'red'
});
layer.add(rect);
layer.draw();
//动画系统
rect.to({
x: 100,
y: 100,
opactity: .1,
duration: 3,
onFinish: function() {
}
});
//to: 就是对tween的简单应用。
5.3.3 Animate 的应用
- Animation 动画,实际上就是浏览器通知开发者进行绘制,并提供当前的时间
var anim = new Konva.Animation(function(frame) {
//动画系统提供的frame有三个属性可以使用:
var time = frame.time, // 动画执行的总时间
timeDiff = frame.timeDiff, // 距离上一帧的时间
frameRate = frame.frameRate; // 帧率(既1000/间隔时间)
//动画的动作
}, layer);
anim.start();//启动动画
//anim.stop();//结束动画
5.3.4 循环播放动画的实现
//总体思路,使用tween 配合onFinish事件中重新播放动画,达到循环播放的效果
var loopTween = new Konva.Tween({
node: star, //设置要表现动画的 Konva对象
rotation: 360, //旋转360度
duration: 2, //动画持续时间
easing: Konva.Easings.Linear,
onFinish: function() {
// this === loopTween //true
this.reset(); //重置动画
this.play(); //重新播放动画
}
});
loopTween.play();
5.3.5 回放且循环播放动画
- yoyo 属性可以进行对动画进行播放完后,回放当前动画,并持续循环来回切换播放。
rect.to({
duration: 2,
scale: 1.5,
yoyo: true // 此设置也可以用于 tween
});
5.3.6 进度条案例
5.3.7 (谦太祥和)官网案例
- 三角函数的补充
- Math.sin(弧度); //夹角对面的边 和 斜边的比值
- Math.cos(弧度); //夹角侧边 与斜边的比值
- 圆形上面的点的坐标的计算公式
x =x0 + Math.cos(rad) * R;
//x0 和 y0 是圆心点坐标 _y =y0 + Math.sin(rad) * R;
//注意都是弧度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>33Canvas案例-canvas案例</title>
<style type="text/css" media="screen">
body {
padding: 0;
margin: 0;
background-color: #f0f0f0;
overflow: hidden;
}
</style>
<script src="bower_components/konva/konva.min.js"></script>
</head>
<body>
<div id="container">
</div>
<script>
(function(){
//创建舞台
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
//舞台中心,也是旋转的中心
var groupX = stage.width() / 2,
groupY = stage.height() / 2,
L3_Radius = 217,
L2_Radius = 125,
L1_Radius = 90,
L0_Radius = 66;
//背景层
var bgLayer = new Konva.Layer({
hitGraphEnabled : false//don’t need event on layer set
});
//绘制背景圆形 3环
var circle_L3 = new Konva.Circle({
x: groupX,
y: groupY,
radius: L3_Radius,
stroke: '#a0a0a0',
stokeWidth: 2,
opacity: .3,
dash: [10,4]
});
bgLayer.add(circle_L3);
//绘制背景圆形 2环
var circle_L2 = new Konva.Circle({
x: groupX,
y: groupY,
radius: L2_Radius,
stroke: '#2A3466',
stokeWidth: 2,
opacity: .3,
dash: [10,4]
});
bgLayer.add(circle_L2);
//绘制背景中心区域
var cneterCircleText = new CircleText({
text: "WEB全栈",
innerRadius: L0_Radius,
outerRadius: L1_Radius,
fontSize: 17,
fontFamily: '微软雅黑',
fontFill: "#fff",
fontX: -41,
fontY: -8,
x: groupX,
y: groupY,
innerFill: "#2A3466",
outerFill: "#ddd",
opacity: .8
});
var centerGroup = cneterCircleText.createCircleText();
bgLayer.add(centerGroup);
stage.add(bgLayer);
//动画层
var layer = new Konva.Layer({
// hitGraphEnabled : false
});
stage.add(layer);
//创建整体的动画组
var group = new Konva.Group({
x: groupX,
y: groupY,
rotation: 0
});
//要创建的5个3环的对象数据设置
var L3CircleData = [{
text: "WebApp",//创建webapp的圆心组合 1
innerRadius: 40,
outerRadius: 50,
fontSize: 14,
fontFamily: '微软雅黑',
fontFill: "#fff",
fontX: -30,
fontY: -7,
x: L3_Radius,
y: 0,
x: (Math.cos(20 * Math.PI / 180) * L3_Radius),
y: (Math.sin(20 * Math.PI / 180) * L3_Radius),
innerFill: "#CF2782",
outerFill: "#ddd",
opacity: .7
},{
text: "canvas",//动态创建第2个group
innerRadius: 40,
outerRadius: 50,
fontSize: 16 ,
fontFamily: '微软雅黑',
fontFill: "purple",
fontX: -28,
fontY: -7,
x: 0,
y: L3_Radius,
innerFill: "#7CB9CE",
outerFill: "#ddd",
opacity: .7
},{
text: "ReactJS",
innerRadius: 40,
outerRadius: 50,
fontSize: 16 ,
fontFamily: '微软雅黑',
fontFill: "purple",
fontX: -30 ,
fontY: -7,
x: -L3_Radius,
y: 0,
innerFill: "#68AAFC",
outerFill: "#ddd",
opacity: .7
},{
text: "NodeJS",
innerRadius: 40,
outerRadius: 50,