From 06aaead258ace437c7122ea569e1f8817412979f Mon Sep 17 00:00:00 2001 From: 0JARVIS0 <709406687@qq.com> Date: Tue, 19 Nov 2019 19:22:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=BE=B9=E6=A1=86dashed?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E8=87=AA=E5=AE=9A=E4=B9=89=E8=99=9A=E7=BA=BF?= =?UTF-8?q?=E8=A7=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pen.js | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/lib/pen.js b/lib/pen.js index 857e7e7..657eb92 100644 --- a/lib/pen.js +++ b/lib/pen.js @@ -81,7 +81,7 @@ export default class Painter { } } - _doRadius(borderRadius, width, height, borderWidth = '0') { + _border({ borderRadius = '0', width, height, borderWidth = '0', borderStyle = 'solid' }) { let r1 = 0, r2 = 0, r3 = 0, @@ -99,34 +99,48 @@ export default class Painter { } const lineWidth = borderWidth === '0' ? 0 : borderWidth.toPx(); this.ctx.lineWidth = lineWidth; - const points = [ - [r2 === 0 ? width / 2 + lineWidth / 2 : width / 2 - r2, -height / 2 - lineWidth / 2], - [width / 2 + lineWidth / 2, r3 === 0 ? height / 2 + lineWidth / 2 : height / 2 - r3], - [r4 === 0 ? -width / 2 - lineWidth / 2 : -width / 2 + r4, height / 2 + lineWidth / 2], - [-width / 2 - lineWidth / 2, r1 === 0 ? -height / 2 - lineWidth / 2 : -height / 2 + r1] - ] + if (borderStyle === 'dashed') { + this.ctx.setLineDash([2 * lineWidth, 2 * lineWidth]); + } else if (borderStyle === 'dotted') { + this.ctx.setLineDash([lineWidth, lineWidth]); + } else if (borderStyle !== 'solid') { + const segments = borderStyle.split(/\s+/) + if (segments.length === 2) { + this.ctx.setLineDash([segments[0].toPx(), segments[1].toPx()]) + } + } + const notSolid = borderStyle !== 'solid' this.ctx.beginPath(); + + notSolid && r1 === 0 && this.ctx.moveTo(-width / 2 - lineWidth / 2, -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); //左上角圆弧 - this.ctx.lineTo(...points[0]); + this.ctx.lineTo(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 / 2) // 右边虚线规避重叠规则 r2 !== 0 && this.ctx.arc(width / 2 - r2, -height / 2 + r2, r2 + lineWidth / 2, 1.5 * Math.PI, 2 * Math.PI); // 右上角圆弧 - this.ctx.lineTo(...points[1]); + this.ctx.lineTo(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 / 2, height / 2 + lineWidth / 2) // 底边虚线规避重叠规则 r3 !== 0 && this.ctx.arc(width / 2 - r3, height / 2 - r3, r3 + lineWidth / 2, 0, 0.5 * Math.PI); // 右下角圆弧 - this.ctx.lineTo(...points[2]); + this.ctx.lineTo(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 / 2) // 左边虚线规避重叠规则 r4 !== 0 && this.ctx.arc(-width / 2 + r4, height / 2 - r4, r4 + lineWidth / 2, 0.5 * Math.PI, 1 * Math.PI); // 左下角圆弧 - this.ctx.lineTo(...points[3]); + this.ctx.lineTo(-width / 2 - lineWidth / 2, r1 === 0 ? notSolid ? -height / 2 : -height / 2 - lineWidth / 2 : -height / 2 + r1); // 左边线 + this.ctx.closePath(); } /** * 根据 borderRadius 进行裁减 */ - _doClip(borderRadius, width, height) { + _doClip(borderRadius, width, height, borderStyle) { if (borderRadius && width && height) { // 防止在某些机型上周边有黑框现象,此处如果直接设置 fillStyle 为透明,在 Android 机型上会导致被裁减的图片也变为透明, iOS 和 IDE 上不会 // globalAlpha 在 1.9.90 起支持,低版本下无效,但把 fillStyle 设为了 white,相对默认的 black 要好点 this.ctx.globalAlpha = 0; this.ctx.fillStyle = 'white'; - this._doRadius(borderRadius, width, height) + this._border({ borderRadius, width, height, borderStyle }) this.ctx.fill(); // 在 ios 的 6.6.6 版本上 clip 有 bug,禁掉此类型上的 clip,也就意味着,在此版本微信的 ios 设备下无法使用 border 属性 if (!(getApp().systemInfo && @@ -149,6 +163,7 @@ export default class Painter { borderRadius, borderWidth, borderColor, + borderStyle } = view.css; if (!borderWidth) { return; @@ -156,7 +171,7 @@ export default class Painter { this.ctx.save(); this._preProcess(view, true); this.ctx.strokeStyle = (borderColor || 'black'); - this._doRadius(borderRadius, width, height, borderWidth) + this._border({ borderRadius, width, height, borderWidth, borderStyle }) this.ctx.stroke(); this.ctx.restore(); } @@ -317,7 +332,7 @@ export default class Painter { this.ctx.rotate(angle); if (!notClip && view.css && view.css.borderRadius && view.type !== 'rect') { - this._doClip(view.css.borderRadius, width, height); + this._doClip(view.css.borderRadius, width, height, view.css.borderStyle); } this._doShadow(view); if (view.id) { @@ -381,7 +396,7 @@ export default class Painter { const width = rawWidth + pd[1] + pd[3]; const height = rawHeight + pd[0] + pd[2]; - this._doClip(view.css.borderRadius, width, height) + this._doClip(view.css.borderRadius, width, height, view.css.borderStyle) if (GD.api.isGradient(background)) { GD.api.doGradient(background, width, height, this.ctx); } else { @@ -609,8 +624,8 @@ export default class Painter { } else { this.ctx.fillStyle = view.css.color; } - const borderRadius = view.css.borderRadius - this._doRadius(borderRadius, width, height) + const { borderRadius, borderStyle, borderWidth } = view.css + this._border({ borderRadius, width, height, borderWidth, borderStyle }) this.ctx.fill(); this.ctx.restore(); this._doBorder(view, width, height);