优化文字移动性能
This commit is contained in:
parent
d85be378c4
commit
b613dd610b
61
lib/pen.js
61
lib/pen.js
@ -9,17 +9,23 @@ export default class Painter {
|
||||
this.globalHeight = {};
|
||||
}
|
||||
|
||||
paint(callback) {
|
||||
isMoving = false
|
||||
movingCache = {}
|
||||
paint(callback, isMoving, movingCache) {
|
||||
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();
|
||||
callback && callback(this.callbackInfo);
|
||||
});
|
||||
}
|
||||
|
||||
@ -420,6 +426,7 @@ export default class Painter {
|
||||
this._doBorder(view, width, height);
|
||||
}
|
||||
|
||||
callbackInfo = {}
|
||||
_fillAbsText(view) {
|
||||
if (!view.text) {
|
||||
return;
|
||||
@ -434,7 +441,32 @@ export default class Painter {
|
||||
height,
|
||||
extra,
|
||||
} = this._preProcess(view, view.css.background && view.css.borderRadius);
|
||||
|
||||
if (this.isMoving && JSON.stringify(this.movingCache) !== JSON.stringify({})) {
|
||||
this.globalWidth[view.id] = this.movingCache.globalWidth
|
||||
this.ctx.setTextAlign(view.css.textAlign ? view.css.textAlign : 'left');
|
||||
for (const i of this.movingCache.lineArray) {
|
||||
const {
|
||||
measuredWith,
|
||||
text,
|
||||
x,
|
||||
y,
|
||||
} = i
|
||||
if (view.css.textStyle === 'stroke') {
|
||||
this.ctx.strokeText(text, x, y, measuredWith);
|
||||
} else {
|
||||
this.ctx.fillText(text, x, y, measuredWith);
|
||||
}
|
||||
const fontSize = view.css.fontSize.toPx();
|
||||
if (view.css.textDecoration) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(...this.callbackInfo.textDecoration.moveTo);
|
||||
this.ctx.lineTo(...this.callbackInfo.textDecoration.lineTo);
|
||||
this.ctx.closePath();
|
||||
this.ctx.strokeStyle = view.css.color;
|
||||
this.ctx.stroke();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.ctx.fillStyle = (view.css.color || 'black');
|
||||
const {
|
||||
lines,
|
||||
@ -449,6 +481,11 @@ export default class Painter {
|
||||
textWidth = this.ctx.measureText(textArray[i]).width > textWidth ? this.ctx.measureText(textArray[i]).width : textWidth;
|
||||
}
|
||||
this.globalWidth[view.id] = width ? (textWidth < width ? textWidth : width) : textWidth;
|
||||
if (!this.isMoving) {
|
||||
Object.assign(this.callbackInfo, {
|
||||
globalWidth: this.globalWidth[view.id]
|
||||
})
|
||||
}
|
||||
}
|
||||
let lineIndex = 0;
|
||||
for (let j = 0; j < textArray.length; ++j) {
|
||||
@ -477,7 +514,7 @@ export default class Painter {
|
||||
}
|
||||
measuredWith = this.ctx.measureText(text).width;
|
||||
}
|
||||
start += text.length;
|
||||
start += text.length
|
||||
// 如果是最后一行了,发现还有未绘制完的内容,则加...
|
||||
if (lineIndex === lines - 1 && (j < textArray.length - 1 || start < textArray[j].length)) {
|
||||
while (this.ctx.measureText(`${text}...`).width > width) {
|
||||
@ -516,19 +553,35 @@ export default class Painter {
|
||||
if (/\bunderline\b/.test(view.css.textDecoration)) {
|
||||
this.ctx.moveTo(x, y);
|
||||
this.ctx.lineTo(x + measuredWith, y);
|
||||
!this.isMoving && (this.callbackInfo.textDecoration = {
|
||||
moveTo: [x, y],
|
||||
lineTo: [x + measuredWith, y]
|
||||
})
|
||||
}
|
||||
if (/\boverline\b/.test(view.css.textDecoration)) {
|
||||
this.ctx.moveTo(x, y - fontSize);
|
||||
this.ctx.lineTo(x + measuredWith, y - fontSize);
|
||||
!this.isMoving && (this.callbackInfo.textDecoration = {
|
||||
moveTo: [x, y - fontSize],
|
||||
lineTo: [x + measuredWith, y - fontSize]
|
||||
})
|
||||
}
|
||||
if (/\bline-through\b/.test(view.css.textDecoration)) {
|
||||
this.ctx.moveTo(x, y - fontSize / 3);
|
||||
this.ctx.lineTo(x + measuredWith, y - fontSize / 3);
|
||||
!this.isMoving && (this.callbackInfo.textDecoration = {
|
||||
moveTo: [x, y - fontSize / 3],
|
||||
lineTo: [x + measuredWith, y - fontSize / 3]
|
||||
})
|
||||
}
|
||||
this.ctx.closePath();
|
||||
this.ctx.strokeStyle = view.css.color;
|
||||
this.ctx.stroke();
|
||||
}
|
||||
if (!this.isMoving) {
|
||||
this.callbackInfo.lineArray ? this.callbackInfo.lineArray.push({ text, x, y, measuredWith }) : this.callbackInfo.lineArray = [{ text, x, y, measuredWith }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.ctx.restore();
|
||||
|
||||
86
painter.js
86
painter.js
@ -13,6 +13,7 @@ Component({
|
||||
canvasHeightInPx: 0,
|
||||
paintCount: 0,
|
||||
currentPalette: {},
|
||||
movingCache: {},
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
@ -22,7 +23,7 @@ Component({
|
||||
},
|
||||
palette: {
|
||||
type: Object,
|
||||
observer: function (newVal, oldVal) {
|
||||
observer: function(newVal, oldVal) {
|
||||
if (this.isNeedRefresh(newVal, oldVal)) {
|
||||
this.paintCount = 0;
|
||||
this.startPaint();
|
||||
@ -31,7 +32,7 @@ Component({
|
||||
},
|
||||
dancePalette: {
|
||||
type: Object,
|
||||
observer: function (newVal, oldVal) {
|
||||
observer: function(newVal, oldVal) {
|
||||
if (!this.isEmpty(newVal)) {
|
||||
this.initDancePalette(newVal);
|
||||
}
|
||||
@ -48,7 +49,7 @@ Component({
|
||||
},
|
||||
action: {
|
||||
type: Object,
|
||||
observer: function (newVal, oldVal) {
|
||||
observer: function(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
this.doAction(newVal)
|
||||
}
|
||||
@ -82,7 +83,7 @@ Component({
|
||||
return true;
|
||||
},
|
||||
|
||||
doAction(newVal) {
|
||||
doAction(newVal, callback, isMoving) {
|
||||
if (newVal && newVal.id && this.touchedView.id !== newVal.id) {
|
||||
// 带 id 的动作给撤回时使用,不带 id,表示对当前选中对象进行操作
|
||||
const {
|
||||
@ -118,17 +119,21 @@ Component({
|
||||
const draw = {
|
||||
width: this.currentPalette.width,
|
||||
height: this.currentPalette.height,
|
||||
views: [doView]
|
||||
views: this.isEmpty(doView) ? [] : [doView]
|
||||
}
|
||||
const pen = new Pen(this.globalContext, draw);
|
||||
pen.paint();
|
||||
if (isMoving && this.currentPalette.views[0].type === 'text') {
|
||||
pen.paint(callback, true, this.movingCache);
|
||||
} else {
|
||||
pen.paint(callback)
|
||||
}
|
||||
const {
|
||||
rect
|
||||
} = doView
|
||||
const block = {
|
||||
width: this.currentPalette.width,
|
||||
height: this.currentPalette.height,
|
||||
views: [{
|
||||
views: this.isEmpty(this.touchedView) ? [] : [{
|
||||
type: 'rect',
|
||||
css: {
|
||||
height: `${rect.bottom - rect.top}px`,
|
||||
@ -151,6 +156,19 @@ Component({
|
||||
}
|
||||
}]
|
||||
}
|
||||
if (this.touchedView.type === 'text') {
|
||||
block.views.push({
|
||||
type: 'rect',
|
||||
css: {
|
||||
height: `${2 * ACTION_POINT_RADIUS}px`,
|
||||
width: `${2 * ACTION_POINT_RADIUS}px`,
|
||||
borderRadius: `${ACTION_POINT_RADIUS}px`,
|
||||
color: '#0000ff',
|
||||
left: `${rect.left - ACTION_POINT_RADIUS}px`,
|
||||
top: `${rect.top - ACTION_POINT_RADIUS}px`
|
||||
}
|
||||
})
|
||||
}
|
||||
const topBlock = new Pen(this.frontContext, block)
|
||||
topBlock.paint();
|
||||
},
|
||||
@ -173,34 +191,48 @@ Component({
|
||||
)
|
||||
},
|
||||
|
||||
isDelete(x, y, rect) {
|
||||
return (x > rect.left - ACTION_POINT_RADIUS &&
|
||||
y > rect.top - ACTION_POINT_RADIUS &&
|
||||
x < rect.left + ACTION_POINT_RADIUS &&
|
||||
y < rect.top + ACTION_POINT_RADIUS)
|
||||
},
|
||||
|
||||
touchedView: {},
|
||||
findedIndex: -1,
|
||||
onClick(event) {
|
||||
onClick() {
|
||||
const x = this.startX
|
||||
const y = this.startY
|
||||
const totalLayerCount = this.currentPalette.views.length
|
||||
const hasTouchedView = this.findedIndex !== -1
|
||||
this.touchedView = {}
|
||||
let canBeTouched = []
|
||||
let isDelete = false
|
||||
for (let i = totalLayerCount - 1; i >= 0; i--) {
|
||||
const view = this.currentPalette.views[i]
|
||||
const {
|
||||
rect
|
||||
} = view
|
||||
if (this.inArea(x, y, rect, hasTouchedView)) {
|
||||
if (this.touchedView && this.touchedView.id &&
|
||||
this.touchedView.id === view.id &&
|
||||
this.isDelete(x, y, rect)) {
|
||||
canBeTouched.length = 0
|
||||
this.currentPalette.views.splice(i, 1)
|
||||
isDelete = true
|
||||
break
|
||||
}
|
||||
if (this.inArea(x, y, rect, !this.isEmpty(this.touchedView))) {
|
||||
canBeTouched.push({
|
||||
view,
|
||||
index: i
|
||||
})
|
||||
}
|
||||
}
|
||||
this.touchedView = {}
|
||||
if (canBeTouched.length === 0) {
|
||||
this.findedIndex = -1
|
||||
} else {
|
||||
let i = 0
|
||||
const touchAble = canBeTouched.filter(item => Boolean(item.view.id))
|
||||
if (touchAble.length === 0) {
|
||||
this.touchedView = {}
|
||||
this.findedIndex = canBeTouched[0].index
|
||||
} else {
|
||||
for (i = 0; i < touchAble.length; i++) {
|
||||
@ -226,7 +258,6 @@ Component({
|
||||
}
|
||||
if (this.findedIndex < 0 || (this.touchedView && !this.touchedView.id)) {
|
||||
// 证明点击了背景 或无法移动的view
|
||||
this.touchedView = {}
|
||||
const block = {
|
||||
width: this.currentPalette.width,
|
||||
height: this.currentPalette.height,
|
||||
@ -234,7 +265,9 @@ Component({
|
||||
}
|
||||
const topBlock = new Pen(this.frontContext, block)
|
||||
topBlock.paint();
|
||||
if (this.findedIndex < 0) {
|
||||
if (isDelete) {
|
||||
this.doAction()
|
||||
} else if (this.findedIndex < 0) {
|
||||
this.triggerEvent('touchStart', {})
|
||||
}
|
||||
this.findedIndex = -1
|
||||
@ -260,11 +293,15 @@ Component({
|
||||
}
|
||||
if (this.prevFindedIndex < this.findedIndex) {
|
||||
new Pen(this.bottomContext, bottomDraw).paint();
|
||||
this.doAction()
|
||||
this.doAction(null, (callbackInfo) => {
|
||||
this.movingCache = callbackInfo
|
||||
})
|
||||
new Pen(this.topContext, topDraw).paint();
|
||||
} else {
|
||||
new Pen(this.topContext, topDraw).paint();
|
||||
this.doAction()
|
||||
this.doAction(null, (callbackInfo) => {
|
||||
this.movingCache = callbackInfo
|
||||
})
|
||||
new Pen(this.bottomContext, bottomDraw).paint();
|
||||
}
|
||||
this.prevFindedIndex = this.findedIndex
|
||||
@ -290,6 +327,7 @@ Component({
|
||||
} = this.touchedView
|
||||
if (rect.right - ACTION_POINT_RADIUS < x && x < rect.right + ACTION_POINT_RADIUS && rect.bottom - ACTION_POINT_RADIUS < y && y < rect.bottom + ACTION_POINT_RADIUS) {
|
||||
this.isScale = true
|
||||
this.movingCache = {}
|
||||
this.startH = rect.bottom - rect.top
|
||||
this.startW = rect.right - rect.left
|
||||
} else {
|
||||
@ -357,7 +395,11 @@ Component({
|
||||
}
|
||||
this.doAction({
|
||||
css
|
||||
})
|
||||
}, (callbackInfo) => {
|
||||
if (this.isScale) {
|
||||
this.movingCache = callbackInfo
|
||||
}
|
||||
}, !this.isScale)
|
||||
},
|
||||
|
||||
initScreenK() {
|
||||
@ -378,12 +420,6 @@ Component({
|
||||
|
||||
initDancePalette() {
|
||||
this.initScreenK();
|
||||
this.hasIdViews = []
|
||||
this.properties.dancePalette && this.properties.dancePalette.views.map(view => {
|
||||
if (view.id) {
|
||||
this.hasIdViews.push(view)
|
||||
}
|
||||
})
|
||||
|
||||
this.downloadImages(this.properties.dancePalette).then((palette) => {
|
||||
this.currentPalette = palette
|
||||
@ -507,10 +543,10 @@ Component({
|
||||
setTimeout(() => {
|
||||
wx.canvasToTempFilePath({
|
||||
canvasId: 'photo',
|
||||
success: function (res) {
|
||||
success: function(res) {
|
||||
that.getImageInfo(res.tempFilePath);
|
||||
},
|
||||
fail: function (error) {
|
||||
fail: function(error) {
|
||||
console.error(`canvasToTempFilePath failed, ${JSON.stringify(error)}`);
|
||||
that.triggerEvent('imgErr', {
|
||||
error: error
|
||||
|
||||
Loading…
Reference in New Issue
Block a user