From 3fe12602818369f3c3fb7d824909f384b16a3086 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Wed, 11 Aug 2021 08:48:59 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat(dot-pattern):=20=E4=BC=98=E5=8C=96=20d?= =?UTF-8?q?ot=20pattern,=20=E4=BF=AE=E5=A4=8D=20stagger=20=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/pattern/dot.ts | 119 ++++++++++++++++++++----------------- src/utils/pattern/index.ts | 3 +- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/src/utils/pattern/dot.ts b/src/utils/pattern/dot.ts index 3e01186e6f..73afee9211 100644 --- a/src/utils/pattern/dot.ts +++ b/src/utils/pattern/dot.ts @@ -1,8 +1,47 @@ import { DotPatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; -export function createDotPattern(cfg: DotPatternCfg): HTMLCanvasElement { - const dotOptions = deepAssign( +function drawRect(options: DotPatternCfg, canvas: HTMLCanvasElement, unitSize: number) { + const { backgroundColor, opacity } = options; + const ctx = canvas.getContext('2d'); + + canvas.width = unitSize; + canvas.height = unitSize; + ctx.globalAlpha = opacity; + ctx.fillStyle = backgroundColor; + + ctx.beginPath(); + ctx.fillRect(0, 0, unitSize, unitSize); + ctx.closePath(); +} + +function drawDot(options: DotPatternCfg, canvas: HTMLCanvasElement, x: number, y: number) { + const { radius, fill, lineWidth, stroke, fillOpacity } = options; + const ctx = canvas.getContext('2d'); + + ctx.beginPath(); + ctx.globalAlpha = fillOpacity; + ctx.fillStyle = fill; + ctx.strokeStyle = stroke; + ctx.lineWidth = lineWidth; + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.fill(); + if (lineWidth) { + ctx.stroke(); + } + ctx.closePath(); +} + +/** + * 创建 dot pattern,返回 HTMLCanvasElement + * + * @param cfg + * @returns HTMLCanvasElement + */ +export function createDotPattern(cfg: DotPatternCfg): CanvasPattern { + const pixelRatio = typeof window === 'object' && window.devicePixelRatio ? window.devicePixelRatio : 1; + + const dotCfg = deepAssign( {}, { radius: 4, @@ -18,62 +57,36 @@ export function createDotPattern(cfg: DotPatternCfg): HTMLCanvasElement { cfg ); - const canvas = document.createElement('canvas'); - const { radius, padding, isStagger } = dotOptions; - const unitSize = isStagger ? (radius + padding) * 4 : (radius + padding) * 2; - const dots = isStagger - ? [ - [(unitSize / 4) * 1, (unitSize / 4) * 1], - [(unitSize / 4) * 3, (unitSize / 4) * 1], - [(unitSize / 4) * 0, (unitSize / 4) * 3], - [(unitSize / 4) * 2, (unitSize / 4) * 3], - [(unitSize / 4) * 4, (unitSize / 4) * 3], - ] - : [[unitSize / 2, unitSize / 2]]; - - // 后续再行测试 - // const dpr = window.devicePixelRatio; - // const logicalWidth = size / 2 - // const logicalHeight = size / 2 - // canvas.width = logicalWidth * dpr; - // canvas.height = logicalHeight * dpr; - // canvas.style.width = logicalWidth + 'px'; - // canvas.style.height = logicalHeight + 'px'; - // ctx.scale(dpr, dpr); - - // console.info('dpr', dpr) + /** 大小 */ + const { radius, padding, isStagger } = dotCfg; + const dots = [[padding / 2 + radius, padding / 2 + radius]]; - drawBackground(dotOptions, canvas, unitSize); - // 绘制图案 - for (const [x, y] of dots) { - drawDot(dotOptions, canvas, x, y); + let size = radius * 2 + padding; + // 如果交错, size 放大两倍 交错绘制 dot + if (isStagger) { + dots.push([size + radius, size + radius]); + size *= 2; } - return canvas; -} - -function drawBackground(options: DotPatternCfg, canvas: HTMLCanvasElement, unitSize: number) { - const { backgroundColor, opacity } = options; + const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); - canvas.width = unitSize; - canvas.height = unitSize; - ctx.globalAlpha = opacity; - ctx.globalAlpha = opacity; - ctx.fillStyle = backgroundColor; - ctx.fillRect(0, 0, unitSize, unitSize); -} + // ~~~ 后续再行测试 ~~~ + const logicalWidth = size; + const logicalHeight = size; + // 画布尺寸 + canvas.width = logicalWidth * pixelRatio; + canvas.height = logicalHeight * pixelRatio; + // 显示尺寸 + canvas.style.width = `${logicalWidth}px`; + canvas.style.height = `${logicalHeight}px`; + // ~~~ 后续再行测试 ~~~ -function drawDot(options: DotPatternCfg, canvas: HTMLCanvasElement, x: number, y: number) { - const { radius, fill, lineWidth, stroke, fillOpacity } = options; - const ctx = canvas.getContext('2d'); + drawRect(dotCfg, canvas, size); + // 绘制图案 + for (const [x, y] of dots) { + drawDot(dotCfg, canvas, x, y); + } - ctx.beginPath(); - ctx.globalAlpha = fillOpacity; - ctx.fillStyle = fill; - ctx.strokeStyle = stroke; - ctx.lineWidth = lineWidth; - ctx.arc(x, y, radius, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); + return ctx.createPattern(canvas, cfg.mode || 'repeat'); } diff --git a/src/utils/pattern/index.ts b/src/utils/pattern/index.ts index 339f30816e..73678e4173 100644 --- a/src/utils/pattern/index.ts +++ b/src/utils/pattern/index.ts @@ -32,8 +32,7 @@ export function getCanvasPattern(options: PatternOption): CanvasPattern { switch (type) { case 'dot': - patternCanvas = createDotPattern(cfg); - break; + return createDotPattern(cfg); case 'line': patternCanvas = createLinePattern(cfg); break; From 37943391bf16146bc45f37fbb2be589818e503a9 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Wed, 11 Aug 2021 09:00:14 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat(square-pattern):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20square=20pattern,=20=E4=BF=AE=E5=A4=8D=20stagger=20=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/pattern/dot.ts | 2 +- src/utils/pattern/index.ts | 3 +- src/utils/pattern/square.ts | 88 ++++++++++++++++--------------------- 3 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/utils/pattern/dot.ts b/src/utils/pattern/dot.ts index 73afee9211..4c4226c596 100644 --- a/src/utils/pattern/dot.ts +++ b/src/utils/pattern/dot.ts @@ -1,7 +1,7 @@ import { DotPatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; -function drawRect(options: DotPatternCfg, canvas: HTMLCanvasElement, unitSize: number) { +export function drawRect(options: DotPatternCfg, canvas: HTMLCanvasElement, unitSize: number) { const { backgroundColor, opacity } = options; const ctx = canvas.getContext('2d'); diff --git a/src/utils/pattern/index.ts b/src/utils/pattern/index.ts index 73678e4173..0145f601e8 100644 --- a/src/utils/pattern/index.ts +++ b/src/utils/pattern/index.ts @@ -37,8 +37,7 @@ export function getCanvasPattern(options: PatternOption): CanvasPattern { patternCanvas = createLinePattern(cfg); break; case 'square': - patternCanvas = createSquarePattern(cfg); - break; + return createSquarePattern(cfg); default: return; } diff --git a/src/utils/pattern/square.ts b/src/utils/pattern/square.ts index e3eaa8dba8..f655e04bcc 100644 --- a/src/utils/pattern/square.ts +++ b/src/utils/pattern/square.ts @@ -1,17 +1,38 @@ import { SquarePatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; +import { drawRect } from './dot'; -export function createSquarePattern(cfg: SquarePatternCfg): HTMLCanvasElement { - const squareOptions = deepAssign( +function drawSquare(options: SquarePatternCfg, canvas: HTMLCanvasElement, x: number, y: number) { + const { stroke, size, fill, lineWidth, fillOpacity, rotation } = options; + const ctx = canvas.getContext('2d'); + const radians = (rotation % 360) * (Math.PI / 180); + + ctx.globalAlpha = fillOpacity; + ctx.strokeStyle = stroke; + ctx.lineWidth = lineWidth; + ctx.fillStyle = fill; + ctx.fillRect(x, y, size, size); + + // todo 控制旋转 + // ctx.translate(x, y); + // ctx.rotate(radians); + // ctx.translate(-x, -y); + // ctx.strokeRect(x - size / 2, y - size / 2, size, size); + // // reset to identity matrix 重制成单位矩阵 + // ctx.setTransform(1, 0, 0, 1, 0, 0); +} + +export function createSquarePattern(cfg: SquarePatternCfg): CanvasPattern { + const squareCfg = deepAssign( {}, { - size: 7, + size: 4, + padding: 4, backgroundColor: 'transparent', opacity: 1, - rotation: 45, + rotation: 0, fill: '#FFF', fillOpacity: 1, - padding: 10, stroke: 'transparent', lineWidth: 0, isStagger: true, @@ -20,52 +41,21 @@ export function createSquarePattern(cfg: SquarePatternCfg): HTMLCanvasElement { ); const canvas = document.createElement('canvas'); - const { size, padding, isStagger } = squareOptions; - // 计算 贴图单元的大小 - const unitSize = isStagger ? (size + padding * 2) * 2 : size + padding * 2; - const squares = isStagger - ? [ - [(unitSize / 4) * 1, (unitSize / 4) * 1], - [(unitSize / 4) * 3, (unitSize / 4) * 1], - [(unitSize / 4) * 0, (unitSize / 4) * 3], - [(unitSize / 4) * 2, (unitSize / 4) * 3], - [(unitSize / 4) * 4, (unitSize / 4) * 3], - ] - : [[unitSize / 2, unitSize / 2]]; - - drawBackground(squareOptions, canvas, unitSize); - for (const [x, y] of squares) { - drawSquare(squareOptions, canvas, x, y); - } - return canvas; -} - -function drawBackground(options: SquarePatternCfg, canvas: HTMLCanvasElement, unitSize: number) { - const { backgroundColor, opacity } = options; const ctx = canvas.getContext('2d'); - canvas.width = unitSize; - canvas.height = unitSize; - ctx.globalAlpha = opacity; - ctx.fillStyle = backgroundColor; - ctx.fillRect(0, 0, unitSize, unitSize); -} + const { size, padding, isStagger } = squareCfg; + const squares = [[padding / 2, padding / 2]]; -function drawSquare(options: SquarePatternCfg, canvas: HTMLCanvasElement, x: number, y: number) { - const { stroke, size, fill, lineWidth, fillOpacity } = options; - const ctx = canvas.getContext('2d'); - const rotation = options.rotation % 360; - const radians = rotation * (Math.PI / 180); + let unitSize = size + padding; + // 如果交错, size 放大两倍 交错绘制 dot + if (isStagger) { + squares.push([unitSize + padding / 2, unitSize + padding / 2]); + unitSize *= 2; + } - ctx.globalAlpha = fillOpacity; - ctx.strokeStyle = stroke; - ctx.lineWidth = lineWidth; - ctx.translate(x, y); - ctx.rotate(radians); - ctx.translate(-x, -y); - ctx.strokeRect(x - size / 2, y - size / 2, size, size); - ctx.fillStyle = fill; - ctx.fillRect(x - size / 2, y - size / 2, size, size); - // reset to identity matrix 重制成单位矩阵 - ctx.setTransform(1, 0, 0, 1, 0, 0); + drawRect(squareCfg, canvas, unitSize); + for (const [x, y] of squares) { + drawSquare(squareCfg, canvas, x, y); + } + return ctx.createPattern(canvas, cfg.mode || 'repeat'); } From 75e5d08e3cd83a7fd0272d58f9af9dbfeaea4850 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Wed, 11 Aug 2021 09:06:20 +0800 Subject: [PATCH 3/5] =?UTF-8?q?refactor(pattern):=20=E4=BC=98=E5=8C=96=20l?= =?UTF-8?q?ine=20pattern=20&=20=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/pattern/base.ts | 30 --------------------- src/utils/pattern/dot.ts | 11 +++++--- src/utils/pattern/index.ts | 10 +------ src/utils/pattern/line.ts | 53 ++++++++++++++++---------------------- 4 files changed, 30 insertions(+), 74 deletions(-) delete mode 100644 src/utils/pattern/base.ts diff --git a/src/utils/pattern/base.ts b/src/utils/pattern/base.ts deleted file mode 100644 index 317a54baa2..0000000000 --- a/src/utils/pattern/base.ts +++ /dev/null @@ -1,30 +0,0 @@ -export type PatternCfg = { - opacity: number; // 整个贴图透明 - stroke?: string; - lineWidth?: number; - backgroundColor?: string | 'inherit'; - mode?: 'repeat' | 'no-repeat' | 'repeat-x' | 'repeat-y'; -}; - -export abstract class Pattern { - public options: O; - public pattern: CanvasPattern; - public patternCanvas: HTMLCanvasElement; - public patternContext: CanvasRenderingContext2D; - - constructor(options?: O) { - this.options = this.initOptions(options); - this.patternCanvas = document.createElement('canvas'); - this.patternContext = this.patternCanvas.getContext('2d'); - - this.init(); - } - - protected abstract init(); - - public getCanvas() { - return this.patternCanvas; - } - - protected abstract initOptions(options: O); -} diff --git a/src/utils/pattern/dot.ts b/src/utils/pattern/dot.ts index 4c4226c596..b05a80c50c 100644 --- a/src/utils/pattern/dot.ts +++ b/src/utils/pattern/dot.ts @@ -1,17 +1,20 @@ import { DotPatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; -export function drawRect(options: DotPatternCfg, canvas: HTMLCanvasElement, unitSize: number) { +export function drawRect(options: DotPatternCfg, canvas: HTMLCanvasElement, width: number, height?: number) { const { backgroundColor, opacity } = options; const ctx = canvas.getContext('2d'); - canvas.width = unitSize; - canvas.height = unitSize; + const w = width; + const h = height || width; + + canvas.width = w; + canvas.height = h; ctx.globalAlpha = opacity; ctx.fillStyle = backgroundColor; ctx.beginPath(); - ctx.fillRect(0, 0, unitSize, unitSize); + ctx.fillRect(0, 0, w, h); ctx.closePath(); } diff --git a/src/utils/pattern/index.ts b/src/utils/pattern/index.ts index 0145f601e8..50649d850f 100644 --- a/src/utils/pattern/index.ts +++ b/src/utils/pattern/index.ts @@ -3,8 +3,6 @@ import { createDotPattern } from './dot'; import { createLinePattern } from './line'; import { createSquarePattern } from './square'; -export type PatternShape = 'dot' | 'square' | 'line'; //... - export type PatternOption = | { type: 'dot'; @@ -26,21 +24,15 @@ export type PatternOption = */ export function getCanvasPattern(options: PatternOption): CanvasPattern { const { type, cfg } = options; - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - let patternCanvas; switch (type) { case 'dot': return createDotPattern(cfg); case 'line': - patternCanvas = createLinePattern(cfg); - break; + return createLinePattern(cfg); case 'square': return createSquarePattern(cfg); default: return; } - - return ctx.createPattern(patternCanvas, cfg?.mode || 'repeat'); } diff --git a/src/utils/pattern/line.ts b/src/utils/pattern/line.ts index 846421d0d1..27178fd100 100644 --- a/src/utils/pattern/line.ts +++ b/src/utils/pattern/line.ts @@ -1,8 +1,21 @@ import { LinePatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; +import { drawRect } from './dot'; -export function createLinePattern(cfg: LinePatternCfg): HTMLCanvasElement { - const lineOptions = deepAssign( +function drawLine(options: LinePatternCfg, canvas: HTMLCanvasElement, d: string) { + const { stroke, lineWidth, strokeOpacity } = options; + const path = new Path2D(d); + const ctx = canvas.getContext('2d'); + + ctx.globalAlpha = strokeOpacity; + ctx.lineCap = 'square'; + ctx.strokeStyle = stroke; + ctx.lineWidth = lineWidth; + ctx.stroke(path); +} + +export function createLinePattern(cfg: LinePatternCfg): CanvasPattern { + const lineCfg = deepAssign( {}, { rotation: 45, @@ -17,8 +30,10 @@ export function createLinePattern(cfg: LinePatternCfg): HTMLCanvasElement { ); const canvas = document.createElement('canvas'); - const { spacing } = lineOptions; - const rotation = lineOptions.rotation % 360; + const ctx = canvas.getContext('2d'); + + const { spacing } = lineCfg; + const rotation = lineCfg.rotation % 360; const radians = rotation * (Math.PI / 180); // w, h 画布宽高 let w = Math.floor(Math.abs(spacing / Math.sin(radians))); @@ -68,32 +83,8 @@ export function createLinePattern(cfg: LinePatternCfg): HTMLCanvasElement { } } - drawBackground(lineOptions, canvas, w, h); - drawLine(lineOptions, canvas, d); - - return canvas; -} - -function drawBackground(options: LinePatternCfg, canvas: HTMLCanvasElement, w: number, h: number) { - const { backgroundColor, opacity } = options; - const ctx = canvas.getContext('2d'); - - canvas.width = w; - canvas.height = h; - ctx.globalAlpha = opacity; - ctx.fillStyle = backgroundColor; - ctx.fillRect(0, 0, w, h); - ctx.fill(); -} + drawRect(lineCfg, canvas, w, h); + drawLine(lineCfg, canvas, d); -function drawLine(options: LinePatternCfg, canvas: HTMLCanvasElement, d: string) { - const { stroke, lineWidth, strokeOpacity } = options; - const path = new Path2D(d); - const ctx = canvas.getContext('2d'); - - ctx.globalAlpha = strokeOpacity; - ctx.lineCap = 'square'; - ctx.strokeStyle = stroke; - ctx.lineWidth = lineWidth; - ctx.stroke(path); + return ctx.createPattern(canvas, cfg.mode || 'repeat'); } From 85b7e024c8e2f9c87b125a66d95e2bb644de2d3b Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Wed, 11 Aug 2021 10:23:53 +0800 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20=E4=B8=80=E4=BA=9B=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=B8=8A=E7=9A=84=E4=BC=98=E5=8C=96=20&=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=97=A0=E7=94=A8=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/pattern/dot.ts | 33 ++++++++++++++++----------------- src/utils/pattern/line.ts | 17 ++++++++--------- src/utils/pattern/pattern.ts | 32 -------------------------------- src/utils/pattern/square.ts | 17 ++++++++--------- 4 files changed, 32 insertions(+), 67 deletions(-) delete mode 100644 src/utils/pattern/pattern.ts diff --git a/src/utils/pattern/dot.ts b/src/utils/pattern/dot.ts index b05a80c50c..a6d2361fb3 100644 --- a/src/utils/pattern/dot.ts +++ b/src/utils/pattern/dot.ts @@ -1,8 +1,8 @@ import { DotPatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; -export function drawRect(options: DotPatternCfg, canvas: HTMLCanvasElement, width: number, height?: number) { - const { backgroundColor, opacity } = options; +export function drawRect(canvas: HTMLCanvasElement, cfg: DotPatternCfg, width: number, height: number = width) { + const { backgroundColor, opacity } = cfg; const ctx = canvas.getContext('2d'); const w = width; @@ -18,21 +18,20 @@ export function drawRect(options: DotPatternCfg, canvas: HTMLCanvasElement, widt ctx.closePath(); } -function drawDot(options: DotPatternCfg, canvas: HTMLCanvasElement, x: number, y: number) { - const { radius, fill, lineWidth, stroke, fillOpacity } = options; - const ctx = canvas.getContext('2d'); +function drawDot(cfg: DotPatternCfg, context: CanvasRenderingContext2D, x: number, y: number) { + const { radius, fill, lineWidth, stroke, fillOpacity } = cfg; - ctx.beginPath(); - ctx.globalAlpha = fillOpacity; - ctx.fillStyle = fill; - ctx.strokeStyle = stroke; - ctx.lineWidth = lineWidth; - ctx.arc(x, y, radius, 0, 2 * Math.PI, false); - ctx.fill(); + context.beginPath(); + context.globalAlpha = fillOpacity; + context.fillStyle = fill; + context.strokeStyle = stroke; + context.lineWidth = lineWidth; + context.arc(x, y, radius, 0, 2 * Math.PI, false); + context.fill(); if (lineWidth) { - ctx.stroke(); + context.stroke(); } - ctx.closePath(); + context.closePath(); } /** @@ -42,7 +41,7 @@ function drawDot(options: DotPatternCfg, canvas: HTMLCanvasElement, x: number, y * @returns HTMLCanvasElement */ export function createDotPattern(cfg: DotPatternCfg): CanvasPattern { - const pixelRatio = typeof window === 'object' && window.devicePixelRatio ? window.devicePixelRatio : 1; + const pixelRatio = window?.devicePixelRatio || 2; const dotCfg = deepAssign( {}, @@ -85,10 +84,10 @@ export function createDotPattern(cfg: DotPatternCfg): CanvasPattern { canvas.style.height = `${logicalHeight}px`; // ~~~ 后续再行测试 ~~~ - drawRect(dotCfg, canvas, size); + drawRect(canvas, dotCfg, size); // 绘制图案 for (const [x, y] of dots) { - drawDot(dotCfg, canvas, x, y); + drawDot(dotCfg, ctx, x, y); } return ctx.createPattern(canvas, cfg.mode || 'repeat'); diff --git a/src/utils/pattern/line.ts b/src/utils/pattern/line.ts index 27178fd100..1cc8049391 100644 --- a/src/utils/pattern/line.ts +++ b/src/utils/pattern/line.ts @@ -2,16 +2,15 @@ import { LinePatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; import { drawRect } from './dot'; -function drawLine(options: LinePatternCfg, canvas: HTMLCanvasElement, d: string) { +function drawLine(options: LinePatternCfg, context: CanvasRenderingContext2D, d: string) { const { stroke, lineWidth, strokeOpacity } = options; const path = new Path2D(d); - const ctx = canvas.getContext('2d'); - ctx.globalAlpha = strokeOpacity; - ctx.lineCap = 'square'; - ctx.strokeStyle = stroke; - ctx.lineWidth = lineWidth; - ctx.stroke(path); + context.globalAlpha = strokeOpacity; + context.lineCap = 'square'; + context.strokeStyle = stroke; + context.lineWidth = lineWidth; + context.stroke(path); } export function createLinePattern(cfg: LinePatternCfg): CanvasPattern { @@ -83,8 +82,8 @@ export function createLinePattern(cfg: LinePatternCfg): CanvasPattern { } } - drawRect(lineCfg, canvas, w, h); - drawLine(lineCfg, canvas, d); + drawRect(canvas, lineCfg, w, h); + drawLine(lineCfg, ctx, d); return ctx.createPattern(canvas, cfg.mode || 'repeat'); } diff --git a/src/utils/pattern/pattern.ts b/src/utils/pattern/pattern.ts deleted file mode 100644 index 9bf7272751..0000000000 --- a/src/utils/pattern/pattern.ts +++ /dev/null @@ -1,32 +0,0 @@ -export type PatternCfg = { - size?: [number, number]; //[width, height] - padding?: number; - fill?: string; - stroke?: string; - lineWidth?: number; - opacity?: number; - rotate?: number; - isStagger?: boolean; - backgroundColor?: string | 'inherit'; - mode?: 'repeat' | 'no-repeat' | 'repeat-x' | 'repeat-y'; -}; - -export abstract class Pattern { - public options: O; - public pattern: CanvasPattern; - public patternCanvas: HTMLCanvasElement; - - constructor(options?: O) { - this.options = this.initOptions(options); - this.patternCanvas = document.createElement('canvas'); - this.init(); - } - - protected abstract init(); - - public getCanvas() { - return this.patternCanvas; - } - - protected abstract initOptions(options: O); -} diff --git a/src/utils/pattern/square.ts b/src/utils/pattern/square.ts index f655e04bcc..dcbd61fd8e 100644 --- a/src/utils/pattern/square.ts +++ b/src/utils/pattern/square.ts @@ -2,16 +2,15 @@ import { SquarePatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; import { drawRect } from './dot'; -function drawSquare(options: SquarePatternCfg, canvas: HTMLCanvasElement, x: number, y: number) { +function drawSquare(options: SquarePatternCfg, context: CanvasRenderingContext2D, x: number, y: number) { const { stroke, size, fill, lineWidth, fillOpacity, rotation } = options; - const ctx = canvas.getContext('2d'); const radians = (rotation % 360) * (Math.PI / 180); - ctx.globalAlpha = fillOpacity; - ctx.strokeStyle = stroke; - ctx.lineWidth = lineWidth; - ctx.fillStyle = fill; - ctx.fillRect(x, y, size, size); + context.globalAlpha = fillOpacity; + context.strokeStyle = stroke; + context.lineWidth = lineWidth; + context.fillStyle = fill; + context.fillRect(x, y, size, size); // todo 控制旋转 // ctx.translate(x, y); @@ -53,9 +52,9 @@ export function createSquarePattern(cfg: SquarePatternCfg): CanvasPattern { unitSize *= 2; } - drawRect(squareCfg, canvas, unitSize); + drawRect(canvas, squareCfg, unitSize); for (const [x, y] of squares) { - drawSquare(squareCfg, canvas, x, y); + drawSquare(squareCfg, ctx, x, y); } return ctx.createPattern(canvas, cfg.mode || 'repeat'); } From 29f13869a22d412c54358935500e4e13672bc4a9 Mon Sep 17 00:00:00 2001 From: visiky <736929286@qq.com> Date: Wed, 11 Aug 2021 10:36:48 +0800 Subject: [PATCH 5/5] =?UTF-8?q?refactor(pattern):=20=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=20canvas=20=E7=9A=84=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=8A=BD=E5=8F=96=E4=B8=BA=E4=B8=80=E4=B8=AA=20util=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/pattern/dot.ts | 68 ++++++++++++++++++++++--------------- src/utils/pattern/line.ts | 11 +++--- src/utils/pattern/square.ts | 11 +++--- 3 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/utils/pattern/dot.ts b/src/utils/pattern/dot.ts index a6d2361fb3..7d7faea39a 100644 --- a/src/utils/pattern/dot.ts +++ b/src/utils/pattern/dot.ts @@ -1,24 +1,48 @@ import { DotPatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; -export function drawRect(canvas: HTMLCanvasElement, cfg: DotPatternCfg, width: number, height: number = width) { - const { backgroundColor, opacity } = cfg; - const ctx = canvas.getContext('2d'); +/** + * 初始化 cavnas,设置宽高等 + */ +export function initCanvas(canvas: HTMLCanvasElement, width: number, height: number = width) { + // ~~~ 后续再行测试 ~~~ + const pixelRatio = window?.devicePixelRatio || 2; + const logicalWidth = width; + const logicalHeight = height; + // 画布尺寸 + canvas.width = logicalWidth * pixelRatio; + canvas.height = logicalHeight * pixelRatio; + // 显示尺寸 + canvas.style.width = `${logicalWidth}px`; + canvas.style.height = `${logicalHeight}px`; + // ~~~ 后续再行测试 ~~~ +} - const w = width; - const h = height || width; +/** + * 绘制背景 + * + * @param context + * @param cfg + * @param width + * @param height + */ +export function drawBackground( + context: CanvasRenderingContext2D, + cfg: DotPatternCfg, + width: number, + height: number = width +) { + const { backgroundColor, opacity } = cfg; - canvas.width = w; - canvas.height = h; - ctx.globalAlpha = opacity; - ctx.fillStyle = backgroundColor; + context.globalAlpha = opacity; + context.fillStyle = backgroundColor; - ctx.beginPath(); - ctx.fillRect(0, 0, w, h); - ctx.closePath(); + context.beginPath(); + context.fillRect(0, 0, width, height); + context.closePath(); } -function drawDot(cfg: DotPatternCfg, context: CanvasRenderingContext2D, x: number, y: number) { +function drawDot(context: CanvasRenderingContext2D, cfg: DotPatternCfg, x: number, y: number) { const { radius, fill, lineWidth, stroke, fillOpacity } = cfg; context.beginPath(); @@ -41,8 +65,6 @@ function drawDot(cfg: DotPatternCfg, context: CanvasRenderingContext2D, x: numbe * @returns HTMLCanvasElement */ export function createDotPattern(cfg: DotPatternCfg): CanvasPattern { - const pixelRatio = window?.devicePixelRatio || 2; - const dotCfg = deepAssign( {}, { @@ -73,21 +95,11 @@ export function createDotPattern(cfg: DotPatternCfg): CanvasPattern { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); - // ~~~ 后续再行测试 ~~~ - const logicalWidth = size; - const logicalHeight = size; - // 画布尺寸 - canvas.width = logicalWidth * pixelRatio; - canvas.height = logicalHeight * pixelRatio; - // 显示尺寸 - canvas.style.width = `${logicalWidth}px`; - canvas.style.height = `${logicalHeight}px`; - // ~~~ 后续再行测试 ~~~ - - drawRect(canvas, dotCfg, size); + initCanvas(canvas, size); + drawBackground(ctx, dotCfg, size); // 绘制图案 for (const [x, y] of dots) { - drawDot(dotCfg, ctx, x, y); + drawDot(ctx, dotCfg, x, y); } return ctx.createPattern(canvas, cfg.mode || 'repeat'); diff --git a/src/utils/pattern/line.ts b/src/utils/pattern/line.ts index 1cc8049391..b9485dcfbd 100644 --- a/src/utils/pattern/line.ts +++ b/src/utils/pattern/line.ts @@ -1,9 +1,9 @@ import { LinePatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; -import { drawRect } from './dot'; +import { drawBackground, initCanvas } from './dot'; -function drawLine(options: LinePatternCfg, context: CanvasRenderingContext2D, d: string) { - const { stroke, lineWidth, strokeOpacity } = options; +function drawLine(context: CanvasRenderingContext2D, cfg: LinePatternCfg, d: string) { + const { stroke, lineWidth, strokeOpacity } = cfg; const path = new Path2D(d); context.globalAlpha = strokeOpacity; @@ -82,8 +82,9 @@ export function createLinePattern(cfg: LinePatternCfg): CanvasPattern { } } - drawRect(canvas, lineCfg, w, h); - drawLine(lineCfg, ctx, d); + initCanvas(canvas, w, h); + drawBackground(ctx, lineCfg, w, h); + drawLine(ctx, lineCfg, d); return ctx.createPattern(canvas, cfg.mode || 'repeat'); } diff --git a/src/utils/pattern/square.ts b/src/utils/pattern/square.ts index dcbd61fd8e..a9cd0ff46f 100644 --- a/src/utils/pattern/square.ts +++ b/src/utils/pattern/square.ts @@ -1,9 +1,9 @@ import { SquarePatternCfg } from '../../types/pattern'; import { deepAssign } from '../../utils'; -import { drawRect } from './dot'; +import { drawBackground, initCanvas } from './dot'; -function drawSquare(options: SquarePatternCfg, context: CanvasRenderingContext2D, x: number, y: number) { - const { stroke, size, fill, lineWidth, fillOpacity, rotation } = options; +function drawSquare(context: CanvasRenderingContext2D, cfg: SquarePatternCfg, x: number, y: number) { + const { stroke, size, fill, lineWidth, fillOpacity, rotation } = cfg; const radians = (rotation % 360) * (Math.PI / 180); context.globalAlpha = fillOpacity; @@ -52,9 +52,10 @@ export function createSquarePattern(cfg: SquarePatternCfg): CanvasPattern { unitSize *= 2; } - drawRect(canvas, squareCfg, unitSize); + initCanvas(canvas, size, unitSize); + drawBackground(ctx, squareCfg, unitSize); for (const [x, y] of squares) { - drawSquare(squareCfg, ctx, x, y); + drawSquare(ctx, squareCfg, x, y); } return ctx.createPattern(canvas, cfg.mode || 'repeat'); }