###### 1.0.11 更新说明
* ###### 修复 uni.canvasToTempFilePath中组件实例导致输出失败问题

###### 一款支持 Node、web、uni-app 的canvas绘图工具
###### 有使用ES6语法 有需要需自行转ES5
###### 目前uni-app环境 H5、APP 会存在clip裁剪失效的情况 hbx 3.4.8+ 已修复
---
###### Node环境注意：需要安装canvas `npm i canvas`, 并且切换Node版本后需要重新安装canvas
---
### npm
```js
npm i qs-canvas
```
## Step1 引入
* #### node
```js
const QSCanvas = require('qs-canvas')
```

* #### web
```html
<script src="xxx.js"></script>
```

* #### uni-app
```js
import QSCanvas from 'xxx.js'
```

## Step2 QSCanvas对象
```js
const qsc = new QSCanvas(options, vm)
options<Object>: {
	width<Number>: 10, //canvas的宽
	height<Number>: 10, //canvas的高
	canvasId<String>: '', //canvasId, uni-app必传、web可不传
	setCanvasWH<Function>: undefined, //动态设置canvas宽高方法, uni-app需传
	asyncDrawMode<Boolean>: true, //异步绘制模式, web、node支持, 控制是否像uni-app一样只有在调用draw时才绘制内容
}

vm<Object>: undefined //uni-app, 自定义组件实例 this ，表示在这个自定义组件下查找拥有 canvas-id 的 <canvas/> ，如果省略，则不在任何自定义组件内查找
```
---
# Attribute
```js
qsc._data<Object>: {
	oldPaintbrushProps: paintbrushProps<Object>, //当前画笔设置
	width<Number>: 10, //画布宽度
	height<Number>: 10, //画布高度
}
```
---
# API
* #### 支持原生canvas上下文所有方法(如: fill、save、clip...)

* #### setPaintbrush
###### 设置画笔属性, 原生canvas上下文除所有方法外的属性均在此设置
```js
// 展示的是默认值， 不用都传
qsc.setPaintbrush(paintbrushProps<Object>)
paintbrushProps<Object>: {
		fillStyle<String>?: '#000000',
		strokeStyle<String>?: '#000000',
		shadowColor<String>?: '#000000',
		shadowBlur<Number>?: 0,
		shadowOffsetX<Number>?: 0,
		shadowOffsetY<Number>?: 0,
		lineCap<String>?: 'butt',
		lineJoin<String>?: 'miter',
		lineWidth<Number>?: 1,
		miterLimit<Number>?: 10,
		font: { // 头条小程序只支持fontSize
			fontStyle<String>?: 'normal', 
			fontVariant<String>?: 'normal', 
			fontWeight<String>?: 'normal', 
			fontSize<Number>?: 10, 
			fontFamily<String>?: 'sans-serif' 
		},
		textAlign<String>?: 'start',
		textBaseline<String>?: 'top',
		globalAlpha<Number>?: 1.0,
		globalCompositeOperation<String>?: 'source-over',
	}
```

* #### resetPaintbrush
###### 重置画笔属性
```js
// 若不传参则重置为setPaintbrush中展示的默认值, 若传可覆盖
qsc.resetPaintbrush(paintbrushProps<Object>?)
```

* #### savePaintbrush
###### 保存画笔属性, 推入栈(先入后出)中保存, 可调用restorePaintbrush恢复
```js
qsc.savePaintbrush()
```

* #### restorePaintbrush
###### 恢复最近一次保存的画笔属性
```js
qsc.restorePaintbrush()
```

* #### saveAndSetPaintbrush
###### 先保存一次画笔属性, 再设置
```js
qsc.saveAndSetPaintbrush(paintbrushProps<Object>)
```

* #### updateCanvasWH `promise`
###### 更新画布宽高
```js
// 该方法会在结束时自动调用一次resetPaintbrush(this._data.oldPaintbrushProps)
await qsc.updateCanvasWH(options<Object>?)
options<Object>: {
	width<Number>?: this.width, // 若不传则使用初始化时的width
	height<Number>?: this.height, // 若不传则使用初始化时的height
	delay<Number>?: 50, // uni-app更新画布宽高后延时操作
}
```

* #### draw `promise`
###### 执行绘制, web、node在异步绘制模式下同uni-app一样需调用, uni-app必须调用才能绘制
```js
await qsc.draw(options<Object>?)
options<Obeject>: {
	reserve<Boolean>?: false, // 是否接着上一次绘制
}
```

* #### toImage `promise`
###### canvas转图片
```js
await qsc.toImage(options<Object>?)
options<Obeject>: {
	// web、node、uni-app 支持
	fileType<String>: 'png', // 图片格式
	quality<Number>: 1, // 图片质量，jpg格式有效
	
	// uni-app 支持
	x<Number>?: 0, // 画布x轴起点（默认0）
	y<Number>?: 0, // 画布y轴起点（默认0）
	width<Number>?: canvas宽度-x, // 画布宽度（默认为canvas宽度-x）
	height<Number>?: canvas高度-y, // 画布高度（默认为canvas高度-y）
	destWidth<Number>?: width * 屏幕像素密度, // 输出图片宽度（默认为 width * 屏幕像素密度）
	destHeight<Number>?: height * 屏幕像素密度, // 输出图片高度（默认为 height * 屏幕像素密度）
}
```


* #### drawText `promise`
###### 绘制文字, 调用calcText后进行绘制
```js
const calcR<Object> = await qsc.drawText(options<Object>?)
options<Obeject>: {
	val<String>?: '', // 文字内容
	x<Number>?: 0, // x轴位置
	y<Number>?: 0, // y轴位置
	maxWidth<Number>?: null, // 达到此最大宽度后换行
	line<Number>?: -1, // 换行时行数, 小于零则无限, 为0时会赋值为1
	lineHeight<Number>?: 0, // 行高, 行与行之间的距离, 不计文字本身高度
	paintbrushProps<Object>?: paintbrushProps, // 设置画笔属性，可以传 fillStyle 控制颜色、font.fontSize控制字体大小等
	textDecoration<Object>?: {
		line<String>?: 'line-through', // 线条类型, 支持 ['line-through','underline','overline']
		color<String>?: oldProps.fillStyle || '#000000', // 线条颜色
		thickness<Number>|width<Number>?: fontSize * 0.1 || 1, // 线条宽度
		style<String>?: 'solide', // 线条样式, 支持 ['solide', 'double', 'dotted']
		offset<Number>?: 0, // 线条偏移
		gap<Number>?: 1, // 间隔，double、dotted时的间隔
	}
}
calcR<Object>: {
	calcTexts<Array>, // 计算后的文字数组
	x<Number>, // x轴位置
	y<Number>, // y轴位置
	height<Number>, // 高度
	width<Number>, // 宽度
	top<Number>, // 上边界
	left<Number>, // 左边界
	right<Number>, // 右边界
	bottom<Number>, // 下边界
}
```

* #### calcText `promise`
###### 计算需绘制的文字
```js
// calcR可直接传给drawText绘制
const calcR<Object> = await qsc.calcText(options<Object>)
options<Object>: 同drawText的options
```


* #### drawImg `promise`
###### 绘制图片, 调用calcImg后进行绘制
```js
const calcR<Object> = await qsc.drawImg(options<Object>?)
options<Obeject>: {
	val<String>?: '', // 图片路径, 支持 网络图片、1.0.10+ 本地图片(字节小程序只支持相对路径)、base64图片(某些小程序无法获取图片信息)
	x<Number>?: 0, // x轴位置
	y<Number>?: 0, // y轴位置
	mode<String>?: 'scaleToFill', // 绘制模式 同uni-app image mode, 支持 ['scaleToFill', 'aspectFit', 'aspectFill', 'widthFix', 'heightFix']
	width<Number>?: 0, // 图片宽度
	height<Number>?: 0, // 图片高度
}
calcR<Object>: {
	drawImageArgs<Array>, // 计算后的绘制参数
	x<Number>, // x轴位置
	y<Number>, // y轴位置
	height<Number>, // 高度
	width<Number>, // 宽度
	top<Number>, // 上边界
	left<Number>, // 左边界
	right<Number>, // 右边界
	bottom<Number>, // 下边界
}
```

* #### calcImg `promise`
###### 计算需绘制的图片
```js
// calcR可直接传给drawImg绘制
const calcR<Object> = await qsc.calcText(options<Object>)
options<Object>: 同drawImg的options
```

* #### loadImage `promise`
###### 加载图片
```js
// img可直接传给 drawImg 或者 calcImg 当做 val 值
const img<Object> = await qsc.loadImage(url<String>)
url<String>: 图片路径
```

* #### drawQrCode `promise`
###### 绘制二维码， 参考诗小柒的二维码生成器代码
```js
await qsc.drawQrCode(options<Object>?)
options<Obeject>: {
	val<String>?: '', // 二维码内容
	x<Number>, // x轴位置
	y<Number>, // y轴位置
	size<Number>?: 200, // 二维码大小
	background<String>?: '#ffffff', // 背景色
	foreground<String>?: '#000000', // 前景色
	pdground<String>?: '#000000', // 定位角点颜色
	correctLevel<Number>?: 3, // 容错级别
}
```

* #### setCircle
###### 设置圆形
```js
qsc.setCircle(options<Object>?)
options<Obeject>: {
	x<Number>, // x轴位置
	y<Number>, // y轴位置
	d<Number>, // 直径
	mode<String>?: 'leftTop', // 圆心模式, 支持 ['leftTop', 'center']
	clip<Boolean>?: false, // 是否裁剪, 设置true后 需手动 qsc.restore()
}
```

* #### setRect
###### 设置矩形
```js
qsc.setRect(options<Object>?)
options<Obeject>: {
	x<Number>, // x轴位置
	y<Number>, // y轴位置
	r<Number>, // 圆角值
	width<Number>, // 宽度
	height<Number>, // 高度
	clip<Boolean>?: false, // 是否裁剪, 设置true后 需手动 qsc.restore()
}
```

* #### drawArray `promise`
###### Array形式绘制
```js
const drawR<Array> = await qsc.drawArray(options<[]<Object|Function>>?)
options<[]<Object|Function>>: [
	<Function>, //直接执行函数, 支持返回Promise
	<Object>:{
		type<String>: '', // 类型, 支持 ['text','image','qrcode','method', 'function']
		zIndex<Number>: 0, //1.0.10+ 层级， 越大越往后绘制
		//type 为 'text'、'image'、'qrcode'传原本方法需要传的参数
		...options<Object>,
		
		// type 为 method 时
		name<String>: '', // 需要执行qsc下的方法名称
		data<Array|Object>, //传给执行方法的参数, Array时以...arguments传给执行方法, Obejct时以[data<Object>]传给执行方法

		//1.0.10+ type 为 function 时
		val<Function>: '', // 需要执行qsc下的方法名称
	}
]
```

* #### initAsyncDrawMode
###### 转为异步绘制模式 uni-app无效
```js
qsc.initAsyncDrawMode()
```
* #### restoreAsyncDrawMode
###### 取消异步绘制模式 uni-app无效
```js
qsc.restoreAsyncDrawMode()
```