Konva

179 阅读3分钟

1.konva是什么

  • 是一个扩展了 2d 上下文的 HTML5 Canvas JavaScript 框架
  • 支持动画、过渡、节点嵌套、分层、过滤,事件处理

Konva 支持高性能动画、过渡、节点嵌套、分层、过滤、缩放,旋转,缓存等

Konva 支持高性能动画、过渡、节点嵌套、分层、过滤、,

缓存、桌面和移动应用程序的事件处理等等。

2.konav如何工作

  1. 每一层都有两个渲染器: 一个场景渲染器和一个点击图渲染器。

场景渲染器是看到的,点击图形渲染器是一个特殊的隐藏用于高性能事件检测的画布。

  1. 每一层可以包含形状、形状组或其他组的组,阶段、层、组和形状是虚拟节点,类似于 HTML 页面中的 DOM 节点。

3.形状

  1. 内置: Rect, Circle, Ellipse, Line, Polygorn, Spline, Blob, Image, Text, TextPath, Star, Label, SVG Path
  2. 自定义形状
        const triangle = new Konva.Shape({
      sceneFunc: function (context) {
        context.beginPath()
        context.moveTo(20, 50)
        context.lineTo(220, 80)
        context.quadraticCurveTo(150, 100, 260, 170)
        context.closePath()
        context.fillStrokeShape(triangle)
      },
      fill: '#00D2FF',
      stroke: 'black',
      strokeWidth: 4
    })
    

image.png

  1. 给形状添加样式
     const  pentagon = new Konva.RegularPolygon({
      x: 100,
      y: 100,
      sides: 5,
      radius: 70,
      fill: 'red',
      stroke: 'black',
      strokeWidth: 4,
      shadowOffsetX: 20,
      shadowOffsetY: 25,
      shadowBlur: 40,
      opacity: 0.5
    })
    

4.事件

    circle.on('mouseout touchend', function () {
      console.log('user input mouseout touchend')
    })

    circle.on('xChange', function () {
      console.log('position change')
    })

    circle.on('dragend', function () {
      console.log('drag stopped')
    })
    
     stage.on('mousedown touchstart', (e) => {
      x1 = stage?.getPointerPosition()?.x ?? 0
      y1 = stage?.getPointerPosition()?.y ?? 0
    })

  • mouseout touchend 监听鼠标进入元素事件
  • xChange 位置改变事件
  • dragend 拖拽事件 结束的时候

stage 事件

```tsx
 stage.on('mousedown touchstart', (e) => {
  x1 = stage?.getPointerPosition()?.x ?? 0
  y1 = stage?.getPointerPosition()?.y ?? 0
})

 stage.on('mousemove touchmove', (e) => {
  x2 = stage?.getPointerPosition()?.x ?? 0
  y2 = stage?.getPointerPosition()?.y ?? 0
})
```
  • mousedown touchstart 鼠标按下开始时间
  • mousemove touchmove 鼠标移动事件

删除事件

键盘事件

  • 在 Konva 没有像 keydown 或 keyup 这样的内置键盘事件。
  • 方法
      1. window 上加监听事件
      1. 或者使用 tabIndex 属性使 stage 容器可聚焦,并在其上侦听事件。
   const container = stage.container()

    // 确保舞台可以获得焦点
    container.tabIndex = 1 // 使舞台可以获得焦点
    container.style.outline = 'none' // 去掉焦点时的轮廓
    container.focus()

    container.addEventListener('keydown', function (e) {
      console.log(e.key)
      e.preventDefault()
    })

5.拖拽

增加.draggable(true),可以给当前元素增加,也可以给整个层级添加

6.动画

   const anim = new Konva.Animation((frame) => {
      if (frame) {
        // Example: Move shapes up and down
        const time = frame.time
        const yOffset = Math.sin(time * 0.001) * 50 

        circle.y(stage.height() / 2 + yOffset)
        triangle.y(stage.height() / 2 + yOffset)
        pentagon.y(100 + yOffset)
      }
      layer.batchDraw()
    }, layer)

   
    anim.start()
    
    
     var tween = new Konva.Tween({
      node: circle,
      duration: 1,
      x: 140,
      rotation: Math.PI * 2,
      opacity: 1,
      strokeWidth: 6
    })
    tween.play()

    circle.to({
      duration: 1,
      fill: 'green'
    })

-Tween

  • Animation

7.选择器 selectors 和 transformer

可以使用 find () 方法 (返回集合) 或 findOne () 方法 (返回集合的第一个元素)

1.transformer 允许轻松地调整和旋转任何节点或节点集(不会改变宽高 只会改变scaleX scaleY

8.序列化


var json = stage.toJSON();  // 所有对象转为JSON


导入JSON

   const 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"}]}]}'

    const stage = Konva.Node.create(json, 'container')

9.svg

方法一 Konva.Image

Konva.Image.fromURL('/image.svg', (image) => {   layer.add(image); });

方法二 Konva.Path

   const path = new Konva.Path({
        x: 50,
        y: 40,
        data: 'M213.1,6.7c-32.4-14.4-73.7,0-88.1,30.6C110.6,4.9,67.5-9.5,36.9,6.7C2.8,22.9-13.4,62.4,13.5,110.9C33.3,145.1,67.5,170.3,125,217c59.3.186.7,93.5-71.9,111.5-106.1C263.4,64.2,247.2,22.9.3.18.1,6.7z',
        fill: 'green',
        scaleX: 0.5,
        scaleY: 0.5,
      });