From 14b8436ed3667bea4cbb249d83c154e6917f14af Mon Sep 17 00:00:00 2001 From: chenshenhai Date: Sun, 5 Nov 2023 21:09:10 +0800 Subject: [PATCH] feat: add config and dash effect --- packages/renderer/src/draw/base.ts | 33 +++++++++++++++++++------- packages/renderer/src/draw/elements.ts | 15 ++++++++++-- packages/types/src/index.ts | 1 + packages/types/src/lib/config.ts | 3 +++ packages/util/src/index.ts | 1 + packages/util/src/lib/config.ts | 17 +++++++++++++ packages/util/src/lib/context2d.ts | 3 ++- 7 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 packages/types/src/lib/config.ts create mode 100644 packages/util/src/lib/config.ts diff --git a/packages/renderer/src/draw/base.ts b/packages/renderer/src/draw/base.ts index 8d7d74783..06f225db8 100644 --- a/packages/renderer/src/draw/base.ts +++ b/packages/renderer/src/draw/base.ts @@ -1,7 +1,9 @@ import { ViewContext2D, Element, ElementType, ElementSize, ViewScaleInfo, ViewSizeInfo, TransformAction } from '@idraw/types'; -import { istype, isColorStr, generateSVGPath, rotateElement, is } from '@idraw/util'; +import { istype, isColorStr, generateSVGPath, rotateElement, is, getDefaultElementDetailConfig } from '@idraw/util'; import { createColorStyle } from './color'; +const defaultElemConfig = getDefaultElementDetailConfig(); + export function drawBox( ctx: ViewContext2D, viewElem: Element, @@ -66,7 +68,6 @@ function drawClipPath( ctx.scale(totalScale * scaleW, totalScale * scaleH); const pathStr = generateSVGPath(clipPath.commands || []); const path2d = new Path2D(pathStr); - // ctx.fillStyle = clipPath.fill || '#FFFFFF'; ctx.clip(path2d); ctx.translate(0 - (internalX as number), 0 - (internalY as number)); ctx.setTransform(1, 0, 0, 1, 0, 0); @@ -89,7 +90,7 @@ function drawBoxBackground( const { pattern, viewScaleInfo } = opts; const { scale } = viewScaleInfo; let transform: TransformAction[] = []; - let { borderRadius, boxSizing, borderWidth } = viewElem.detail; + let { borderRadius, boxSizing = defaultElemConfig.boxSizing, borderWidth } = viewElem.detail; if (typeof borderWidth !== 'number') { // TODO: If borderWidth is an array, borderRadius will not take effect and will become 0. borderRadius = 0; @@ -189,6 +190,9 @@ function drawBoxBackground( } function drawBoxBorder(ctx: ViewContext2D, viewElem: Element, opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): void { + if (viewElem.detail.borderWidth === 0) { + return; + } if (!isColorStr(viewElem.detail.borderColor)) { return; } @@ -199,11 +203,11 @@ function drawBoxBorder(ctx: ViewContext2D, viewElem: Element, opts: } const { viewScaleInfo } = opts; const { scale } = viewScaleInfo; - let borderColor = '#000000'; + let borderColor = defaultElemConfig.borderColor; if (isColorStr(viewElem.detail.borderColor) === true) { borderColor = viewElem.detail.borderColor as string; } - const { borderWidth, borderRadius, borderDash, boxSizing } = viewElem.detail; + const { borderWidth, borderRadius, borderDash, boxSizing = defaultElemConfig.boxSizing } = viewElem.detail; let bw: number = 0; if (typeof borderWidth === 'number') { bw = borderWidth || 1; @@ -217,7 +221,10 @@ function drawBoxBorder(ctx: ViewContext2D, viewElem: Element, opts: radiusList = [borderRadius[0] * scale, borderRadius[1] * scale, borderRadius[2] * scale, borderRadius[3] * scale]; } ctx.strokeStyle = borderColor; - ctx.setLineDash(borderDash || []); + let viewBorderDash: number[] = []; + if (Array.isArray(borderDash) && borderDash.length > 0) { + viewBorderDash = borderDash.map((num) => Math.ceil(num * scale)); + } let borderTop = 0; let borderRight = 0; @@ -229,7 +236,9 @@ function drawBoxBorder(ctx: ViewContext2D, viewElem: Element, opts: borderBottom = (borderWidth[2] || 0) * scale; borderLeft = (borderWidth[3] || 0) * scale; } + if (borderLeft || borderRight || borderTop || borderBottom) { + ctx.lineCap = 'butt'; let { x, y, w, h } = viewElem; if (boxSizing === 'border-box') { x = x + borderLeft / 2; @@ -306,9 +315,14 @@ function drawBoxBorder(ctx: ViewContext2D, viewElem: Element, opts: // if (r < w / 2 && r < h / 2) { // r = r + bw / 2; // } - ctx.beginPath(); - ctx.lineCap = 'square'; + if (viewBorderDash.length > 0) { + ctx.lineCap = 'butt'; + } else { + ctx.lineCap = 'square'; + } + ctx.setLineDash(viewBorderDash); ctx.lineWidth = bw; + ctx.beginPath(); ctx.moveTo(x + radiusList[0], y); ctx.arcTo(x + w, y, x + w, y + h, radiusList[1]); ctx.arcTo(x + w, y + h, x, y + h, radiusList[2]); @@ -318,6 +332,7 @@ function drawBoxBorder(ctx: ViewContext2D, viewElem: Element, opts: ctx.stroke(); ctx.globalAlpha = 1; } + ctx.setLineDash([]); } export function drawBoxShadow( @@ -330,7 +345,7 @@ export function drawBoxShadow( const { shadowColor, shadowOffsetX, shadowOffsetY, shadowBlur } = detail; if (is.number(shadowBlur)) { ctx.save(); - ctx.shadowColor = shadowColor || '#000000'; + ctx.shadowColor = shadowColor || defaultElemConfig.shadowColor; ctx.shadowOffsetX = (shadowOffsetX || 0) * viewScaleInfo.scale; ctx.shadowOffsetY = (shadowOffsetY || 0) * viewScaleInfo.scale; ctx.shadowBlur = (shadowBlur || 0) * viewScaleInfo.scale; diff --git a/packages/renderer/src/draw/elements.ts b/packages/renderer/src/draw/elements.ts index 153243a8e..66cc48a39 100644 --- a/packages/renderer/src/draw/elements.ts +++ b/packages/renderer/src/draw/elements.ts @@ -1,11 +1,22 @@ import type { Data, RendererDrawElementOptions, ViewContext2D } from '@idraw/types'; - +import { getDefaultElementDetailConfig } from '@idraw/util'; import { drawElement } from './group'; +const defaultDetail = getDefaultElementDetailConfig(); + export function drawElementList(ctx: ViewContext2D, data: Data, opts: RendererDrawElementOptions) { const { elements = [] } = data; for (let i = 0; i < elements.length; i++) { - const elem = elements[i]; + const element = elements[i]; + const elem = { + ...element, + ...{ + detail: { + ...defaultDetail, + ...element?.detail + } + } + }; // TODO if (!opts.calculator.isElementInView(elem, opts.viewScaleInfo, opts.viewSizeInfo)) { continue; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index cf6f3fa8c..a8e458c79 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -15,3 +15,4 @@ export * from './lib/context2d'; export * from './lib/controller'; export * from './lib/html'; export * from './lib/svg-path'; +export * from './lib/config'; diff --git a/packages/types/src/lib/config.ts b/packages/types/src/lib/config.ts new file mode 100644 index 000000000..352da87f7 --- /dev/null +++ b/packages/types/src/lib/config.ts @@ -0,0 +1,3 @@ +import type { ElementBaseDetail } from './element'; + +export type DefaultElementDetailConfig = Required>; diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index a790a5500..4dbe4ca62 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -55,3 +55,4 @@ export { generateHTML, parseHTML } from './lib/html'; export { compressImage } from './lib/image'; export { formatNumber } from './lib/number'; export { matrixToAngle, matrixToRadian } from './lib/matrix'; +export { getDefaultElementDetailConfig } from './lib/config'; diff --git a/packages/util/src/lib/config.ts b/packages/util/src/lib/config.ts new file mode 100644 index 000000000..46a1a6f43 --- /dev/null +++ b/packages/util/src/lib/config.ts @@ -0,0 +1,17 @@ +import type { DefaultElementDetailConfig } from '@idraw/types'; + +export function getDefaultElementDetailConfig(): DefaultElementDetailConfig { + const config: DefaultElementDetailConfig = { + boxSizing: 'border-box', + borderWidth: 0, + borderColor: '#000000', + shadowColor: '#000000', + borderRadius: 0, + borderDash: [], + shadowOffsetX: 0, + shadowOffsetY: 0, + shadowBlur: 0, + opacity: 1 + }; + return config; +} diff --git a/packages/util/src/lib/context2d.ts b/packages/util/src/lib/context2d.ts index a1b002bcc..be947289a 100644 --- a/packages/util/src/lib/context2d.ts +++ b/packages/util/src/lib/context2d.ts @@ -181,7 +181,8 @@ export class Context2D implements ViewContext2D { } setLineDash(nums: number[]) { - return this._ctx.setLineDash(nums.map((n) => this.$doPixelRatio(n))); + const dash = nums.map((n) => this.$doPixelRatio(n)); + return this._ctx.setLineDash(dash); } stroke(path?: Path2D) {