高性能canvas插件 - KineticJs

YUDG 2015-12-17 10:42:03
这几年一直在做一个项目,要用到html的canvas来展示产品。手动调用canvas内部元素和方法是件挺费劲的事情,就想到用一些便捷的方法和工具来快速开发并实现客户的要求。网上搜来搜去,找到了现在使用的html5的一个插件-KineticJs。
KineticJs是一个优秀的canvas插件,它封装了HTML5的canvas元素和方法,可以嵌套、分层、滤镜、缓存、增加部件事件等功能。可以绘制各种图形并且进行缩放、移动等,还可以增加事件的监听。并且可以应用在移动端。
目前插件是5.1版本。很遗憾的一点是它已经停止了维护,放到开源项目github上了。
需要用到这样插件的朋友,有兴趣的话可以来探讨和交流一下这个插件。
KineticJs官网:http://www.kineticjs.com/
Github网站地址“:https://github.com/ericdrowell/KineticJS/

以此文章来介绍一下常用的一些方法、命令、图形、事件等等。

首先下载插件,并且把它加载到页面中。加载方法和加载js文件一样。
<script type="text/javascript" src="kinetic.js" ></script>
我用的是5.1版本。

Stage (舞台/容器)
想要创建kinetic图形或者对象,需要先创建一个舞台(stage),所有对象要放在这个舞台/容器里边。
stage这个容器,是需要通过div来创建的(类似html里边创建一个canvas区域要先创建<canvas />一样)。
创建好div后,我们就可以创建一个stage对象了。初始对象时,需设置舞台容器的id,否则创建不了stage对象。注意,各个对象的id是不可以重复的。
var stage = new Kinetic.Stage({
container: "test" // div的id。同时也可以对这个div进行样式的添加。
});

在创建任何Kinetic对象时,我们都可以直接构造他们的属性或创建之后再进行设置。

方法1:
var stage = new Kinetic.Stage({
container: "test"
});

stage.setWidth(800);
stage.setHeight(800);
方法2:
stage = new Kinetic.Stage({
container: "test",
width: 800,
height: 800
});

Layer(层)
KineticJs中对层的定义,类似PhotoShop中的层一样。根据个人需要,可以把不通种类的对象放置在不同的层中(层也可以添加事件的监听)。清晰了各个对象中的关系,和查找顺序。对象可以在不同的层中切换,不同的层也可以交换位置。KineticJs需要至少创建一个层。
var layer = new Kinetic.Layer({
id: "layer"
});

Shap(图形)
KineticJs可以方便画出通用的一些图形(继承于Shap),如矩形(Rect)、圆(Circle)、图像(Image)、精灵(Sprite)、文本(Text)、线(Line)、多边形(Polygon)、常用多边形(Regular Polygon)、路径(Path)、星星(Star)等。也可以通过Shap核心方法来绘制自定义的形状。
kineticjs图形绘制核心方法 :drawFunc
示例1
var config = {

//绘制一个圆形
drawFunc : function() {

var context = this.getContext();
context.beginPath();
// 参数是arc(x, y, radius, startRad, endRad, anticlockwise)
// 以坐标点(x,y)为圆心、半径为radius的圆上的一段弧线。
// 这段弧线的起始弧度是startRad,结束弧度是endRad。
// 弧度是以x轴正方向(时钟三点钟)为基准、进行顺时针旋转的角度来计算的。
// anticlockwise表示是以逆时针方向还是顺时针方向开始绘制,如果为true则表示逆时针,如果为false则表示顺时针。
// anticlockwise参数是可选的,默认为false,即顺时针。
context.arc(200,150,50,0,Math.PI*2,true);
context.closePath();
context.fillStrokeShape(this);

this.fill();
this.stroke();
},
//填充色
fill : "gray",
//边缘线颜色
stroke : "pink",
//边缘线宽度
strokeWidth : 5
};

//创建Shape对象

var circle = new Kinetic.Shape(config);

也可以直接调用KineticJs封装好的画圆方法,并设置好指定核心参数。
示例2:
var circle = new Kinetic.Circle({
x: 200,
y: 150,
fill: 'gray',
stroke: 'pink',
radius: 50,
strokeWidth: 5
});

通过以上代码片段可以看出,kineticjs可以快速便捷的在html页面创建canvas区域并且绘制出一个圆形。以下是完整的代码。
js文件代码:
function createStage(){

//创建Kinetic舞台,绑定我们添加的<div>容器

var stage = new Kinetic.Stage({
container: "test"
});

stage.setWidth(800);
stage.setHeight(800);
//创建Kinetic用户层
var layer = new Kinetic.Layer({
id: "layer"
});
//layer.setId("layer1");

var shap = createCircle();

//添加图形到层
layer.add(shap);
//将层添加到舞台上
stage.add(layer);
// 刷新舞台
stage.draw();
}

// 创建矩形
function createRec(){
var rect = new Kinetic.Rect({
x : 200, //矩形左上角x坐标
y : 150, //矩形左上角y坐标
width : 200, //矩形的宽度
height : 100, //矩形的高度
fill : "red", //矩形的填充色
stroke : "black", //矩形边缘线的颜色
strokeWidth : 4 //矩形边缘线的宽度
});

return rect;
}

// 图形核心方法
function createShap(){
//创建config参数

var config = {

//绘制一个圆形
drawFunc : function() {

var context = this.getContext();
context.beginPath();
// 参数是arc(x, y, radius, startRad, endRad, anticlockwise)
// 以坐标点(x,y)为圆心、半径为radius的圆上的一段弧线。
// 这段弧线的起始弧度是startRad,结束弧度是endRad。
// 弧度是以x轴正方向(时钟三点钟)为基准、进行顺时针旋转的角度来计算的。
// anticlockwise表示是以逆时针方向还是顺时针方向开始绘制,如果为true则表示逆时针,如果为false则表示顺时针。
// anticlockwise参数是可选的,默认为false,即顺时针。
context.arc(200,150,50,0,Math.PI*2,true);
context.closePath();
context.fillStrokeShape(this);

this.fill();
this.stroke();
},
//填充色
fill : "gray",
//边缘线颜色
stroke : "pink",
//边缘线宽度
strokeWidth : 5
};

//创建Shape对象
return new Kinetic.Shape(config);
}

// 创建圆形
function createCircle(){
var circle = new Kinetic.Circle({
x: 200,
y: 150,
fill: 'gray',
stroke: 'pink',
radius: 50,
strokeWidth: 5
});

return circle;
}

Group(组)
也可以通过组这个概念来统一管理创建的对象。
function createGroup(){
var group = new Kinetic.Group({
x: 200,
y: 150
});

var circle = new Kinetic.Circle({
radius: 8,
stroke: 'black',
strokeWidth: 5
});
group.add(circle);

var line1 = new Kinetic.Path({
data: 'M0,0L10,0A10,10,0,0,1,-10,0z',
fill: 'yellow'
});
group.add(line1);

var line2 = new Kinetic.Path({
data: 'M0,0L-10,0A10,10,0,0,1,10,0z',
fill: 'red'
});
group.add(line2);

return group;
}


html页面代码
<!doctype html>
<html xmlns=http://www.w3.org/1999/xhtml>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<meta http-equiv=X-UA-Compatible content=IE=9>
<title>Stage</title>
<script type="text/javascript" src="js/jquery-1.9.0.min.js" ></script>
<script type="text/javascript" src="js/kinetic.js" ></script>
<script type="text/javascript" src="test.js" ></script>
<script type="text/javascript">
//在页面加载时进行绘图
window.onload = function() {
createStage();
};
</script>
</head>

<body>
<!-- 路网图 -->
<div id="test" class="nmap"></div>

</body>
</html>

代码的完整逻辑是
创建stage对象 -> 创建layer对象 -> 创建自定义对象并实现逻辑 ->将对象add到layer中 ->将layer add到stage中 -> 刷新stage
有的时候,动态改变了层、对象、舞台的效果,但是在html页面中没有看到效果是因为,没有刷新对应的对象。一般刷新对象用draw()或drawScene()方法。

Property(属性)
对于图形对象来说,都具备大多数相同的属性。因为都是继承于Node。简单列出一些常用属性。
x:对象位于坐标的x点位置
y:对象位于坐标的y点位置
width:对象的宽度
height:对象的高度
draggable:是否可以拖拽
id:对象的id
name:对象名称
visible:是否可见
scale:缩放大小
scaleX:缩放后的x
scaleY:缩放后的y
opacity:透明度
offsetX:相对位置的x
offsetY:相对位置的y
fill:填充色
stroke:边缘色
strokeWidth:边缘宽度
callback:回调方法(function(){})
duration:持续时间
。。。。。。还有很多就不一一列出

Event(事件)和Selector(选择器)
在KineticJs中可以给对象绑定响应事件,就像jquery一样方便简单。所支持的事件类型包括: mouseover, mouseout, mousemove, mousedown, mouseup, click, dblclick, dragstart ,gragend等。绑定事件所用的方法是on()
object.on(“evtName”, function(evt){

// 事件响应代码

});
解绑事件我们用 off("name")。
模拟事件用// 触发事件鼠标点击事件
object.simulate(“evtName”);

例如,我在已创建好的圆形对象上绑定一个点击和鼠标滑过、滑出事件。
// 创建圆形
function createCircle(){
var mover = "yellow", mout = "red";
var circle = new Kinetic.Circle({
x: 200,
y: 150,
fill: 'gray',
stroke: 'pink',
radius: 50,
strokeWidth: 5
});

circle.on("click",function(){
alert("You clicked me.");
});

circle.on("mouseover",function(){
circle.setFill(mover);
circle.setStroke("bule");
circle.draw();
});

circle.on("mouseout",function(){
circle.setFill(mout);
circle.setStroke("yellow");
circle.draw();
});

return circle;
}

同时,我们还可以多事件绑定
circle.on("evtName1 evtName2",function(){
// 逻辑
});

和事件命名
circle.on("evtName.A evtName.B",function(){
// 逻辑
});

还可以取消事件的监听
// 在构造方法的config参数中设置

var obj = new Kinetic.x({
listening: false
});

// 使用对象方法设置

obj.listen(true);

KineticJs也像JQuery一样,可以很方便的选取一个对象。选择器的形式也大同小异。
var obj = stage.get("#id");
var obj = stage.get(".name");
我们可以通过stage或者layer对象来取的对应的对象。注意,通过get方法取得的对象,是一个数组。


触摸事件响应
对于应用在移动设备上的开发,触摸事件的响应,与普通电脑处理的方法相似,但名称不同。触摸屏事件有touchstart, touchmove, touchend, tap, dbltap, dragstart, dragmove 以及 dragend。
触摸屏的触摸点坐标的获取就不是用getMousePosition(evt),而是触摸屏专用方法getTouchPosition(evt)或者桌面与触摸屏通用方法getUserPosition(evt)。

Tween(图形的线性变化)
KineticJs也可以实现图形从原始的状态到新的线性变化,可以通过设置一系列如 x, y, rotation, width, height, radius, strokeWidth, alpha, scale, centerOffset属性来改变渐变。用duration来计时变化的时间。
示例:对shap对象进行变化
var tween = new Kinetic.Tween({
node: shap, // 要变化的对象
opacity: 0, // 透明度 0-1 透明-不透明
duration: 1, // 1秒
x: 300, // 新坐标x
y: 150, // 新坐标y
easing: Kinetic.Easings.EaseInOut // 变化效果
});

tween.play(); // 开始

以上在开始变化对象时,要保证对象已经被add到具体的一个layer中,否则对象不会变化。
还可以根据需要对正在变化中的对象进行暂停和重新开始变化等操作,具体方法有pause(),reset(),reverse(),seek(number),pause(),finish()。在变化完毕,也可以进行回调,用callback属性。
对于渐变的类型,还有很多Kinetic.Easings.BackEaseIn, Kinetic.Easings.BackEaseOut ,Kinetic.Easings.BackEaseInOut ,Kinetic.Easings.ElasticEaseIn ,Kinetic.Easings.ElasticEaseOut ,Kinetic.Easings.ElasticEaseInOut ,Kinetic.Easings.BounceEaseOut ,Kinetic.Easings.BounceEaseIn ,Kinetic.Easings.BounceEaseInOut ,Kinetic.Easings.EaseIn ,Kinetic.Easings.EaseOut ,Kinetic.Easings.EaseInOut ,Kinetic.Easings.StrongEaseIn ,Kinetic.Easings.StrongEaseOut ,Kinetic.Easings.StrongEaseInOut ,Kinetic.Easings.Linear

Animation(动画)
KineticJs还提供了根据帧来显示画面。

function createAnimation(stage, layer){
var config = {
id: "aaaa",
x : 200,
y : 150,
radius : 30,
fill : "red",
stroke : "black",
strokeWidth : 5
};

var circle = new Kinetic.Circle(config);

var amplitude = 150;
var period = 2000;

var centerX = stage.getWidth() / 2;

layer.add(circle);
var anim = new Kinetic.Animation(function(frame) {
circle.move({x:100,y:100});
}, layer);
anim.start();

}

在这个方法中,frame为参数,此参数对象包含两个属性,一个是frame.time,表示当前帧是动画开始后的毫秒数,另一个属性是 frame.timeDiff,表示的是当前帧与上一帧之间的时间毫秒差。当前帧因该是什么形态就是根据这两个事件来判断的。

其它方法
KineticJs还有一些常用方法。包括移动对象到指定图层,组,舞台等方法。对象的zindex属性可以改变彼此之间的层叠关系,zindex最大的值的对象在最上层,这样就可以指定对象之间的遮盖。
指定一个对象moveTo到指定的一个图层、组、舞台等。
还可以直接指定对象移动到遮盖或者它所遮盖的地方。
//移动到最上层
layer.moveToTop();

//移动到最下层
layer.moveToBottom();

//向上移动一层
layer.moveUp();

//向下移动一层
layer.moveDown();

//设定层的ZIndex值
layer.setZIndex(5);

如果想输出整个舞台到外部成图片格式,Kineticjs也可以做到。可以通过toDataURL(config)方法来输出。x,y,width,height指定舞台的区域;mimeType可以设置"image/png" or "image/jpeg"格式. "image/png"是默认格式;quality指定图片质量0-1浮点型。
也可以将舞台输出层json格式(toJson())或者load(json)。但是事件和图片不能被序列化。需要重新回调加载。

以上,暂写到这里。欢迎大家交流。
...全文
6962 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
snake.sxs 2018-04-13
  • 打赏
  • 举报
回复
正在学习这个,楼主方便留个QQ请教一下吗?我的qq:1065617008
YUDG 2017-06-06
  • 打赏
  • 举报
回复
引用 2 楼 u012118784 的回复:
找了好久都找不到资料学习
其实,你按照例子做,多做几个,也就上手了。这个和SVG绘图是一样的套路。
wzqworry 2016-10-20
  • 打赏
  • 举报
回复
找了好久都找不到资料学习
pf_yin 2015-12-21
  • 打赏
  • 举报
回复

25,985

社区成员

发帖
与我相关
我的任务
社区描述
高性能WEB开发
社区管理员
  • 高性能WEB开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧