diff --git a/lib/calc.js b/lib/calc.js index 27dfbc1..88ea3e6 100644 --- a/lib/calc.js +++ b/lib/calc.js @@ -1,4 +1,4 @@ -var calculate = function (s) { +module.exports = function (s) { s = s.trim(); const stack = new Array(); let preSign = '+'; @@ -45,6 +45,4 @@ var calculate = function (s) { ans += stack.pop(); } return ans; -}; - -module.exports = calculate; +}; \ No newline at end of file diff --git a/lib/pen.js b/lib/pen.js index 18d4733..f702c8b 100644 --- a/lib/pen.js +++ b/lib/pen.js @@ -1,33 +1,38 @@ const QR = require('./qrcode.js'); const GD = require('./gradient.js'); +export const penCache = { + // 用于存储带 id 的 view 的 rect 信息 + viewRect: {}, + textLines: {}, +}; +export const clearPenCache = id => { + if (id) { + penCache.viewRect[id] = null; + penCache.textLines[id] = null; + } else { + penCache.viewRect = {}; + penCache.textLines = {}; + } +}; export default class Painter { constructor(ctx, data) { this.ctx = ctx; this.data = data; } - isMoving = false; - // 动态模板时的缓存,加速渲染 - movingCache = {}; - callbackInfo = {}; - // 用于存储带 id 的 view 的 rect 信息 - viewRect = {}; - paint(callback, isMoving, movingCache) { + paint(callback) { this.style = { width: this.data.width.toPx(), height: this.data.height.toPx(), }; - if (isMoving) { - this.isMoving = true; - this.movingCache = movingCache; - } + this._background(); for (const view of this.data.views) { this._drawAbsolute(view); } this.ctx.draw(false, () => { - callback && callback(this.callbackInfo); + callback && callback(); }); } @@ -262,14 +267,14 @@ export default class Painter { width = Math.round(view.sWidth / ratio); height = Math.round(view.sHeight / ratio); } else if (view.css.width === 'auto') { - height = view.css.height.toPx(false, this.style.height, this.viewRect); + height = view.css.height.toPx(false, this.style.height); width = (view.sWidth / view.sHeight) * height; } else if (view.css.height === 'auto') { - width = view.css.width.toPx(false, this.style.width, this.viewRect); + width = view.css.width.toPx(false, this.style.width); height = (view.sHeight / view.sWidth) * width; } else { - width = view.css.width.toPx(false, this.style.width, this.viewRect); - height = view.css.height.toPx(false, this.style.height, this.viewRect); + width = view.css.width.toPx(false, this.style.width); + height = view.css.height.toPx(false, this.style.height); } break; } @@ -278,26 +283,29 @@ export default class Painter { console.error('You should set width and height'); return; } - width = view.css.width.toPx(false, this.style.width, this.viewRect); - height = view.css.height.toPx(false, this.style.height, this.viewRect); + width = view.css.width.toPx(false, this.style.width); + height = view.css.height.toPx(false, this.style.height); break; } let x; if (view.css && view.css.right) { if (typeof view.css.right === 'string') { - x = this.style.width - view.css.right.toPx(true, this.style.width, this.viewRect); + x = this.style.width - view.css.right.toPx(true, this.style.width); } else { // 可以用数组方式,把文字长度计算进去 // [right, 文字id, 乘数(默认 1)] const rights = view.css.right; - x = this.style.width - rights[0].toPx(true, this.style.width) - this.viewRect[rights[1]].width * (rights[2] || 1); + x = + this.style.width - + rights[0].toPx(true, this.style.width) - + penCache.viewRect[rights[1]].width * (rights[2] || 1); } } else if (view.css && view.css.left) { if (typeof view.css.left === 'string') { - x = view.css.left.toPx(true, this.style.width, this.viewRect); + x = view.css.left.toPx(true, this.style.width); } else { const lefts = view.css.left; - x = lefts[0].toPx(true, this.style.width) + this.viewRect[lefts[1]].width * (lefts[2] || 1); + x = lefts[0].toPx(true, this.style.width) + penCache.viewRect[lefts[1]].width * (lefts[2] || 1); } } else { x = 0; @@ -305,14 +313,14 @@ export default class Painter { //const y = view.css && view.css.bottom ? this.style.height - height - view.css.bottom.toPx(true) : (view.css && view.css.top ? view.css.top.toPx(true) : 0); let y; if (view.css && view.css.bottom) { - y = this.style.height - height - view.css.bottom.toPx(true, this.style.height, this.viewRect); + y = this.style.height - height - view.css.bottom.toPx(true, this.style.height); } else { if (view.css && view.css.top) { if (typeof view.css.top === 'string') { - y = view.css.top.toPx(true, this.style.height, this.viewRect); + y = view.css.top.toPx(true, this.style.height); } else { const tops = view.css.top; - y = tops[0].toPx(true, this.style.height) + this.viewRect[tops[1]].height * (tops[2] || 1); + y = tops[0].toPx(true, this.style.height) + penCache.viewRect[tops[1]].height * (tops[2] || 1); } } else { y = 0; @@ -396,7 +404,7 @@ export default class Painter { } this._doShadow(view); if (view.id) { - this.viewRect[view.id] = { + penCache.viewRect[view.id] = { width, height, left: x, @@ -520,10 +528,9 @@ export default class Painter { this.ctx.save(); const { width, height, extra } = this._preProcess(view, view.css.background && view.css.borderRadius); this.ctx.fillStyle = view.css.color || 'black'; - if (this.isMoving && JSON.stringify(this.movingCache) !== JSON.stringify({})) { - this.viewRect[view.id] = this.movingCache.viewRect; + if (view.id && penCache.textLines[view.id]) { this.ctx.textAlign = view.css.textAlign ? view.css.textAlign : 'left'; - for (const i of this.movingCache.lineArray) { + for (const i of penCache.textLines[view.id]) { const { measuredWith, text, x, y, textDecoration } = i; if (view.css.textStyle === 'stroke') { this.ctx.strokeText(text, x, y, measuredWith); @@ -550,12 +557,7 @@ export default class Painter { const _w = this.ctx.measureText(textArray[i]).width; textWidth = _w > textWidth ? _w : textWidth; } - this.viewRect[view.id].width = width ? (textWidth < width ? textWidth : width) : textWidth; - if (!this.isMoving) { - Object.assign(this.callbackInfo, { - viewRect: this.viewRect[view.id], - }); - } + penCache.viewRect[view.id].width = width ? (textWidth < width ? textWidth : width) : textWidth; } let lineIndex = 0; for (let j = 0; j < textArray.length; ++j) { @@ -619,6 +621,7 @@ export default class Painter { lineX = x; break; } + const y = -(height / 2) + (lineIndex === 0 ? view.css.fontSize.toPx() : view.css.fontSize.toPx() + lineIndex * lineHeight); @@ -661,16 +664,16 @@ export default class Painter { this.ctx.strokeStyle = view.css.color; this.ctx.stroke(); } - if (!this.isMoving) { - this.callbackInfo.lineArray - ? this.callbackInfo.lineArray.push({ + if (view.id) { + penCache.textLines[view.id] + ? penCache.textLines[view.id].push({ text, x, y, measuredWith, textDecoration, }) - : (this.callbackInfo.lineArray = [ + : (penCache.textLines[view.id] = [ { text, x, diff --git a/painter.js b/painter.js index e9cfeed..32cc760 100644 --- a/painter.js +++ b/painter.js @@ -1,4 +1,4 @@ -import Pen from './lib/pen'; +import Pen, { penCache, clearPenCache } from './lib/pen'; import Downloader from './lib/downloader'; import WxCanvas from './lib/wx-canvas'; @@ -17,7 +17,6 @@ Component({ canvasNode: null, paintCount: 0, currentPalette: {}, - movingCache: {}, outterDisabled: false, isDisabled: false, needClear: false, @@ -40,6 +39,7 @@ Component({ observer: function (newVal, oldVal) { if (this.isNeedRefresh(newVal, oldVal)) { this.paintCount = 0; + clearPenCache(); this.startPaint(); } }, @@ -48,6 +48,7 @@ Component({ type: Object, observer: function (newVal, oldVal) { if (!this.isEmpty(newVal) && !this.properties.use2D) { + clearPenCache(); this.initDancePalette(newVal); } }, @@ -55,11 +56,11 @@ Component({ // 缩放比,会在传入的 palette 中统一乘以该缩放比 scaleRatio: { type: Number, - value: 1 + value: 1, }, widthPixels: { type: Number, - value: 0 + value: 0, }, // 启用脏检查,默认 false dirty: { @@ -74,18 +75,16 @@ Component({ type: Object, observer: function (newVal, oldVal) { if (newVal && !this.isEmpty(newVal) && !this.properties.use2D) { - this.doAction(newVal, (callbackInfo) => { - this.movingCache = callbackInfo - }, false, true) + this.doAction(newVal, null, false, true); } }, }, disableAction: { type: Boolean, observer: function (isDisabled) { - this.outterDisabled = isDisabled - this.isDisabled = isDisabled - } + this.outterDisabled = isDisabled; + this.isDisabled = isDisabled; + }, }, clearActionBox: { type: Boolean, @@ -96,12 +95,12 @@ Component({ this.frontContext.draw(); }, 100); this.touchedView = {}; - this.prevFindedIndex = this.findedIndex + this.prevFindedIndex = this.findedIndex; this.findedIndex = -1; } } - this.needClear = needClear - } + this.needClear = needClear; + }, }, }, @@ -112,7 +111,6 @@ Component({ }, methods: { - /** * 判断一个 object 是否为 空 * @param {object} object @@ -141,28 +139,26 @@ Component({ top: `${rect.top}px`, borderWidth: '4rpx', borderColor: '#1A7AF8', - color: 'transparent' - } - } + color: 'transparent', + }, + }; if (type === 'text') { boxArea.css = Object.assign({}, boxArea.css, { - borderStyle: 'dashed' - }) + borderStyle: 'dashed', + }); } if (this.properties.customActionStyle && this.properties.customActionStyle.border) { - boxArea.css = Object.assign({}, boxArea.css, this.properties.customActionStyle.border) + boxArea.css = Object.assign({}, boxArea.css, this.properties.customActionStyle.border); } Object.assign(boxArea, { - id: 'box' - }) - return boxArea + id: 'box', + }); + return boxArea; }, getScaleIcon(rect, type) { - let scaleArea = {} - const { - customActionStyle - } = this.properties + let scaleArea = {}; + const { customActionStyle } = this.properties; if (customActionStyle && customActionStyle.scale) { scaleArea = { type: 'image', @@ -171,8 +167,8 @@ Component({ height: `${2 * ACTION_DEFAULT_SIZE}rpx`, width: `${2 * ACTION_DEFAULT_SIZE}rpx`, borderRadius: `${ACTION_DEFAULT_SIZE}rpx`, - } - } + }, + }; } else { scaleArea = { type: 'rect', @@ -181,25 +177,26 @@ Component({ width: `${2 * ACTION_DEFAULT_SIZE}rpx`, borderRadius: `${ACTION_DEFAULT_SIZE}rpx`, color: '#0000ff', - } - } + }, + }; } scaleArea.css = Object.assign({}, scaleArea.css, { align: 'center', left: `${rect.right + ACTION_OFFSET.toPx()}px`, - top: type === 'text' ? `${rect.top - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px` : `${rect.bottom - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px` - }) + top: + type === 'text' + ? `${rect.top - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px` + : `${rect.bottom - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px`, + }); Object.assign(scaleArea, { - id: 'scale' - }) - return scaleArea + id: 'scale', + }); + return scaleArea; }, getDeleteIcon(rect) { - let deleteArea = {} - const { - customActionStyle - } = this.properties + let deleteArea = {}; + const { customActionStyle } = this.properties; if (customActionStyle && customActionStyle.scale) { deleteArea = { type: 'image', @@ -208,8 +205,8 @@ Component({ height: `${2 * ACTION_DEFAULT_SIZE}rpx`, width: `${2 * ACTION_DEFAULT_SIZE}rpx`, borderRadius: `${ACTION_DEFAULT_SIZE}rpx`, - } - } + }, + }; } else { deleteArea = { type: 'rect', @@ -218,91 +215,96 @@ Component({ width: `${2 * ACTION_DEFAULT_SIZE}rpx`, borderRadius: `${ACTION_DEFAULT_SIZE}rpx`, color: '#0000ff', - } - } + }, + }; } deleteArea.css = Object.assign({}, deleteArea.css, { align: 'center', left: `${rect.left - ACTION_OFFSET.toPx()}px`, - top: `${rect.top - ACTION_OFFSET.toPx() - deleteArea.css.height.toPx() / 2}px` - }) + top: `${rect.top - ACTION_OFFSET.toPx() - deleteArea.css.height.toPx() / 2}px`, + }); Object.assign(deleteArea, { - id: 'delete' - }) - return deleteArea + id: 'delete', + }); + return deleteArea; }, doAction(action, callback, isMoving, overwrite) { if (this.properties.use2D) { return; } - let newVal = null + let newVal = null; if (action) { - newVal = action.view + newVal = action.view; } if (newVal && newVal.id && this.touchedView.id !== newVal.id) { // 带 id 的动作给撤回时使用,不带 id,表示对当前选中对象进行操作 - const { - views - } = this.currentPalette; + const { views } = this.currentPalette; for (let i = 0; i < views.length; i++) { if (views[i].id === newVal.id) { // 跨层回撤,需要重新构建三层关系 this.touchedView = views[i]; this.findedIndex = i; this.sliceLayers(); - break + break; } } } - const doView = this.touchedView + const doView = this.touchedView; if (!doView || this.isEmpty(doView)) { - return + return; } if (newVal && newVal.css) { if (overwrite) { - doView.css = newVal.css + doView.css = newVal.css; } else if (Array.isArray(doView.css) && Array.isArray(newVal.css)) { - doView.css = Object.assign({}, ...doView.css, ...newVal.css) + doView.css = Object.assign({}, ...doView.css, ...newVal.css); } else if (Array.isArray(doView.css)) { - doView.css = Object.assign({}, ...doView.css, newVal.css) + doView.css = Object.assign({}, ...doView.css, newVal.css); } else if (Array.isArray(newVal.css)) { - doView.css = Object.assign({}, doView.css, ...newVal.css) + doView.css = Object.assign({}, doView.css, ...newVal.css); } else { - doView.css = Object.assign({}, doView.css, newVal.css) + doView.css = Object.assign({}, doView.css, newVal.css); } } if (newVal && newVal.rect) { doView.rect = newVal.rect; } if (newVal && newVal.url && doView.url && newVal.url !== doView.url) { - downloader.download(newVal.url, this.properties.LRU).then((path) => { - if (newVal.url.startsWith('https')) { - doView.originUrl = newVal.url - } - doView.url = path; - wx.getImageInfo({ - src: path, - success: (res) => { - doView.sHeight = res.height - doView.sWidth = res.width - this.reDraw(doView, callback, isMoving) - }, - fail: () => { - this.reDraw(doView, callback, isMoving) + downloader + .download(newVal.url, this.properties.LRU) + .then(path => { + if (newVal.url.startsWith('https')) { + doView.originUrl = newVal.url; } + doView.url = path; + wx.getImageInfo({ + src: path, + success: res => { + doView.sHeight = res.height; + doView.sWidth = res.width; + this.reDraw(doView, callback, isMoving); + }, + fail: () => { + this.reDraw(doView, callback, isMoving); + }, + }); }) - }).catch((error) => { - // 未下载成功,直接绘制 - console.error(error) - this.reDraw(doView, callback, isMoving) - }) + .catch(error => { + // 未下载成功,直接绘制 + console.error(error); + this.reDraw(doView, callback, isMoving); + }); } else { - (newVal && newVal.text && doView.text && newVal.text !== doView.text) && (doView.text = newVal.text); - (newVal && newVal.content && doView.content && newVal.content !== doView.content) && (doView.content = newVal.content); - this.reDraw(doView, callback, isMoving) + newVal && newVal.text && doView.text && newVal.text !== doView.text && (doView.text = newVal.text); + newVal && + newVal.content && + doView.content && + newVal.content !== doView.content && + (doView.content = newVal.content); + this.reDraw(doView, callback, isMoving); } }, @@ -310,133 +312,104 @@ Component({ const draw = { width: this.currentPalette.width, height: this.currentPalette.height, - views: this.isEmpty(doView) ? [] : [doView] - } + views: this.isEmpty(doView) ? [] : [doView], + }; const pen = new Pen(this.globalContext, draw); - if (isMoving && doView.type === 'text') { - pen.paint((callbackInfo) => { - callback && callback(callbackInfo); - this.triggerEvent('viewUpdate', { - view: this.touchedView - }); - }, true, this.movingCache); - } else { - // 某些机型(华为 P20)非移动和缩放场景下,只绘制一遍会偶然性图片绘制失败 - // if (!isMoving && !this.isScale) { - // pen.paint() - // } - pen.paint((callbackInfo) => { - callback && callback(callbackInfo); - this.triggerEvent('viewUpdate', { - view: this.touchedView - }); - }) - } + pen.paint(callbackInfo => { + callback && callback(callbackInfo); + this.triggerEvent('viewUpdate', { + view: this.touchedView, + }); + }); - const { - rect, - css, - type - } = doView + const { rect, css, type } = doView; this.block = { width: this.currentPalette.width, height: this.currentPalette.height, - views: this.isEmpty(doView) ? [] : [this.getBox(rect, doView.type)] - } + views: this.isEmpty(doView) ? [] : [this.getBox(rect, doView.type)], + }; if (css && css.scalable) { - this.block.views.push(this.getScaleIcon(rect, type)) + this.block.views.push(this.getScaleIcon(rect, type)); } if (css && css.deletable) { - this.block.views.push(this.getDeleteIcon(rect)) + this.block.views.push(this.getDeleteIcon(rect)); } - const topBlock = new Pen(this.frontContext, this.block) + const topBlock = new Pen(this.frontContext, this.block); topBlock.paint(); }, isInView(x, y, rect) { - return (x > rect.left && - y > rect.top && - x < rect.right && - y < rect.bottom - ) + return x > rect.left && y > rect.top && x < rect.right && y < rect.bottom; }, isInDelete(x, y) { for (const view of this.block.views) { if (view.id === 'delete') { - return (x > view.rect.left && - y > view.rect.top && - x < view.rect.right && - y < view.rect.bottom) + return x > view.rect.left && y > view.rect.top && x < view.rect.right && y < view.rect.bottom; } } - return false + return false; }, isInScale(x, y) { for (const view of this.block.views) { if (view.id === 'scale') { - return (x > view.rect.left && - y > view.rect.top && - x < view.rect.right && - y < view.rect.bottom) + return x > view.rect.left && y > view.rect.top && x < view.rect.right && y < view.rect.bottom; } } - return false + return false; }, touchedView: {}, findedIndex: -1, onClick() { - const x = this.startX - const y = this.startY - const totalLayerCount = this.currentPalette.views.length - let canBeTouched = [] - let isDelete = false - let deleteIndex = -1 + const x = this.startX; + const y = this.startY; + const totalLayerCount = this.currentPalette.views.length; + let canBeTouched = []; + let isDelete = false; + let deleteIndex = -1; for (let i = totalLayerCount - 1; i >= 0; i--) { - const view = this.currentPalette.views[i] - const { - rect - } = view + const view = this.currentPalette.views[i]; + const { rect } = view; if (this.touchedView && this.touchedView.id && this.touchedView.id === view.id && this.isInDelete(x, y, rect)) { - canBeTouched.length = 0 - deleteIndex = i - isDelete = true - break + canBeTouched.length = 0; + deleteIndex = i; + isDelete = true; + break; } if (this.isInView(x, y, rect)) { canBeTouched.push({ view, - index: i - }) + index: i, + }); } } - this.touchedView = {} + this.touchedView = {}; if (canBeTouched.length === 0) { - this.findedIndex = -1 + this.findedIndex = -1; } else { - let i = 0 - const touchAble = canBeTouched.filter(item => Boolean(item.view.id)) + let i = 0; + const touchAble = canBeTouched.filter(item => Boolean(item.view.id)); if (touchAble.length === 0) { - this.findedIndex = canBeTouched[0].index + this.findedIndex = canBeTouched[0].index; } else { for (i = 0; i < touchAble.length; i++) { if (this.findedIndex === touchAble[i].index) { - i++ - break + i++; + break; } } if (i === touchAble.length) { - i = 0 + i = 0; } - this.touchedView = touchAble[i].view - this.findedIndex = touchAble[i].index + this.touchedView = touchAble[i].view; + this.findedIndex = touchAble[i].index; this.triggerEvent('viewClicked', { - view: this.touchedView - }) + view: this.touchedView, + }); } } if (this.findedIndex < 0 || (this.touchedView && !this.touchedView.id)) { @@ -446,47 +419,43 @@ Component({ this.triggerEvent('touchEnd', { view: this.currentPalette.views[deleteIndex], index: deleteIndex, - type: 'delete' - }) - this.doAction() + type: 'delete', + }); + this.doAction(); } else if (this.findedIndex < 0) { - this.triggerEvent('viewClicked', {}) + this.triggerEvent('viewClicked', {}); } - this.findedIndex = -1 - this.prevFindedIndex = -1 + this.findedIndex = -1; + this.prevFindedIndex = -1; } else if (this.touchedView && this.touchedView.id) { this.sliceLayers(); } }, sliceLayers() { - const bottomLayers = this.currentPalette.views.slice(0, this.findedIndex) - const topLayers = this.currentPalette.views.slice(this.findedIndex + 1) + const bottomLayers = this.currentPalette.views.slice(0, this.findedIndex); + const topLayers = this.currentPalette.views.slice(this.findedIndex + 1); const bottomDraw = { width: this.currentPalette.width, height: this.currentPalette.height, background: this.currentPalette.background, - views: bottomLayers - } + views: bottomLayers, + }; const topDraw = { width: this.currentPalette.width, height: this.currentPalette.height, - views: topLayers - } + views: topLayers, + }; if (this.prevFindedIndex < this.findedIndex) { new Pen(this.bottomContext, bottomDraw).paint(); - this.doAction(null, (callbackInfo) => { - this.movingCache = callbackInfo - }) + this.doAction(); new Pen(this.topContext, topDraw).paint(); } else { new Pen(this.topContext, topDraw).paint(); - this.doAction(null, (callbackInfo) => { - this.movingCache = callbackInfo - }) + this.doAction(); new Pen(this.bottomContext, bottomDraw).paint(); } - this.prevFindedIndex = this.findedIndex + this.prevFindedIndex = this.findedIndex; }, startX: 0, @@ -497,116 +466,105 @@ Component({ startTimeStamp: 0, onTouchStart(event) { if (this.isDisabled) { - return + return; } - const { - x, - y - } = event.touches[0] - this.startX = x - this.startY = y - this.startTimeStamp = new Date().getTime() + const { x, y } = event.touches[0]; + this.startX = x; + this.startY = y; + this.startTimeStamp = new Date().getTime(); if (this.touchedView && !this.isEmpty(this.touchedView)) { - const { - rect - } = this.touchedView + const { rect } = this.touchedView; if (this.isInScale(x, y, rect)) { - this.isScale = true - this.movingCache = {} - this.startH = rect.bottom - rect.top - this.startW = rect.right - rect.left + this.isScale = true; + this.startH = rect.bottom - rect.top; + this.startW = rect.right - rect.left; } else { - this.isScale = false + this.isScale = false; } } else { - this.isScale = false + this.isScale = false; } }, onTouchEnd(e) { if (this.isDisabled) { - return + return; } - const current = new Date().getTime() - if ((current - this.startTimeStamp) <= 500 && !this.hasMove) { - !this.isScale && this.onClick(e) + const current = new Date().getTime(); + if (current - this.startTimeStamp <= 500 && !this.hasMove) { + !this.isScale && this.onClick(e); } else if (this.touchedView && !this.isEmpty(this.touchedView)) { this.triggerEvent('touchEnd', { view: this.touchedView, - }) + }); } - this.hasMove = false + this.hasMove = false; }, onTouchCancel(e) { if (this.isDisabled) { - return + return; } - this.onTouchEnd(e) + this.onTouchEnd(e); }, hasMove: false, onTouchMove(event) { if (this.isDisabled) { - return + return; } - this.hasMove = true + this.hasMove = true; if (!this.touchedView || (this.touchedView && !this.touchedView.id)) { - return + return; } - const { - x, - y - } = event.touches[0] - const offsetX = x - this.startX - const offsetY = y - this.startY - const { - rect, - type - } = this.touchedView - let css = {} + const { x, y } = event.touches[0]; + const offsetX = x - this.startX; + const offsetY = y - this.startY; + const { rect, type } = this.touchedView; + let css = {}; if (this.isScale) { - const newW = this.startW + offsetX > 1 ? this.startW + offsetX : 1 + clearPenCache(this.touchedView.id); + const newW = this.startW + offsetX > 1 ? this.startW + offsetX : 1; if (this.touchedView.css && this.touchedView.css.minWidth) { if (newW < this.touchedView.css.minWidth.toPx()) { - return + return; } } if (this.touchedView.rect && this.touchedView.rect.minWidth) { if (newW < this.touchedView.rect.minWidth) { - return + return; } } - const newH = this.startH + offsetY > 1 ? this.startH + offsetY : 1 + const newH = this.startH + offsetY > 1 ? this.startH + offsetY : 1; css = { width: `${newW}px`, - } + }; if (type !== 'text') { if (type === 'image') { - css.height = `${(newW) * this.startH / this.startW }px` + css.height = `${(newW * this.startH) / this.startW}px`; } else { - css.height = `${newH}px` + css.height = `${newH}px`; } } } else { - this.startX = x - this.startY = y + this.startX = x; + this.startY = y; css = { left: `${rect.x + offsetX}px`, top: `${rect.y + offsetY}px`, right: undefined, - bottom: undefined - } + bottom: undefined, + }; } - this.doAction({ - view: { - css - } - }, (callbackInfo) => { - if (this.isScale) { - this.movingCache = callbackInfo - } - }, !this.isScale) + this.doAction( + { + view: { + css, + }, + }, + null, + !this.isScale, + ); }, initScreenK() { @@ -631,12 +589,9 @@ Component({ } this.isDisabled = true; this.initScreenK(); - this.downloadImages(this.properties.dancePalette).then(async (palette) => { - this.currentPalette = palette - const { - width, - height - } = palette; + this.downloadImages(this.properties.dancePalette).then(async palette => { + this.currentPalette = palette; + const { width, height } = palette; if (!width || !height) { console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`); @@ -663,10 +618,7 @@ Component({ startPaint() { this.initScreenK(); - const { - width, - height - } = this.properties.palette; + const { width, height } = this.properties.palette; if (!width || !height) { console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`); @@ -680,33 +632,36 @@ Component({ needScale = this.properties.use2D; } if (this.properties.widthPixels) { - setStringPrototype(this.screenK, this.properties.widthPixels / this.canvasWidthInPx) - this.canvasWidthInPx = this.properties.widthPixels + setStringPrototype(this.screenK, this.properties.widthPixels / this.canvasWidthInPx); + this.canvasWidthInPx = this.properties.widthPixels; } if (this.canvasHeightInPx !== height.toPx()) { this.canvasHeightInPx = height.toPx(); needScale = needScale || this.properties.use2D; } - this.setData({ - photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`, - }, function () { - this.downloadImages(this.properties.palette).then(async palette => { - if (!this.photoContext) { - this.photoContext = await this.getCanvasContext(this.properties.use2D, 'photo'); - } - if (needScale) { - const scale = getApp().systemInfo.pixelRatio; - this.photoContext.width = this.canvasWidthInPx * scale; - this.photoContext.height = this.canvasHeightInPx * scale; - this.photoContext.scale(scale, scale); - } - new Pen(this.photoContext, palette).paint(() => { - this.saveImgToLocal(); + this.setData( + { + photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`, + }, + function () { + this.downloadImages(this.properties.palette).then(async palette => { + if (!this.photoContext) { + this.photoContext = await this.getCanvasContext(this.properties.use2D, 'photo'); + } + if (needScale) { + const scale = getApp().systemInfo.pixelRatio; + this.photoContext.width = this.canvasWidthInPx * scale; + this.photoContext.height = this.canvasHeightInPx * scale; + this.photoContext.scale(scale, scale); + } + new Pen(this.photoContext, palette).paint(() => { + this.saveImgToLocal(); + }); + setStringPrototype(this.screenK, this.properties.scaleRatio); }); - setStringPrototype(this.screenK, this.properties.scaleRatio); - }); - }); + }, + ); }, downloadImages(palette) { @@ -716,52 +671,58 @@ Component({ const paletteCopy = JSON.parse(JSON.stringify(palette)); if (paletteCopy.background) { preCount++; - downloader.download(paletteCopy.background, this.properties.LRU).then((path) => { - paletteCopy.background = path; - completeCount++; - if (preCount === completeCount) { - resolve(paletteCopy); - } - }, () => { - completeCount++; - if (preCount === completeCount) { - resolve(paletteCopy); - } - }); + downloader.download(paletteCopy.background, this.properties.LRU).then( + path => { + paletteCopy.background = path; + completeCount++; + if (preCount === completeCount) { + resolve(paletteCopy); + } + }, + () => { + completeCount++; + if (preCount === completeCount) { + resolve(paletteCopy); + } + }, + ); } if (paletteCopy.views) { for (const view of paletteCopy.views) { if (view && view.type === 'image' && view.url) { preCount++; /* eslint-disable no-loop-func */ - downloader.download(view.url, this.properties.LRU).then((path) => { - view.originUrl = view.url; - view.url = path; - wx.getImageInfo({ - src: path, - success: (res) => { - // 获得一下图片信息,供后续裁减使用 - view.sWidth = res.width; - view.sHeight = res.height; - }, - fail: (error) => { - // 如果图片坏了,则直接置空,防止坑爹的 canvas 画崩溃了 - console.warn(`getImageInfo ${view.originUrl} failed, ${JSON.stringify(error)}`); - view.url = ""; - }, - complete: () => { - completeCount++; - if (preCount === completeCount) { - resolve(paletteCopy); - } - }, - }); - }, () => { - completeCount++; - if (preCount === completeCount) { - resolve(paletteCopy); - } - }); + downloader.download(view.url, this.properties.LRU).then( + path => { + view.originUrl = view.url; + view.url = path; + wx.getImageInfo({ + src: path, + success: res => { + // 获得一下图片信息,供后续裁减使用 + view.sWidth = res.width; + view.sHeight = res.height; + }, + fail: error => { + // 如果图片坏了,则直接置空,防止坑爹的 canvas 画崩溃了 + console.warn(`getImageInfo ${view.originUrl} failed, ${JSON.stringify(error)}`); + view.url = ''; + }, + complete: () => { + completeCount++; + if (preCount === completeCount) { + resolve(paletteCopy); + } + }, + }); + }, + () => { + completeCount++; + if (preCount === completeCount) { + resolve(paletteCopy); + } + }, + ); } } } @@ -774,73 +735,81 @@ Component({ saveImgToLocal() { const that = this; setTimeout(() => { - wx.canvasToTempFilePath({ - canvasId: 'photo', - canvas: that.properties.use2D ? that.canvasNode : null, - destWidth: that.canvasWidthInPx * getApp().systemInfo.pixelRatio, - destHeight: that.canvasHeightInPx * getApp().systemInfo.pixelRatio, - success: function (res) { - that.getImageInfo(res.tempFilePath); + wx.canvasToTempFilePath( + { + canvasId: 'photo', + canvas: that.properties.use2D ? that.canvasNode : null, + destWidth: that.canvasWidthInPx, + destHeight: that.canvasHeightInPx, + success: function (res) { + that.getImageInfo(res.tempFilePath); + }, + fail: function (error) { + console.error(`canvasToTempFilePath failed, ${JSON.stringify(error)}`); + that.triggerEvent('imgErr', { + error: error, + }); + }, }, - fail: function (error) { - console.error(`canvasToTempFilePath failed, ${JSON.stringify(error)}`); - that.triggerEvent('imgErr', { - error: error - }); - }, - }, this); + this, + ); }, 300); }, - getCanvasContext(use2D, id) { const that = this; return new Promise(resolve => { if (use2D) { const query = wx.createSelectorQuery().in(that); const selectId = `#${id}`; - query.select(selectId) - .fields({ node: true, size: true }) - .exec((res) => { - that.canvasNode = res[0].node; - const ctx = that.canvasNode.getContext('2d'); - const wxCanvas = new WxCanvas('2d', ctx, id, true, that.canvasNode); - resolve(wxCanvas); - }); + query + .select(selectId) + .fields({ node: true, size: true }) + .exec(res => { + that.canvasNode = res[0].node; + const ctx = that.canvasNode.getContext('2d'); + const wxCanvas = new WxCanvas('2d', ctx, id, true, that.canvasNode); + resolve(wxCanvas); + }); } else { const temp = wx.createCanvasContext(id, that); resolve(new WxCanvas('mina', temp, id, true)); } - }) + }); }, getImageInfo(filePath) { const that = this; wx.getImageInfo({ src: filePath, - success: (infoRes) => { + success: infoRes => { if (that.paintCount > MAX_PAINT_COUNT) { const error = `The result is always fault, even we tried ${MAX_PAINT_COUNT} times`; console.error(error); that.triggerEvent('imgErr', { - error: error + error: error, }); return; } // 比例相符时才证明绘制成功,否则进行强制重绘制 - if (Math.abs((infoRes.width * that.canvasHeightInPx - that.canvasWidthInPx * infoRes.height) / (infoRes.height * that.canvasHeightInPx)) < 0.01) { + if ( + Math.abs( + (infoRes.width * that.canvasHeightInPx - that.canvasWidthInPx * infoRes.height) / + (infoRes.height * that.canvasHeightInPx), + ) < 0.01 + ) { that.triggerEvent('imgOK', { - path: filePath + path: filePath, }); } else { that.startPaint(); } that.paintCount++; }, - fail: (error) => { + fail: error => { console.error(`getImageInfo failed, ${JSON.stringify(error)}`); that.triggerEvent('imgErr', { - error: error + error: error, }); }, }); @@ -848,15 +817,13 @@ Component({ }, }); - function setStringPrototype(screenK, scale) { /* eslint-disable no-extend-native */ /** * string 到对应的 px * @param {Number} baseSize 当设置了 % 号时,设置的基准值 - * @param {Object} relativeViewRect 所相对的 view 的信息 */ - String.prototype.toPx = function toPx(_, baseSize, relativeViewRect) { + String.prototype.toPx = function toPx(_, baseSize) { if (this === '0') { return 0; } @@ -881,18 +848,17 @@ function setStringPrototype(screenK, scale) { } return res; }; - const formula = /^calc\((.+)\)$/.exec(this) + const formula = /^calc\((.+)\)$/.exec(this); if (formula && formula[1]) { // 进行 calc 计算 - const afterOne = formula[1].replace(/([^\s]+)\.(left|right|bottom|top|width|height)/g, (word) => { - const [id, attr] = word.split('.'); - return relativeViewRect[id][attr] - } - ); + const afterOne = formula[1].replace(/([^\s]+)\.(left|right|bottom|top|width|height)/g, word => { + const [id, attr] = word.split('.'); + return penCache.viewRect[id][attr]; + }); const afterTwo = afterOne.replace(new RegExp(REG, 'g'), parsePx); return calc(afterTwo); } else { return parsePx(this); } }; -} \ No newline at end of file +} diff --git a/painter.wxml b/painter.wxml index bd7a3b6..6873c45 100644 --- a/painter.wxml +++ b/painter.wxml @@ -1,31 +1,21 @@ - - - - + + + + + + -