Konva-前端绘图框架

发布时间 2024-01-11 11:12:11作者: _成飞

一、介绍
Konva is an HTML5 Canvas JavaScript framework that extends the 2d context by enabling canvas interactivity for desktop and mobile applications.
Konva enables high performance animations, transitions, node nesting, layering, filtering, caching, event handling for desktop
and mobile applications, and much more.
You can draw things onto the stage, add event listeners to them, move them, scale them, and rotate them independently from other shapes to support high performance animations, even if your application uses thousands of shapes.
This project began as a GitHub fork of KineticJS.

大白话翻译:
Konva是一个H5 Canvas的JavaScript的框架,它通过为桌面和移动应用程序启用画布交互来扩展2d上下文。
Konva为桌面应用和移动应用程序提供高性能动画,过渡,节点嵌套,分层,过滤,缓存,事件处理等。
你可以将事物绘制到Stage上,向其添加事件侦听器,使用高性能动画对其进行移动,缩放以及从其他形状中独立旋转它们,即使你的应用程序使用数千种形状。
这个项目开始于KineticJS的GitHub分支。

 

二、官方地址
1: Konva官方地址:https://konvajs.org/
2: Konva的Github开源地址:https://github.com/konvajs/konva
3: Api文档:https://konvajs.org/docs/index.html
4:  vue-konva:https://github.com/konvajs/vue-konva
三、使用方法
在某个vue项目中使用了konva,但是没有使用vue-konva。因为vue-konva使用的是标签形式创建各图像组件,因为绘制的图形有点稍稍复杂,可能使用标签的形式不是很方便,还是在外写好再import的方式。

3.1 开始使用

两种方式引用,一种是通过npm instsall的方式;

npm install konva

另一种是使用script标签。

<script src="https://unpkg.com/konva@7.0.3/konva.min.js"></script>

不同于其它框架,konva的id是绑定自一个div标签,而非canvas的id。当用stage绑定后会在该div下自行插入canvas标签。开始使用时需要创建一个stage,即承载各个层、组、图形的舞台;

<div id="container"> </div>

let stage = new Konva.Stage({
        container: 'container', //div的id
        width: width, //宽度
        height: height, //高度
      });

Konva提供了Rect、Circle、Ellipse、Wedge、Line、Sprite、Image、Text、TextPath、Star、Ring、Arc、Label、Path、RegularPolygon、Arrow、Custom等图形、图像和文字组件。基本每个图形的创建都是new Konva.Shape的方式,例如矩形:

let rect = new Konva.Rect({
		x: 30,
		y: 30,
		width: 150,
		height: 50,
		fill: 'red',
		stroke: 'black',
		strokeWidth: 2,
	});

添加完后需要往layer里添加,再把layer往stage里添加。但是一个stage里最好只有2-3层layer,因为一个每添加一个layer就会往绑定的div里插入一个canvas。加入canvas越多,渲染性能越差。同时控制台也会疯狂的弹警告。

Konva warning: The stage has x layers. Recommended maximum number of layers is 3-5. Adding more layers into the stage may drop the performance. Rethink your tree structure, you can use Konva.Group.

正确的做法是引入group,group可以创建多个,将需要加入的图形往group添加,再将group往layer里添加。即一个stage添加最多3-5层layer,一层layer可以添加多个group,一个group又可以添加多个shape。

 

let layer =  new Konva.Layer();
let group = new Konva.Group();
group.add(rect1);
layer.add(group);
stage.add(layer);

3.2 事件绑定

konva提供了多种事件绑定,包括mouseover, mouseout, mouseenter, mouseleave, mousemove, mousedown, mouseup, wheel, click, dblclick, dragstart, dragmove和dragend;可以给stage、layer、group和shape绑定事件。

//基本用法
target.on(eventName, function() {
	//todo
});

//给矩形绑定鼠标点击事件
//这个rect是上面3.1中创建的矩形
rect.on('click' function() {
	alert('rect被点击了');
});

3.3 图形拖拽

fabricjs框架创建出来的图形是默认可以拖拽编辑的,而konva则反其道而行之,默认创建的图形是不可拖拽,想要开启拖拽需要在创建时设置draggable为true,或者后面再进行setAttrs。同时还可以通过dragBoundFunc限制拖拽的范围。

let rect = new Konva.Rect({
		x: 30,
		y: 30,
		width: 150,
		height: 50,
		fill: 'red',
		draggable: true, //设置为可拖拽
		dragBoundFunc: function (pos) {
		  //设置只能横向拖拽
          return {
            x: pos.x,
            y: this.absolutePosition().y,
          };
        },
        
	});

3.4 动画

konva提供了动画,可以以单个图形展示动画,也可以group或其它形式一起展示动画。

//在X方向做来回运动
let centerX = stage.width() / 2;
let anim = new Konva.Animation(function (frame) {
        rect.x(
          100 * Math.sin((frame.time * 2 * Math.PI) / 2000) + centerX
        );
      }, layer);
      
anim.start();

//旋转90度
rect.to({ rotation:90, duration:1, easing: Konva.Easings.EaseIn, });

3.5 其它

除此之外,Konva还提供了更多的功能,比如多重选中、过滤器、补间动画等。具体可以参考相应的文档。

四、遇到问题
刚开始用时,没有看完文档,创建一个图形就添加一个layer,导致创建太多的layer,控制台会警告添加太多layer,后面查看标签元素,发现创建了很多个canvas标签。后面才知道了一个stage添加最多3-5层layer,一层layer可以添加多个group,一个group又可以添加多个shape。
同时,不要往layer或者stage里添加太多的内容,不然,会影响绘制效率。这种绘图在一定程度上是吃GPU,Win10下打开任务管理器会看到使用这些绘图框架都会让浏览器占用一定的GPU,特别是在老旧IE上占用尤为恐怖。
还要妥善维护创建的各图形,不然会引起内存泄漏,可以参考文档:https://konvajs.org/docs/performance/Avoid_Memory_Leaks.html