Vue Konva - 基于 Canvas 开发的 2d JavaScript框架库 - 使用整理【持续更新……】

最近项目中用到Vue Konva框架,遇到一些问题基本搜不到,网上的文章基本都是些入门教程什么的。所以本文整理了使用过程中遇到的问题以及解决办法,希望你用到的时候有所帮助。

基本是按照我在开发中使用的顺序来写的,使用方法和错误处理没有做单独区分。如有需要可以搜索关键字。

我们的项目没有做动画的要求,所以本文也没有提及动画相关的。


2018.8.25

需求:类似美图秀秀网页版的拼图工具。但是美图秀秀用的是 Flash,我们用 canvas,所以能参考的也就只有效果了。

领导给选的是konva.js

Konva.js 一个基于 Canvas 开发的 2d JavaScript框架库, 它可以轻松的实现桌面应用和移动应用中的图形交互交互效果

我们的项目用了Vue,这个框架也有一个Vue版本的。

国际惯例,先撸文档:

Canvas
Konva官方文档(中文)
Konva API文档(英文)
Demo(英文)
Vue Konva(英文)
Vue Konva Issues(英文)

英文API还是挺全的,Vue的文档和文章比较少,主要还是对照英文的API。做这个需求的时候体会到程序员的英语水平真的很重要,因为后面有一些问题去issues提问的时候都是先中文组织好语言再用谷歌翻译下(///▽///)

下面来说说遇到的问题吧(都是在vue框架中)

  1. 渲染图片
  • <v-image/>标签,它的image属性值是一个image对象

  • 渲染的图片不需要改变

      script: 
      	
      	data () {
      		return {
      			// image对象
      			imageObj: new Image()
      		}
      	},
      	computed: {
      		stageImage () {
      			this.imageObj.src = this.stage.url
      			this.imageObj.width = this.stage.width
      			this.imageObj.height = this.stage.height
      			return {
      			  image: this.imageObj
      			}
      		}
      	}
    
      template:
      
      	<v-image 
      		ref="image" 
      		:config="{
      			image: stageImage
      		}"/>
    
  • 渲染的图片是可变的

      	// 创建 image 对象
      	newImage (url) {
      		let img = new Image()
      		img.src = url
      		return img
      	}
    
  • 报错:渲染的图片不是image对象,会报下面的错
    这里写图片描述

  1. 旋转(例如给<v-image/>添加rotation属性)
  • 默认旋转是围绕图片左上角(0, 0)位置的

  • 如果想围绕图片中心旋转需要配置如下属性

      	<v-image 
      		ref="image" 
      		:config="{
      			x: 200,
      			y: 150,
      			offset: {     // 让旋转点的位置从左上角移到图片中心,此时的图片坐标x,y以中心点位置计算
      				x: 200,
      				y: 150,
      			},
      			width: 400,
      			height: 300,
      			rotation: 90,
      			image: stageImage
      		}"/>
    
  1. 裁剪
  • 正三角形

      	<v-group 
      		ref="group"
      		:config="{
      			clipFunc: function(ctx) {
      				// 正三角形 150是边长
      				ctx.beginPath();
      				ctx.moveTo(75, 0)
      				ctx.lineTo(0, Math.sqrt(Math.pow(150, 2) - Math.pow(75, 2)))
      				ctx.lineTo(150, Math.sqrt(Math.pow(150, 2) - Math.pow(75, 2)))
      				ctx.closePath()
      			}
      		}">
      		<v-image 
      			ref="image" 
      			:config="{
      				image: stageImage
      			}"/>
      	</v-group>
    
  • 心形

      	<v-group 
      		ref="group"
      		:config="{
      			clipFunc: function(ctx) {
      				// 心形
      				ctx.beginPath()
      				// 起始点
      				ctx.moveTo(75, 40)
      				// 左半边
      				ctx.bezierCurveTo(75, 37, 70, 25, 50, 25)
      				ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5)
      				ctx.bezierCurveTo(20, 80, 40, 102, 75, 120)
      				// 右半边
      				ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5)
      				ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25)
      				ctx.bezierCurveTo(85, 25, 75, 37, 75, 40)
      				//闭合路径
      				ctx.closePath()
      			}
      		}">
      		<v-image 
      			ref="image" 
      			:config="{
      				image: stageImage
      			}"/>
      	</v-group>
    
  1. 阻止冒泡
    这个issues上有,直接贴了

  2. 鼠标滚轮事件
    也是issues上的

  3. 获取鼠标位置(我是在拖拽的时候用)

     // dragstart 获取鼠标位置
     dragStart () {
     	let posX = this.$refs.stage.getStage().getPointerPosition().x
     	let posY = this.$refs.stage.getStage().getPointerPosition().y
     }
    
  4. this.$refs.stage.getStage() 可以查看vue konva中舞台对象的方法,文档中没有的可以去里面找找,在_proto_属性里

  5. 序列化舞台,konva.js可以,vue konva没有toJSON()方法

  6. 生成 dataurl

     this.$refs.stage.getStage().toDataURL()
    
  7. 生成 img 标签

    this.$refs.stage.getStage().toImage({
    	callback: function(img) {
    		console.log(img)
    	}
    })
    
  8. warning: Konva warning: Unable to get data URL. Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
    error: Uncaught (in promise) TypeError: Cannot read property '1' of null
    这里写图片描述

  • 开发的时候自测没有报这个错误,发到线上之后自测依然正常,但是有的同事电脑会报这个错。
  • 刚开始排查的时候没有留意上面的警告,其实警告内容正是报错的原因“Konva警告:无法获取数据URL。 无法在’HTMLCanvasElement’上执行’toDataURL’:可能无法导出受污染的画布。
    这是因为stage渲染的图片跨域了,污染了画布。什么是“被污染”的 canvas?
  • 按照网上的方法给图片添加了image.setAttribute('crossorigin', 'anonymous')还是不行。
  • 我们的图片是单独在一台服务器上,而且本地环境测试环境正式环境的都不同,图片量很多,所以没办法放到静态文件夹中。最后的解决办法是做了转发,在图片渲染之前匹配线上存储图片的服务器域名,替换为当前域名document.domain
  • 需要注意的是,在stage的配置中不管有没有渲染的图片都必须不能跨域,而且所有url必须都是有效的,否则一样会报错。
  • 但是为什么我自测的时候没有这个问题呢,这是因为我的谷歌浏览器是命令起的,是开发者模式,所以不会报这个错。

猜你喜欢

转载自blog.csdn.net/sansan_7957/article/details/81952061