hios-miniprogram/components/canvasdrawer/canvasdrawer.js
2019-12-18 10:30:03 +08:00

329 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* global Component wx */
Component({
properties: {
painting: {
type: Object,
value: {
view: []
},
observer(newVal, oldVal) {
if (!this.data.isPainting) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
if (newVal && newVal.width && newVal.height) {
this.setData({
showCanvas: true,
isPainting: true
})
this.readyPigment()
}
} else {
if (newVal && newVal.mode !== 'same') {
this.triggerEvent('getImage', {
errMsg: 'canvasdrawer:samme params'
})
}
}
}
}
}
},
data: {
showCanvas: false,
width: 100,
height: 100,
tempFileList: [],
isPainting: false
},
ctx: null,
cache: {},
ready() {
// console.log('ready');
wx.removeStorageSync('canvasdrawer_pic_cache')
this.cache = wx.getStorageSync('canvasdrawer_pic_cache') || {}
this.ctx = wx.createCanvasContext('canvasdrawer', this)
},
methods: {
readyPigment() {
const {
width,
height,
views
} = this.data.painting
this.setData({
width,
height
})
const inter = setInterval(() => {
if (this.ctx) {
clearInterval(inter)
this.ctx.clearActions()
this.ctx.save()
this.getImagesInfo(views)
}
}, 100)
},
getImagesInfo(views) {
const imageList = []
for (let i = 0; i < views.length; i++) {
if (views[i].type === 'image') {
imageList.push(this.getImageInfo(views[i].url))
}
}
const loadTask = []
for (let i = 0; i < Math.ceil(imageList.length / 8); i++) {
loadTask.push(new Promise((resolve, reject) => {
Promise.all(imageList.splice(i * 8, 8)).then(res => {
resolve(res)
}).catch(res => {
reject(res)
})
}))
}
Promise.all(loadTask).then(res => {
let tempFileList = []
for (let i = 0; i < res.length; i++) {
tempFileList = tempFileList.concat(res[i])
}
this.setData({
tempFileList
})
this.startPainting()
})
},
startPainting() {
// console.log('startPainting');
const {
tempFileList,
painting: {
views
}
} = this.data
// console.log(tempFileList)
for (let i = 0, imageIndex = 0; i < views.length; i++) {
// console.log(views[i]);
// console.log(views[i].type);
if (views[i].type === 'image') {
this.drawImage({
...views[i],
url: tempFileList[imageIndex]
})
imageIndex++
} else if (views[i].type === 'text') {
if (!this.ctx.measureText) {
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用 measureText 功能,请升级到最新微信版本后重试。'
})
this.triggerEvent('getImage', {
errMsg: 'canvasdrawer:version too low'
})
return
} else {
this.drawText(views[i])
}
} else if (views[i].type === 'rect') {
this.drawRect(views[i])
}
}
// console.log('????????为什么');
this.ctx.draw(false, () => {
// console.log(this.cache);
wx.setStorageSync('canvasdrawer_pic_cache', this.cache)
const system = wx.getSystemInfoSync().system
if (/ios/i.test(system)) {
this.saveImageToLocal()
} else {
// 延迟保存图片解决安卓生成图片错位bug。
setTimeout(() => {
this.saveImageToLocal()
}, 800)
}
})
},
drawImage(params) {
// console.log('drawImage');
this.ctx.save()
const {
url,
top = 0,
left = 0,
width = 0,
height = 0,
borderRadius = 0,
deg = 0
} = params
// if (borderRadius) {
// this.ctx.beginPath()
// this.ctx.arc(left + borderRadius, top + borderRadius, borderRadius, 0, 2 * Math.PI)
// this.ctx.clip()
// this.ctx.drawImage(url, left, top, width, height)
// } else {
if (deg !== 0) {
this.ctx.translate(left + width / 2, top + height / 2)
this.ctx.rotate(deg * Math.PI / 180)
this.ctx.drawImage(url, -width / 2, -height / 2, width, height)
} else {
this.ctx.drawImage(url, left, top, width, height)
}
// }
this.ctx.restore()
},
drawText(params) {
// console.log('drawText');
this.ctx.save()
// console.log('drawText');
const {
MaxLineNumber = 2,
breakWord = false,
color = 'black',
content = '',
fontSize = 16,
top = 0,
left = 0,
lineHeight = 20,
textAlign = 'left',
width,
bolder = false,
textDecoration = 'none'
} = params
this.ctx.beginPath()
this.ctx.setTextBaseline('top')
this.ctx.setTextAlign(textAlign)
this.ctx.setFillStyle(color)
this.ctx.setFontSize(fontSize)
if (!breakWord) {
this.ctx.fillText(content, left, top)
this.drawTextLine(left, top, textDecoration, color, fontSize, content)
} else {
let fillText = ''
let fillTop = top
let lineNum = 1
for (let i = 0; i < content.length; i++) {
fillText += [content[i]]
if (this.ctx.measureText(fillText).width > width) {
if (lineNum === MaxLineNumber) {
if (i !== content.length) {
fillText = fillText.substring(0, fillText.length - 1) + '...'
this.ctx.fillText(fillText, left, fillTop)
this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
fillText = ''
break
}
}
this.ctx.fillText(fillText, left, fillTop)
this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
fillText = ''
fillTop += lineHeight
lineNum++
}
}
this.ctx.fillText(fillText, left, fillTop)
this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText)
}
this.ctx.restore()
if (bolder) {
this.drawText({
...params,
left: left + 0.3,
top: top + 0.3,
bolder: false,
textDecoration: 'none'
})
}
},
drawTextLine(left, top, textDecoration, color, fontSize, content) {
if (textDecoration === 'underline') {
this.drawRect({
background: color,
top: top + fontSize * 1.2,
left: left - 1,
width: this.ctx.measureText(content).width + 3,
height: 1
})
} else if (textDecoration === 'line-through') {
this.drawRect({
background: color,
top: top + fontSize * 0.6,
left: left - 1,
width: this.ctx.measureText(content).width + 3,
height: 1
})
}
},
drawRect(params) {
this.ctx.save()
const {
background,
top = 0,
left = 0,
width = 0,
height = 0
} = params
this.ctx.setFillStyle(background)
this.ctx.fillRect(left, top, width, height)
this.ctx.restore()
},
getImageInfo(url) {
return new Promise((resolve, reject) => {
if (this.cache[url]) {
resolve(this.cache[url])
} else {
const objExp = new RegExp(/^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/)
if (objExp.test(url)) {
wx.getImageInfo({
src: url,
complete: res => {
// console.log(res.errMsg);
if (res.errMsg === 'getImageInfo:ok') {
this.cache[url] = res.path
resolve(res.path)
} else {
this.triggerEvent('getImage', {
errMsg: 'canvasdrawer:download fail'
})
reject(new Error('getImageInfo fail'))
}
}
})
} else {
this.cache[url] = url
resolve(url)
}
}
})
},
saveImageToLocal() {
// console.log('saveImageToLocal');
const {
width,
height
} = this.data
wx.canvasToTempFilePath({
x: 0,
y: 0,
width,
height,
canvasId: 'canvasdrawer',
complete: res => {
if (res.errMsg === 'canvasToTempFilePath:ok') {
this.setData({
showCanvas: false,
isPainting: false,
tempFileList: []
})
this.triggerEvent('getImage', {
tempFilePath: res.tempFilePath,
errMsg: 'canvasdrawer:ok'
})
} else {
this.triggerEvent('getImage', {
errMsg: 'canvasdrawer:fail'
})
}
}
}, this)
}
}
})