feat: add config and dash effect

This commit is contained in:
chenshenhai 2023-11-05 21:09:10 +08:00
parent 127d60088d
commit 14b8436ed3
7 changed files with 61 additions and 12 deletions

View file

@ -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<ElementType>,
@ -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<ElementType>, 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<ElementType>, 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<ElementType>, 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<ElementType>, 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<ElementType>, 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<ElementType>, 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;

View file

@ -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;

View file

@ -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';

View file

@ -0,0 +1,3 @@
import type { ElementBaseDetail } from './element';
export type DefaultElementDetailConfig = Required<Omit<ElementBaseDetail, 'clipPath' | 'background'>>;

View file

@ -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';

View file

@ -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;
}

View file

@ -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) {