Compare commits

..

No commits in common. "master" and "2.2.0" have entirely different histories.

4 changed files with 540 additions and 546 deletions

View File

@ -1,54 +0,0 @@
/* eslint-disable */
// 四则运算
!(function () {
var calculate = function (s) {
s = s.trim();
const stack = new Array();
let preSign = '+';
let numStr = '';
const n = s.length;
for (let i = 0; i < n; ++i) {
if (s[i] === '.' || (!isNaN(Number(s[i])) && s[i] !== ' ')) {
numStr += s[i];
} else if (s[i] === '(') {
let isClose = 1;
let j = i;
while (isClose > 0) {
j += 1;
if (s[j] === '(') isClose += 1;
if (s[j] === ')') isClose -= 1;
}
numStr = `${calculate(s.slice(i + 1, j))}`;
i = j;
}
if ((isNaN(Number(s[i])) && s[i] !== '.') || i === n - 1) {
let num = parseFloat(numStr);
switch (preSign) {
case '+':
stack.push(num);
break;
case '-':
stack.push(-num);
break;
case '*':
stack.push(stack.pop() * num);
break;
case '/':
stack.push(stack.pop() / num);
break;
default:
break;
}
preSign = s[i];
numStr = '';
}
}
let ans = 0;
while (stack.length) {
ans += stack.pop();
}
return ans;
};
module.exports = calculate;
})();

View File

@ -1,44 +1,40 @@
const QR = require('./qrcode.js'); const QR = require('./qrcode.js');
const GD = require('./gradient.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 { export default class Painter {
constructor(ctx, data) { constructor(ctx, data) {
this.ctx = ctx; this.ctx = ctx;
this.data = data; this.data = data;
this.globalWidth = {};
this.globalHeight = {};
} }
paint(callback) { isMoving = false
movingCache = {}
paint(callback, isMoving, movingCache) {
this.style = { this.style = {
width: this.data.width.toPx(), width: this.data.width.toPx(),
height: this.data.height.toPx(), height: this.data.height.toPx(),
}; };
if (isMoving) {
this.isMoving = true
this.movingCache = movingCache
}
this._background(); this._background();
for (const view of this.data.views) { for (const view of this.data.views) {
this._drawAbsolute(view); this._drawAbsolute(view);
} }
this.ctx.draw(false, () => { this.ctx.draw(false, () => {
callback && callback(); callback && callback(this.callbackInfo);
}); });
} }
_background() { _background() {
this.ctx.save(); this.ctx.save();
const { width, height } = this.style; const {
width,
height,
} = this.style;
const bg = this.data.background; const bg = this.data.background;
this.ctx.translate(width / 2, height / 2); this.ctx.translate(width / 2, height / 2);
@ -64,7 +60,7 @@ export default class Painter {
_drawAbsolute(view) { _drawAbsolute(view) {
if (!(view && view.type)) { if (!(view && view.type)) {
// 过滤无效 view // 过滤无效 view
return; return
} }
// 证明 css 为数组形式,需要合并 // 证明 css 为数组形式,需要合并
if (view.css && view.css.length) { if (view.css && view.css.length) {
@ -89,14 +85,20 @@ export default class Painter {
} }
} }
_border({ borderRadius = 0, width, height, borderWidth = 0, borderStyle = 'solid' }) { _border({
borderRadius = 0,
width,
height,
borderWidth = 0,
borderStyle = 'solid'
}) {
let r1 = 0, let r1 = 0,
r2 = 0, r2 = 0,
r3 = 0, r3 = 0,
r4 = 0; r4 = 0
const minSize = Math.min(width, height); const minSize = Math.min(width, height);
if (borderRadius) { if (borderRadius) {
const border = borderRadius.split(/\s+/); const border = borderRadius.split(/\s+/)
if (border.length === 4) { if (border.length === 4) {
r1 = Math.min(border[0].toPx(false, minSize), width / 2, height / 2); r1 = Math.min(border[0].toPx(false, minSize), width / 2, height / 2);
r2 = Math.min(border[1].toPx(false, minSize), width / 2, height / 2); r2 = Math.min(border[1].toPx(false, minSize), width / 2, height / 2);
@ -109,42 +111,30 @@ export default class Painter {
const lineWidth = borderWidth && borderWidth.toPx(false, minSize); const lineWidth = borderWidth && borderWidth.toPx(false, minSize);
this.ctx.lineWidth = lineWidth; this.ctx.lineWidth = lineWidth;
if (borderStyle === 'dashed') { if (borderStyle === 'dashed') {
this.ctx.setLineDash([(lineWidth * 4) / 3, (lineWidth * 4) / 3]); this.ctx.setLineDash([lineWidth * 4 / 3, lineWidth * 4 / 3]);
// this.ctx.lineDashOffset = 2 * lineWidth // this.ctx.lineDashOffset = 2 * lineWidth
} else if (borderStyle === 'dotted') { } else if (borderStyle === 'dotted') {
this.ctx.setLineDash([lineWidth, lineWidth]); this.ctx.setLineDash([lineWidth, lineWidth]);
} }
const notSolid = borderStyle !== 'solid'; const notSolid = borderStyle !== 'solid'
this.ctx.beginPath(); this.ctx.beginPath();
notSolid && r1 === 0 && this.ctx.moveTo(-width / 2 - lineWidth, -height / 2 - lineWidth / 2); // 顶边虚线规避重叠规则 notSolid && r1 === 0 && this.ctx.moveTo(-width / 2 - lineWidth, -height / 2 - lineWidth / 2) // 顶边虚线规避重叠规则
r1 !== 0 && this.ctx.arc(-width / 2 + r1, -height / 2 + r1, r1 + lineWidth / 2, 1 * Math.PI, 1.5 * Math.PI); //左上角圆弧 r1 !== 0 && this.ctx.arc(-width / 2 + r1, -height / 2 + r1, r1 + lineWidth / 2, 1 * Math.PI, 1.5 * Math.PI); //左上角圆弧
this.ctx.lineTo( this.ctx.lineTo(r2 === 0 ? notSolid ? width / 2 : width / 2 + lineWidth / 2 : width / 2 - r2, -height / 2 - lineWidth / 2); // 顶边线
r2 === 0 ? (notSolid ? width / 2 : width / 2 + lineWidth / 2) : width / 2 - r2,
-height / 2 - lineWidth / 2,
); // 顶边线
notSolid && r2 === 0 && this.ctx.moveTo(width / 2 + lineWidth / 2, -height / 2 - lineWidth); // 右边虚线规避重叠规则 notSolid && r2 === 0 && this.ctx.moveTo(width / 2 + lineWidth / 2, -height / 2 - lineWidth) // 右边虚线规避重叠规则
r2 !== 0 && this.ctx.arc(width / 2 - r2, -height / 2 + r2, r2 + lineWidth / 2, 1.5 * Math.PI, 2 * Math.PI); // 右上角圆弧 r2 !== 0 && this.ctx.arc(width / 2 - r2, -height / 2 + r2, r2 + lineWidth / 2, 1.5 * Math.PI, 2 * Math.PI); // 右上角圆弧
this.ctx.lineTo( this.ctx.lineTo(width / 2 + lineWidth / 2, r3 === 0 ? notSolid ? height / 2 : height / 2 + lineWidth / 2 : height / 2 - r3); // 右边线
width / 2 + lineWidth / 2,
r3 === 0 ? (notSolid ? height / 2 : height / 2 + lineWidth / 2) : height / 2 - r3,
); // 右边线
notSolid && r3 === 0 && this.ctx.moveTo(width / 2 + lineWidth, height / 2 + lineWidth / 2); // 底边虚线规避重叠规则 notSolid && r3 === 0 && this.ctx.moveTo(width / 2 + lineWidth, height / 2 + lineWidth / 2) // 底边虚线规避重叠规则
r3 !== 0 && this.ctx.arc(width / 2 - r3, height / 2 - r3, r3 + lineWidth / 2, 0, 0.5 * Math.PI); // 右下角圆弧 r3 !== 0 && this.ctx.arc(width / 2 - r3, height / 2 - r3, r3 + lineWidth / 2, 0, 0.5 * Math.PI); // 右下角圆弧
this.ctx.lineTo( this.ctx.lineTo(r4 === 0 ? notSolid ? -width / 2 : -width / 2 - lineWidth / 2 : -width / 2 + r4, height / 2 + lineWidth / 2); // 底边线
r4 === 0 ? (notSolid ? -width / 2 : -width / 2 - lineWidth / 2) : -width / 2 + r4,
height / 2 + lineWidth / 2,
); // 底边线
notSolid && r4 === 0 && this.ctx.moveTo(-width / 2 - lineWidth / 2, height / 2 + lineWidth); // 左边虚线规避重叠规则 notSolid && r4 === 0 && this.ctx.moveTo(-width / 2 - lineWidth / 2, height / 2 + lineWidth) // 左边虚线规避重叠规则
r4 !== 0 && this.ctx.arc(-width / 2 + r4, height / 2 - r4, r4 + lineWidth / 2, 0.5 * Math.PI, 1 * Math.PI); // 左下角圆弧 r4 !== 0 && this.ctx.arc(-width / 2 + r4, height / 2 - r4, r4 + lineWidth / 2, 0.5 * Math.PI, 1 * Math.PI); // 左下角圆弧
this.ctx.lineTo( this.ctx.lineTo(-width / 2 - lineWidth / 2, r1 === 0 ? notSolid ? -height / 2 : -height / 2 - lineWidth / 2 : -height / 2 + r1); // 左边线
-width / 2 - lineWidth / 2, notSolid && r1 === 0 && this.ctx.moveTo(-width / 2 - lineWidth, -height / 2 - lineWidth / 2) // 顶边虚线规避重叠规则
r1 === 0 ? (notSolid ? -height / 2 : -height / 2 - lineWidth / 2) : -height / 2 + r1,
); // 左边线
notSolid && r1 === 0 && this.ctx.moveTo(-width / 2 - lineWidth, -height / 2 - lineWidth / 2); // 顶边虚线规避重叠规则
if (!notSolid) { if (!notSolid) {
this.ctx.closePath(); this.ctx.closePath();
@ -164,11 +154,13 @@ export default class Painter {
borderRadius, borderRadius,
width, width,
height, height,
borderStyle, borderStyle
}); })
this.ctx.fill(); this.ctx.fill();
// 在 ios 的 6.6.6 版本上 clip 有 bug禁掉此类型上的 clip也就意味着在此版本微信的 ios 设备下无法使用 border 属性 // 在 ios 的 6.6.6 版本上 clip 有 bug禁掉此类型上的 clip也就意味着在此版本微信的 ios 设备下无法使用 border 属性
if (!(getApp().systemInfo && getApp().systemInfo.version <= '6.6.6' && getApp().systemInfo.platform === 'ios')) { if (!(getApp().systemInfo &&
getApp().systemInfo.version <= '6.6.6' &&
getApp().systemInfo.platform === 'ios')) {
this.ctx.clip(); this.ctx.clip();
} }
this.ctx.globalAlpha = 1; this.ctx.globalAlpha = 1;
@ -182,20 +174,25 @@ export default class Painter {
if (!view.css) { if (!view.css) {
return; return;
} }
const { borderRadius, borderWidth, borderColor, borderStyle } = view.css; const {
borderRadius,
borderWidth,
borderColor,
borderStyle
} = view.css;
if (!borderWidth) { if (!borderWidth) {
return; return;
} }
this.ctx.save(); this.ctx.save();
this._preProcess(view, true); this._preProcess(view, true);
this.ctx.strokeStyle = borderColor || 'black'; this.ctx.strokeStyle = (borderColor || 'black');
this._border({ this._border({
borderRadius, borderRadius,
width, width,
height, height,
borderWidth, borderWidth,
borderStyle, borderStyle
}); })
this.ctx.stroke(); this.ctx.stroke();
this.ctx.restore(); this.ctx.restore();
} }
@ -207,30 +204,26 @@ export default class Painter {
const paddings = this._doPaddings(view); const paddings = this._doPaddings(view);
switch (view.type) { switch (view.type) {
case 'text': { case 'text': {
const textArray = String(view.text).split('\n'); const textArray = view.text.split('\n');
// 处理多个连续的'\n' // 处理多个连续的'\n'
for (let i = 0; i < textArray.length; ++i) { for (let i = 0; i < textArray.length; ++i) {
if (textArray[i] === '') { if (textArray[i] === '') {
textArray[i] = ' '; textArray[i] = ' ';
} }
} }
const fontWeight = view.css.fontWeight || '400'; const fontWeight = view.css.fontWeight === 'bold' ? 'bold' : 'normal';
const textStyle = view.css.textStyle || 'normal'; const textStyle = view.css.textStyle === 'italic' ? 'italic' : 'normal';
if (!view.css.fontSize) { if (!view.css.fontSize) {
view.css.fontSize = '20rpx'; view.css.fontSize = '20rpx';
} }
this.ctx.font = `${textStyle} ${fontWeight} ${view.css.fontSize.toPx()}px "${ this.ctx.font = `${textStyle} ${fontWeight} ${view.css.fontSize.toPx()}px "${view.css.fontFamily || 'sans-serif'}"`;
view.css.fontFamily || 'sans-serif'
}"`;
// 计算行数 // 计算行数
let lines = 0; let lines = 0;
const linesArray = []; const linesArray = [];
for (let i = 0; i < textArray.length; ++i) { for (let i = 0; i < textArray.length; ++i) {
const textLength = this.ctx.measureText(textArray[i]).width; const textLength = this.ctx.measureText(textArray[i]).width;
const minWidth = view.css.fontSize.toPx() + paddings[1] + paddings[3]; const minWidth = view.css.fontSize.toPx() + paddings[1] + paddings[3];
let partWidth = view.css.width let partWidth = view.css.width ? view.css.width.toPx(false, this.style.width) - paddings[1] - paddings[3] : textLength;
? view.css.width.toPx(false, this.style.width) - paddings[1] - paddings[3]
: textLength;
if (partWidth < minWidth) { if (partWidth < minWidth) {
partWidth = minWidth; partWidth = minWidth;
} }
@ -268,10 +261,10 @@ export default class Painter {
height = Math.round(view.sHeight / ratio); height = Math.round(view.sHeight / ratio);
} else if (view.css.width === 'auto') { } else if (view.css.width === 'auto') {
height = view.css.height.toPx(false, this.style.height); height = view.css.height.toPx(false, this.style.height);
width = (view.sWidth / view.sHeight) * height; width = view.sWidth / view.sHeight * height;
} else if (view.css.height === 'auto') { } else if (view.css.height === 'auto') {
width = view.css.width.toPx(false, this.style.width); width = view.css.width.toPx(false, this.style.width);
height = (view.sHeight / view.sWidth) * width; height = view.sHeight / view.sWidth * width;
} else { } else {
width = view.css.width.toPx(false, this.style.width); width = view.css.width.toPx(false, this.style.width);
height = view.css.height.toPx(false, this.style.height); height = view.css.height.toPx(false, this.style.height);
@ -295,17 +288,14 @@ export default class Painter {
// 可以用数组方式,把文字长度计算进去 // 可以用数组方式,把文字长度计算进去
// [right, 文字id, 乘数(默认 1] // [right, 文字id, 乘数(默认 1]
const rights = view.css.right; const rights = view.css.right;
x = x = this.style.width - rights[0].toPx(true, this.style.width) - this.globalWidth[rights[1]] * (rights[2] || 1);
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) { } else if (view.css && view.css.left) {
if (typeof view.css.left === 'string') { if (typeof view.css.left === 'string') {
x = view.css.left.toPx(true, this.style.width); x = view.css.left.toPx(true, this.style.width);
} else { } else {
const lefts = view.css.left; const lefts = view.css.left;
x = lefts[0].toPx(true, this.style.width) + penCache.viewRect[lefts[1]].width * (lefts[2] || 1); x = lefts[0].toPx(true, this.style.width) + this.globalWidth[lefts[1]] * (lefts[2] || 1);
} }
} else { } else {
x = 0; x = 0;
@ -320,16 +310,16 @@ export default class Painter {
y = view.css.top.toPx(true, this.style.height); y = view.css.top.toPx(true, this.style.height);
} else { } else {
const tops = view.css.top; const tops = view.css.top;
y = tops[0].toPx(true, this.style.height) + penCache.viewRect[tops[1]].height * (tops[2] || 1); y = tops[0].toPx(true, this.style.height) + this.globalHeight[tops[1]] * (tops[2] || 1);
} }
} else { } else {
y = 0; y = 0
} }
} }
const angle = view.css && view.css.rotate ? this._getAngle(view.css.rotate) : 0; const angle = view.css && view.css.rotate ? this._getAngle(view.css.rotate) : 0;
// 当设置了 right 时,默认 align 用 right反之用 left // 当设置了 right 时,默认 align 用 right反之用 left
const align = view.css && view.css.align ? view.css.align : view.css && view.css.right ? 'right' : 'left'; const align = view.css && view.css.align ? view.css.align : (view.css && view.css.right ? 'right' : 'left');
const verticalAlign = view.css && view.css.verticalAlign ? view.css.verticalAlign : 'top'; const verticalAlign = view.css && view.css.verticalAlign ? view.css.verticalAlign : 'top';
// 记录绘制时的画布 // 记录绘制时的画布
let xa = 0; let xa = 0;
@ -360,17 +350,17 @@ export default class Painter {
// 记录该 view 的有效点击区域 // 记录该 view 的有效点击区域
// TODO ,旋转和裁剪的判断 // TODO ,旋转和裁剪的判断
// 记录在真实画布上的左侧 // 记录在真实画布上的左侧
let left = x; let left = x
if (align === 'center') { if (align === 'center') {
left = x - width / 2; left = x - width / 2
} else if (align === 'right') { } else if (align === 'right') {
left = x - width; left = x - width
} }
var top = y; var top = y;
if (verticalAlign === 'center') { if (verticalAlign === 'center') {
top = y - height / 2; top = y - height / 2;
} else if (verticalAlign === 'bottom') { } else if (verticalAlign === 'bottom') {
top = y - height; top = y - height
} }
if (view.rect) { if (view.rect) {
view.rect.left = left; view.rect.left = left;
@ -386,7 +376,7 @@ export default class Painter {
right: left + width, right: left + width,
bottom: top + height, bottom: top + height,
x: view.css && view.css.right ? x - width : x, x: view.css && view.css.right ? x - width : x,
y: y, y: y
}; };
} }
@ -404,14 +394,8 @@ export default class Painter {
} }
this._doShadow(view); this._doShadow(view);
if (view.id) { if (view.id) {
penCache.viewRect[view.id] = { this.globalWidth[view.id] = width;
width, this.globalHeight[view.id] = height;
height,
left: x,
top: y,
right: x + width,
bottom: y + height,
};
} }
return { return {
width: width, width: width,
@ -423,7 +407,9 @@ export default class Painter {
} }
_doPaddings(view) { _doPaddings(view) {
const { padding } = view.css ? view.css : {}; const {
padding,
} = view.css;
let pd = [0, 0, 0, 0]; let pd = [0, 0, 0, 0];
if (padding) { if (padding) {
const pdg = padding.split(/\s+/); const pdg = padding.split(/\s+/);
@ -456,14 +442,19 @@ export default class Painter {
// 画文字的背景图片 // 画文字的背景图片
_doBackground(view) { _doBackground(view) {
this.ctx.save(); this.ctx.save();
const { width: rawWidth, height: rawHeight } = this._preProcess(view, true); const {
width: rawWidth,
height: rawHeight,
} = this._preProcess(view, true);
const { background } = view.css; const {
background,
} = view.css;
let pd = this._doPaddings(view); let pd = this._doPaddings(view);
const width = rawWidth + pd[1] + pd[3]; const width = rawWidth + pd[1] + pd[3];
const height = rawHeight + pd[0] + pd[2]; const height = rawHeight + pd[0] + pd[2];
this._doClip(view.css.borderRadius, width, height, view.css.borderStyle); this._doClip(view.css.borderRadius, width, height, view.css.borderStyle)
if (GD.api.isGradient(background)) { if (GD.api.isGradient(background)) {
GD.api.doGradient(background, width, height, this.ctx); GD.api.doGradient(background, width, height, this.ctx);
} else { } else {
@ -476,7 +467,10 @@ export default class Painter {
_drawQRCode(view) { _drawQRCode(view) {
this.ctx.save(); this.ctx.save();
const { width, height } = this._preProcess(view); const {
width,
height,
} = this._preProcess(view);
QR.api.draw(view.content, this.ctx, -width / 2, -height / 2, width, height, view.css.background, view.css.color); QR.api.draw(view.content, this.ctx, -width / 2, -height / 2, width, height, view.css.background, view.css.color);
this.ctx.restore(); this.ctx.restore();
this._doBorder(view, width, height); this._doBorder(view, width, height);
@ -487,7 +481,10 @@ export default class Painter {
return; return;
} }
this.ctx.save(); this.ctx.save();
const { width, height } = this._preProcess(view); const {
width,
height,
} = this._preProcess(view);
// 获得缩放到图片大小级别的裁减框 // 获得缩放到图片大小级别的裁减框
let rWidth = view.sWidth; let rWidth = view.sWidth;
let rHeight = view.sHeight; let rHeight = view.sHeight;
@ -517,6 +514,7 @@ export default class Painter {
this._doBorder(view, width, height); this._doBorder(view, width, height);
} }
callbackInfo = {}
_fillAbsText(view) { _fillAbsText(view) {
if (!view.text) { if (!view.text) {
return; return;
@ -526,12 +524,23 @@ export default class Painter {
this._doBackground(view); this._doBackground(view);
} }
this.ctx.save(); this.ctx.save();
const { width, height, extra } = this._preProcess(view, view.css.background && view.css.borderRadius); const {
this.ctx.fillStyle = view.css.color || 'black'; width,
if (view.id && penCache.textLines[view.id]) { 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.globalWidth[view.id] = this.movingCache.globalWidth
this.ctx.textAlign = view.css.textAlign ? view.css.textAlign : 'left'; this.ctx.textAlign = view.css.textAlign ? view.css.textAlign : 'left';
for (const i of penCache.textLines[view.id]) { for (const i of this.movingCache.lineArray) {
const { measuredWith, text, x, y, textDecoration } = i; const {
measuredWith,
text,
x,
y,
textDecoration
} = i
if (view.css.textStyle === 'stroke') { if (view.css.textStyle === 'stroke') {
this.ctx.strokeText(text, x, y, measuredWith); this.ctx.strokeText(text, x, y, measuredWith);
} else { } else {
@ -549,15 +558,25 @@ export default class Painter {
} }
} }
} else { } else {
const { lines, lineHeight, textArray, linesArray } = extra; const {
lines,
lineHeight,
textArray,
linesArray,
} = extra;
// 如果设置了id则保留 text 的长度 // 如果设置了id则保留 text 的长度
if (view.id) { if (view.id) {
let textWidth = 0; let textWidth = 0;
for (let i = 0; i < textArray.length; ++i) { for (let i = 0; i < textArray.length; ++i) {
const _w = this.ctx.measureText(textArray[i]).width; const _w = this.ctx.measureText(textArray[i]).width
textWidth = _w > textWidth ? _w : textWidth; textWidth = _w > textWidth ? _w : textWidth;
} }
penCache.viewRect[view.id].width = width ? (textWidth < width ? textWidth : 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; let lineIndex = 0;
for (let j = 0; j < textArray.length; ++j) { for (let j = 0; j < textArray.length; ++j) {
@ -575,10 +594,7 @@ export default class Painter {
let measuredWith = this.ctx.measureText(text).width; let measuredWith = this.ctx.measureText(text).width;
// 如果测量大小小于width一个字符的大小则进行补齐如果测量大小超出 width则进行减除 // 如果测量大小小于width一个字符的大小则进行补齐如果测量大小超出 width则进行减除
// 如果已经到文本末尾,也不要进行该循环 // 如果已经到文本末尾,也不要进行该循环
while ( while ((start + alreadyCount <= textArray[j].length) && (width - measuredWith > view.css.fontSize.toPx() || measuredWith - width > view.css.fontSize.toPx())) {
start + alreadyCount <= textArray[j].length &&
(width - measuredWith > view.css.fontSize.toPx() || measuredWith - width > view.css.fontSize.toPx())
) {
if (measuredWith < width) { if (measuredWith < width) {
text = textArray[j].substr(start, ++alreadyCount); text = textArray[j].substr(start, ++alreadyCount);
} else { } else {
@ -591,7 +607,7 @@ export default class Painter {
} }
measuredWith = this.ctx.measureText(text).width; measuredWith = this.ctx.measureText(text).width;
} }
start += text.length; start += text.length
// 如果是最后一行了,发现还有未绘制完的内容,则加... // 如果是最后一行了,发现还有未绘制完的内容,则加...
if (lineIndex === lines - 1 && (j < textArray.length - 1 || start < textArray[j].length)) { if (lineIndex === lines - 1 && (j < textArray.length - 1 || start < textArray[j].length)) {
while (this.ctx.measureText(`${text}...`).width > width) { while (this.ctx.measureText(`${text}...`).width > width) {
@ -613,7 +629,7 @@ export default class Painter {
lineX = x - measuredWith / 2; lineX = x - measuredWith / 2;
break; break;
case 'right': case 'right':
x = width / 2; x = (width / 2);
lineX = x - measuredWith; lineX = x - measuredWith;
break; break;
default: default:
@ -621,10 +637,7 @@ export default class Painter {
lineX = x; lineX = x;
break; break;
} }
const y = -(height / 2) + (lineIndex === 0 ? view.css.fontSize.toPx() : (view.css.fontSize.toPx() + lineIndex * lineHeight));
const y =
-(height / 2) +
(lineIndex === 0 ? view.css.fontSize.toPx() : view.css.fontSize.toPx() + lineIndex * lineHeight);
lineIndex++; lineIndex++;
if (view.css.textStyle === 'stroke') { if (view.css.textStyle === 'stroke') {
this.ctx.strokeText(text, x, y, measuredWith); this.ctx.strokeText(text, x, y, measuredWith);
@ -641,47 +654,43 @@ export default class Painter {
this.ctx.lineTo(lineX + measuredWith, y); this.ctx.lineTo(lineX + measuredWith, y);
textDecoration = { textDecoration = {
moveTo: [lineX, y], moveTo: [lineX, y],
lineTo: [lineX + measuredWith, y], lineTo: [lineX + measuredWith, y]
}; }
} }
if (/\boverline\b/.test(view.css.textDecoration)) { if (/\boverline\b/.test(view.css.textDecoration)) {
this.ctx.moveTo(lineX, y - fontSize); this.ctx.moveTo(lineX, y - fontSize);
this.ctx.lineTo(lineX + measuredWith, y - fontSize); this.ctx.lineTo(lineX + measuredWith, y - fontSize);
textDecoration = { textDecoration = {
moveTo: [lineX, y - fontSize], moveTo: [lineX, y - fontSize],
lineTo: [lineX + measuredWith, y - fontSize], lineTo: [lineX + measuredWith, y - fontSize]
}; }
} }
if (/\bline-through\b/.test(view.css.textDecoration)) { if (/\bline-through\b/.test(view.css.textDecoration)) {
this.ctx.moveTo(lineX, y - fontSize / 3); this.ctx.moveTo(lineX, y - fontSize / 3);
this.ctx.lineTo(lineX + measuredWith, y - fontSize / 3); this.ctx.lineTo(lineX + measuredWith, y - fontSize / 3);
textDecoration = { textDecoration = {
moveTo: [lineX, y - fontSize / 3], moveTo: [lineX, y - fontSize / 3],
lineTo: [lineX + measuredWith, y - fontSize / 3], lineTo: [lineX + measuredWith, y - fontSize / 3]
}; }
} }
this.ctx.closePath(); this.ctx.closePath();
this.ctx.strokeStyle = view.css.color; this.ctx.strokeStyle = view.css.color;
this.ctx.stroke(); this.ctx.stroke();
} }
if (view.id) { if (!this.isMoving) {
penCache.textLines[view.id] this.callbackInfo.lineArray ? this.callbackInfo.lineArray.push({
? penCache.textLines[view.id].push({ text,
text, x,
x, y,
y, measuredWith,
measuredWith, textDecoration
textDecoration, }) : this.callbackInfo.lineArray = [{
}) text,
: (penCache.textLines[view.id] = [ x,
{ y,
text, measuredWith,
x, textDecoration
y, }]
measuredWith,
textDecoration,
},
]);
} }
} }
} }
@ -692,20 +701,27 @@ export default class Painter {
_drawAbsRect(view) { _drawAbsRect(view) {
this.ctx.save(); this.ctx.save();
const { width, height } = this._preProcess(view); const {
width,
height,
} = this._preProcess(view);
if (GD.api.isGradient(view.css.color)) { if (GD.api.isGradient(view.css.color)) {
GD.api.doGradient(view.css.color, width, height, this.ctx); GD.api.doGradient(view.css.color, width, height, this.ctx);
} else { } else {
this.ctx.fillStyle = view.css.color; this.ctx.fillStyle = view.css.color;
} }
const { borderRadius, borderStyle, borderWidth } = view.css; const {
borderRadius,
borderStyle,
borderWidth
} = view.css
this._border({ this._border({
borderRadius, borderRadius,
width, width,
height, height,
borderWidth, borderWidth,
borderStyle, borderStyle
}); })
this.ctx.fill(); this.ctx.fill();
this.ctx.restore(); this.ctx.restore();
this._doBorder(view, width, height); this._doBorder(view, width, height);
@ -719,7 +735,7 @@ export default class Painter {
} }
const box = view.css.shadow.replace(/,\s+/g, ',').split(/\s+/); const box = view.css.shadow.replace(/,\s+/g, ',').split(/\s+/);
if (box.length > 4) { if (box.length > 4) {
console.error("shadow don't spread option"); console.error('shadow don\'t spread option');
return; return;
} }
this.ctx.shadowOffsetX = parseInt(box[0], 10); this.ctx.shadowOffsetX = parseInt(box[0], 10);
@ -729,6 +745,6 @@ export default class Painter {
} }
_getAngle(angle) { _getAngle(angle) {
return (Number(angle) * Math.PI) / 180; return Number(angle) * Math.PI / 180;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,31 @@
<view style='position: relative;{{customStyle}};{{painterStyle}}'> <view style='position: relative;{{customStyle}};{{painterStyle}}'>
<block wx:if="{{!use2D}}"> <block wx:if="{{!use2D}}">
<canvas canvas-id="photo" style="{{photoStyle}};position: absolute; left: -9999px; top: -9999rpx;" /> <canvas canvas-id="photo" style="{{photoStyle}};position: absolute; left: -9999px; top: -9999rpx;" />
<block wx:if="{{dancePalette}}"> <canvas canvas-id="bottom" style="{{painterStyle}};position: absolute;" />
<canvas canvas-id="bottom" style="{{painterStyle}};position: absolute;" /> <canvas canvas-id="k-canvas" style="{{painterStyle}};position: absolute;" />
<canvas canvas-id="k-canvas" style="{{painterStyle}};position: absolute;" /> <canvas canvas-id="top" style="{{painterStyle}};position: absolute;" />
<canvas canvas-id="top" style="{{painterStyle}};position: absolute;" /> <canvas
<canvas canvas-id="front"
canvas-id="front" style="{{painterStyle}};position: absolute;"
style="{{painterStyle}};position: absolute;" bindtouchstart="onTouchStart"
bindtouchstart="onTouchStart" bindtouchmove="onTouchMove"
bindtouchmove="onTouchMove" bindtouchend="onTouchEnd"
bindtouchend="onTouchEnd" bindtouchcancel="onTouchCancel"
bindtouchcancel="onTouchCancel" disable-scroll="{{true}}" />
disable-scroll="{{true}}" />
</block>
</block> </block>
<block wx:if="{{use2D}}"> <block wx:if="{{use2D}}">
<canvas type="2d" id="photo" style="{{photoStyle}};" /> <canvas type="2d" id="photo" style="{{photoStyle}};" />
<!-- <canvas type="2d" id="bottom" style="{{painterStyle}};position: absolute;" />
<canvas type="2d" id="k-canvas" style="{{painterStyle}};position: absolute;" />
<canvas type="2d" id="top" style="{{painterStyle}};position: absolute;" />
<canvas
type="2d"
id="front"
style="{{painterStyle}};position: absolute;"
bindtouchstart="onTouchStart"
bindtouchmove="onTouchMove"
bindtouchend="onTouchEnd"
bindtouchcancel="onTouchCancel"
disable-scroll="{{true}}" /> -->
</block> </block>
</view> </view>