Konva 是一個 基於 Canvas 開發的 2d js 框架庫, 它可以輕松的實現桌面應用和移動應用中的圖形交互交互效果.
Konva 可以高效的實現動畫, 變換, 節點嵌套, 局部操作, 濾鏡, 緩存, 事件等功能, 不僅僅適用於桌面與移動開發, 還有更為廣泛的應用.
Konva 允許在舞台上繪圖, 添加事件監聽, 移動或縮放某個圖形, 獨立旋轉, 以及高效的動畫. 即使應用中含有數千個圖形也是可以輕松實現的.
1.1. 使用 Konva
打開鏈接 http://konvajs.github.io/, 下載 KonvaJS 代碼.
開發中為了方便調試, 使用完全版. 實際使用使用壓縮版.
使用 script 標簽導入需要使用的 Konva 庫.
<script src="konva.js"></script>
1.2. KonvaJS 的理念
任何圖形都存在於舞台中( Konva.Stage ). 這個舞台中又可以包多個用戶層( Konva.Layer ).
每一個層中都含有兩個 <canvas> 着色器: 一個前台渲染器, 一個后台渲染器. 前台渲染器是可以看見的部分, 而后台渲染器是一個隱藏的 canvas. 后台渲染器為了提高效率實現事件監聽的工作.
每一個層可以包含形狀( Shape ), 形狀的組( Group ), 甚至是由組組成的組. 舞台, 層, 組, 以及形狀都是虛擬的節點( node ). 類似於 HTML 頁面中的 DOM 節點.
在這個圖形中, 首先有一個舞台( Stage ). 該舞台在頁面中與整個頁面的大小一樣. 然后舞台中有一個層( Layer ). 層中有一個矩形( Rect )和一個圓形( Circle ). 因此就有一個樹結構:
所有的節點都可以設置樣式與變化. 即使 Konva 可以重新渲染形狀, 例如: 矩形, 圓形, 圖片, 精靈, 文本, 線段, 多邊形, 正多邊形, 路徑, 和星星等. 但是開發者依舊可以根據 Shape 類的模板自定義自己的圖形, 然后重寫 draw 方法.
只要擁有了 舞台( Stage ), 並且上面放置了層( Layer )和圖形( Shape ), 那么就可以為他添加事件監聽, 變換節點, 運行動畫, 使用路徑, 甚至是更多的效果.
例如要實現上面的案例:
需要引入 Konva.js 文件
<script src="konva.js"></script>
然后頁面中放置一個容器作為 Konva 處理的對象. Konva 會在該容器中添加 canvas 標簽. 值得說明的是, 需要為這個標簽添加 id 屬性.
<div id="dv"></div>
然后編寫 js 代碼. Konva 是一個完全面向對象的庫.
創建舞台
var stage = new Konva.Stage({
container: 'dv',
width: window.innerWidth,
height: window.innerHeight
});
首先, 在 Konva 中所有的圖形都是在 Konva 中的一個構造函數. Konva 是全局的命名空間.
創建舞台使用的是 Stage 構造函數. 該函數需要提供參數.
Konva 中所有圖形的參數都是使用 json 對象的方式進行提供.
舞台需要設置容器的 id, 即 container 屬性. 以及寬( width ), 高( height ).
舞台中可以放置一個到多個層( Layer ), 所有的圖形應該放在在層中.
首先創建層對象. 層對象不需要傳遞參數.
var layer = new Konva.Layer();
將層添加到舞台中. Konva 中凡是添加, 都是使用 add 方法.
stage.add( layer );
在層中放置一個矩形, 就創建一個 矩形對象.
矩形對象需要四個參數來確定, 分別是 左上角的兩個坐標, 和 寬與高.
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 200,
height: 100,
fill: 'red'
});
Konva 中添加顏色使用 fill 屬性和 stroke 屬性, 分別表示填充顏色與描邊顏色.
將矩形添加到 層中
layer.add( rect );
在層中添加一個圓形, 使用構造函數 Circle
var circle = new Konva.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 100,
fill: 'pink',
stroke: 'blue'
});
layer.add( circle );
Konva 中使用 radius 設置圓形的半徑.
Konva 中如果需要獲取對象的數據, 使用 getXXX 方法. 傳入參數即設置, 不傳參數就是獲取數據.
最后繪圖使用 draw 方法
layer.draw();
1.3. 基本形狀
Konva.js 支持的形狀有: 矩形( Rect ), 圓形( Circle ), 橢圓( Rllipse ), 線段( Line ), 圖像( Image ), 文本( Text ), 文本路徑( TextPath ), 星星( Start ), 標簽( Label ), SVG 路徑( SVG Path ), 正多邊形( RegularPolygon ). 同時也可以自定義形狀.
自定義形狀使用 Shape 構造函數創建
需要提供自定義的繪圖方法 sceneFunc
var triangle = new Konva.Shape({
sceneFunc: function ( ctx ) {
// 自定義繪圖路徑
ctx.moveTo( window.innerWidth / 2, window.innerHeight / 4 );
ctx.lineTo( window.innerWidth / 2 - window.innerHeight / ( 2 * 1.732 ), window.innerHeight * 3 / 4 );
ctx.lineTo( window.innerWidth / 2 + window.innerHeight / ( 2 * 1.732 ), window.innerHeight * 3 / 4 );
ctx.closePath();
// Konva.js 的獨有方法
ctx.fillStrokeShape( this );
},
fill: 'pink',
stroke: 'red'
});
將圖形添加后繪圖
layer.add( triangle );
layer.draw();
1.4. 樣式
所有的形狀都支持下列樣式屬性:
填充. 顏色, 漸變或圖片.
描邊. 顏色與寬度.
陰影. 顏色, 偏移量, 透明度與模糊
透明度
1.4.1. 繪制正五邊形
構造函數: Konva.RegularPolygon( options )
常用屬性:
x, y. 表示正多邊形的中心坐標.
sides. 表示正多邊形的邊數.
radius. 表示半徑.
fill. 填充顏色.
stroke. 描邊的顏色.
strokeWidth. 描邊的寬度.
shadowOffsetX 和 shadowOffsety. 描述背景的偏移量.
shadowBlur. 表示模糊程度.
opacity. 表示透明度( 取值在 0, 1 之間 ).
案例
var shape = new Konva.RegularPolygon({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
sides: 5,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
shadowOffsetX: 20,
shadowOffsetY: 25,
shadowBlurBlur: 40,
opacity: 0.5
});
layer.add( shape );
1.5. 事件
使用 Konva 可以輕松的實現監聽用戶添加的事件. 例如 click, dblclick, mouseover, tap, dbltap, touchstart 等. 屬性值變化事件. 例如 scaleXChange, fillChange 等. 以及拖拽事件. 例如 dragstart, dragmove, dragend.
代碼
circle.on( 'mouseout touchend', function () {
console.log( '用戶輸入' );
});
circle.on( 'xChange', function () {
console.log( '位置發生改變' );
});
circle.on( 'dragend', function () {
console.log( '拖動停止' );
});
1.6. 拖拽與降低
Konva 支持拖拽的功能. 也支持下降事件( drop, dropenter, dropleave, dropover ).
如果需要實現拖拽的功能. 可以設置 draggable 屬性為 true.
創建的時候設置屬性
創建后使用方法設置屬性
shape.draggable( true );
Konva 還支持給拖拽事件添加移動范圍.
1.7. 濾鏡( Filter )
Konva 支持多種濾鏡功能. 例如: 模糊, 翻轉, 聲音等.
1.8. 動畫
Konva 中可以使用兩種方式創建動畫
使用 Konva.Animation
var anim = new Konva.Animation(function ( frame ) {
var time = frame.time,
timeDiff = frame.timeDiff,
frameRate = frame.frameRate;
// 更新代碼
}, layer );
使用 Konva.Tween
var tween = new Konva.Tween({
node: rect,
duration: 1,
x: 140,
rotation: Math.PI * 2,
opacity: 1,
strokeWidth: 6
});
// 或者使用新的短方法
circle.to({
duration: 1,
fill: 'green'
});
1.9. 選擇器
當構建規模較大的應用時, 如果可以對元素進行搜索是非常方便的. Konva 使用選擇器來實現元素的查找. 使用 find() 方法返回一個集合. 使用 findOne() 方法返回集合中的第 0 個元素.
給元素提供 name 屬性, 可以使用 '.name' 來進行獲取. 類似於類選擇器.
使用構造函數的名字也可以作為名字選擇器. 類似於標簽選擇器.
使用 id 屬性, 則使用 '#id' 來獲取.
查找方法使用層對象來調用.
案例
...
var r = 100;
var c1 = new Konva.Circle({
x: stage.getWidth() / 8,
y: stage.getHeight() / 2,
radius: r,
fill: 'red',
stroke: '#000',
id: 'c1'
});
layer.add( c1 );
var c2 = new Konva.Circle({
x: stage.getWidth() / 8 * 3,
y: stage.getHeight() / 2,
radius: r,
fill: 'red',
stroke: '#000',
name: 'c'
});
layer.add( c2 );
var c3 = new Konva.Circle({
x: stage.getWidth() / 8 * 5,
y: stage.getHeight() / 2,
radius: r,
fill: 'red',
stroke: '#000',
name: 'c'
});
layer.add( c3 );
var c3 = new Konva.Circle({
x: stage.getWidth() / 8 * 7,
y: stage.getHeight() / 2,
radius: r,
fill: 'red',
stroke: '#000'
});
layer.add( c3 );
layer.find( '.c' ).each(function ( v, i ) {
v.fill( 'pink' );
});
layer.find( '#c1' ).forEach(function ( v, i ) {
v.stroke( 'blue' );
v.strokeWidth( 10 );
});
layer.find( 'Circle' ).each( function ( v, i ) {
v.stroke( 'green' );
});
...
1.10. 序列號與反序列化
所有被創建的對象都可以保存為 JSON 對象. 可以在服務器或本地存儲中使用它.
var json = stage.toJSON();
同時, 也可以從 JSON 中恢復 Konva 對象.
var json = '{"attrs":{"width":578,"height":200},' +
'"className":"Stage", ' +
'"children":[{ ' +
'"attrs":{},' +
'"className":"Layer",' +
'"children":[ ' +
'{"attrs":{ ' +
'"x":100,"y":100,' +
'"sides":6,"radius":70,' +
'"fill":"red","stroke":"black",' +
'"strokeWidth":4},' +
'"className":"RegularPolygon"}' +
']' +
'}]}';
var stage = Konva.Node.create(json, 'container');
2. 形狀 Shape
2.1. 矩形 Rect
創建語法: new Konva.Rect( config )
常用屬性:
cornerRadius 屬性. 數字類型, 表示圓角矩形的圓角半徑.
fill 屬性. 字符串, 設置填充顏色.
stroke 屬性. 字符串, 設置描邊顏色.
dash 屬性. 數組, 用於描述虛線的間隔.
x, y, width, height 屬性. 數字, 描述矩形的位置與寬高.
name, id 屬性. 字符串, 用於設置搜索標記.
opacity 屬性. 數字, 用於設置透明度.
scaleX, scaleY 屬性. 數字, 用於設置縮放變換.
rotation 屬性. 數字, 用於設置旋轉角度.
draggable 屬性. 布爾類型, 用於設置是否允許拖拽.
lineJoin, lineCap 屬性. 設置線樣式.
常用方法:
Konva 中構造函數的屬性多半有同名的方法.
toJSON() 方法. 將動畫轉換成 json 字符串.
to( params ) 方法. 使用 Tween 動畫.
setAttrs( config ) 與 setAttr( attr, val ) 方法, 用於重新設置屬性.
remove() 方法. 將當前對象刪除, 但是銷毀.
on( evtStr, handler ) 與 off( evtStr ) 方法, 用於添加與移除事件.
案例
...
var rect = new Konva.Rect({
x: 100, y: 100,
width: 200, height: 100,
stroke: 'red', fill: 'pink'
});
layer.add( rect );
...
2.2. 圓 Circle
創建語法: new Konva.Circle( config )
常用屬性:
radius 屬性. 數字類型, 用於設置半徑.
fill, stroke 屬性.
strokeWidth 屬性.
lineJoin, lineCap 屬性.
dash 屬性.
x, y 屬性
常用方法:
2.3. 橢圓 Ellipse
創建語法: new Konva.Ellipse( config ).
常用屬性:
x, y 屬性. 數字類型, 表示橢圓中心的坐標
radius 屬性. 對象類型, x, y 分別表示橢圓的長軸與短軸.
案例
var ellipse = new Konva.Ellipse({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: {
x: 100, y: 100
},
stroke: 'red',
fill: 'pink',
rotation: 30
});
效果
2.4. 楔形 Wedge
創建語法: new Konva.Wedge( config )
常用屬性:
angle 屬性. 表示楔形的角度. 角度帶有方向, 水平向右為 0 度. 使用角度單位.
radius 屬性. 表示半徑.
clockwise 屬性. 表示方向.
x, y, lineJoin, lineCap, fill, stroke, ...
常用方法:
案例
...
var data = [ .3, .4, .2, .1 ];
var colors = 'red, pink, green, blue'.split( ',' );
var startAngle = -90;
data.forEach( function ( v, i ) {
var wedge = new Konva.Wedge({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 100,
angle: startAngle + 360 * v,
rotation: startAngle,
fill: colors[ i ],
opacity: .8
});
startAngle += 360 * v;
layer.add( wedge );
});
...
效果
2.5. 線段 Line
線段有折現, 曲線與閉合線路的用法.
創建語法: new Konva.Line( config )
常用屬性:
points 屬性. 數組, 用於存儲折線的各個點的坐標.
tension 屬性. 數字類型, 用於表示曲線連線. 默認為 0.
closed 屬性. 布爾值, 用於表示是否閉合路徑.
x, y 屬性. 用於設置繪制直線時的參考坐標原點.
常用方法:
說明:
使用 Konva.Line 構造函數創建直線.
使用 Konva.Line 構造函數與 closed = true 屬性可以創建多邊形.
使用 Konva.Line 構造函數與 tension 屬性可以創建曲線板.
使用 Konva.Line 構造函數與 tension 屬性, 以及 closed = true 可以創建氣泡.
案例
var line = new Konva.Line({
x: 100, y: 100,
points: [ 10, 0, 100, 100, 200, 0 ],
tension: 1,
stroke: 'red'
});
layer.add( line );
var rect = new Konva.Line({
x: 300, y: 100,
points: [ 0, 0, 100, 0, 100, 100, 0, 100 ],
closed: true,
stroke: 'red'
});
layer.add( rect );
效果
2.6. 圖片 Image
創建語法: new Konva.Image( config )
常用屬性:
x, y, width, height
image 屬性. 用於設置圖片對象.
crop 屬性. 對象: { x, y, width, height }. 表示裁剪.
2.7. 文本 Text
創建語法: new Konva.Text( config )
常用屬性:
fontFamily 屬性.
fontSize 屬性.
fontStyle 屬性.
fontVariant 屬性
text 屬性. 用於設置文本內容.
align 屬性. 可選值: left, center, right.
padding 屬性.
lineHeight 屬性.
x, y 屬性
案例
// 創建文本
var txt = new Konva.Text({
x: 100, y: 100,
align: 'left',
text: '測試文本',
fontSize: 30,
padding: 10,
width: 200,
height: 200
});
layer.add( txt );
var rect = new Konva.Rect({
x: 100, y: 100,
width: 200, height: 200,
stroke: 'red'
});
layer.add( rect );
效果
2.8. 星星 Star
創建語法: new Konva.Star( config )
常用屬性:
x, y
numPoints 屬性. 表示 幾角星.
innerRadius 屬性. 表示內半徑.
outerRadius 屬性. 表示外半徑.
旋轉的五角星
var star = new Konva.Star({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
numPoints: 5,
outerRadius: 100,
innerRadius: 50,
stroke: 'red',
fill: 'lightgreen'
});
layer.add( star );
var tween = new Konva.Tween({
node: star,
rotation: 360,
duration: 2,
onFinish: function () {
this.reset();
this.play();
}
});
tween.play();
效果
2.9. 圓環 Ring
創建語法: new Konva.Ring( config )
常用屬性:
innerRadius, outerRadius
clockwise
案例
var ring = new Konva.Ring({
x: width / 2,
y: height / 2,
innerRadius: 50,
outerRadius: 100,
fill: 'pink',
stroke: 'blue',
});
layer.add( ring );
效果
2.10. 圓弧 Arc
創建語法: new Konva.Arc( config )
常用屬性:
innerRadius, outerRadius
angle
案例
var arc = new Konva.Arc({
x: width / 2,
y: height / 2,
innerRadius: 70,
outerRadius: 100,
stroke: 'green',
fill: 'pink',
angle: 60,
rotation: -90
});
layer.add( arc );
效果
2.11. 正多邊形 Regular Polygon
創建語法: new Konva.RegularPolygon( config )
常用屬性:
sides 屬性. 表示多邊形的邊數.
radius 屬性.
案例
var shape = new Konva.RegularPolygon({
x: width / 2, y: height / 2,
sides: 6,
radius: 100,
fill: 'pink',
stroke: 'blue'
});
layer.add( shape );
效果
2.12. 箭頭 Arrow
創建語法: new Konva.Arrow( config )
常用屬性:
points 屬性
tension 屬性
pointerLength 屬性. 表示箭頭的長度.
pointerWidth 屬性. 表示箭頭的寬度.
案例
var rect1 = new Konva.Rect({
x: width / 4 - 50,
y: height / 4 - 25,
stroke: '#000',
width: 100,
height: 50,
fill: 'pink',
opacity: .5
});
layer.add( rect1 );
var txt1 = new Konva.Text({
x: width / 4 - 50,
y: height / 4 - 6,
fontSize: 12,
text: 'Object 構造函數',
align: 'center',
width: 100,
height: 50
});
layer.add( txt1 );
var rect2 = new Konva.Rect({
x: width * 3 / 4 - 50,
y: height * 3 / 4 - 25,
stroke: '#000',
width: 100,
height: 50,
fill: 'pink',
opacity: .5
});
layer.add( rect2 );
var txt2 = new Konva.Text({
x: width * 3 / 4 - 50,
y: height * 3 / 4 - 6,
fontSize: 12,
text: 'Object.prototype',
align: 'center',
width: 100,
height: 50
});
layer.add( txt2 );
var arrow = new Konva.Arrow({
points: [
width / 4 + 50,
height / 4,
width / 2,
height / 4,
width / 2,
height * 3 / 4,
width * 3 / 4 - 50 - 7,
height * 3 / 4
],
pointerLength: 15,
pointerWidth: 6,
fill: '#ccc',
stroke: '#ccc',
lineWidth: .7
});
layer.add( arrow );
效果
3. 組 Group
創建語法: new Konva.Group( config )
常用屬性:
x, y, width, height
rotation, draggable
案例
var group = new Konva.Group({
x: 100, y: 100,
width: 100,
height: 100
});
layer.add( group );
group.add( new Konva.Rect({
x: 0, y: 0, width: 100, height: 100,
fill: 'red', stroke: 'blue'
}) );
注意: 放在 group 中的形狀使用 group 作為參考坐標.
4. Konva.Easing
BackEaseIn
BackEaseOut
BackEaseInOut
ElasticEaseIn
ElasticEaseOut
ElasticEaseInOut
BounceEaseOut
BounceEaseIn
BounceEaseInOut
EaseIn
EaseOut
EaseInOut
StrongEaseIn
StrongEaseOut
StrongEaseInOut
Linear