Skip to content

Commit

Permalink
refactor(pattern): 内置 pattern 的属性设计 & 优化下创建逻辑 (#2785)
Browse files Browse the repository at this point in the history
* feat(dot-pattern): 优化 dot pattern, 修复 stagger 展示

* feat(square-pattern): 优化 square pattern, 修复 stagger 展示

* refactor(pattern): 优化 line pattern & 删除无用代码

* refactor: 一些代码上的优化 & 删除无用的代码

* refactor(pattern): 初始化 canvas 的逻辑,抽取为一个 util 函数
  • Loading branch information
visiky committed Aug 15, 2021
1 parent de0f0dd commit 5ee706f
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 208 deletions.
30 changes: 0 additions & 30 deletions src/utils/pattern/base.ts

This file was deleted.

133 changes: 80 additions & 53 deletions src/utils/pattern/dot.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,71 @@
import { DotPatternCfg } from '../../types/pattern';
import { deepAssign } from '../../utils';

export function createDotPattern(cfg: DotPatternCfg): HTMLCanvasElement {
const dotOptions = deepAssign(
/**
* 初始化 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`;
// ~~~ 后续再行测试 ~~~
}

/**
* 绘制背景
*
* @param context
* @param cfg
* @param width
* @param height
*/
export function drawBackground(
context: CanvasRenderingContext2D,
cfg: DotPatternCfg,
width: number,
height: number = width
) {
const { backgroundColor, opacity } = cfg;

context.globalAlpha = opacity;
context.fillStyle = backgroundColor;

context.beginPath();
context.fillRect(0, 0, width, height);
context.closePath();
}

function drawDot(context: CanvasRenderingContext2D, cfg: DotPatternCfg, x: number, y: number) {
const { radius, fill, lineWidth, stroke, fillOpacity } = cfg;

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) {
context.stroke();
}
context.closePath();
}

/**
* 创建 dot pattern,返回 HTMLCanvasElement
*
* @param cfg
* @returns HTMLCanvasElement
*/
export function createDotPattern(cfg: DotPatternCfg): CanvasPattern {
const dotCfg = deepAssign(
{},
{
radius: 4,
Expand All @@ -18,62 +81,26 @@ 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 { radius, padding, isStagger } = dotCfg;
const dots = [[padding / 2 + radius, padding / 2 + radius]];

// 后续再行测试
// 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);
let size = radius * 2 + padding;
// 如果交错, size 放大两倍 交错绘制 dot
if (isStagger) {
dots.push([size + radius, size + radius]);
size *= 2;
}

// console.info('dpr', dpr)
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

drawBackground(dotOptions, canvas, unitSize);
initCanvas(canvas, size);
drawBackground(ctx, dotCfg, size);
// 绘制图案
for (const [x, y] of dots) {
drawDot(dotOptions, canvas, x, y);
drawDot(ctx, dotCfg, x, y);
}

return canvas;
}

function drawBackground(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.globalAlpha = opacity;
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, unitSize, unitSize);
}

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);
ctx.fill();
ctx.stroke();
return ctx.createPattern(canvas, cfg.mode || 'repeat');
}
16 changes: 3 additions & 13 deletions src/utils/pattern/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -26,23 +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':
patternCanvas = createDotPattern(cfg);
break;
return createDotPattern(cfg);
case 'line':
patternCanvas = createLinePattern(cfg);
break;
return createLinePattern(cfg);
case 'square':
patternCanvas = createSquarePattern(cfg);
break;
return createSquarePattern(cfg);
default:
return;
}

return ctx.createPattern(patternCanvas, cfg?.mode || 'repeat');
}
53 changes: 22 additions & 31 deletions src/utils/pattern/line.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { LinePatternCfg } from '../../types/pattern';
import { deepAssign } from '../../utils';
import { drawBackground, initCanvas } from './dot';

export function createLinePattern(cfg: LinePatternCfg): HTMLCanvasElement {
const lineOptions = deepAssign(
function drawLine(context: CanvasRenderingContext2D, cfg: LinePatternCfg, d: string) {
const { stroke, lineWidth, strokeOpacity } = cfg;
const path = new Path2D(d);

context.globalAlpha = strokeOpacity;
context.lineCap = 'square';
context.strokeStyle = stroke;
context.lineWidth = lineWidth;
context.stroke(path);
}

export function createLinePattern(cfg: LinePatternCfg): CanvasPattern {
const lineCfg = deepAssign(
{},
{
rotation: 45,
Expand All @@ -17,8 +29,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)));
Expand Down Expand Up @@ -68,32 +82,9 @@ 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();
}

function drawLine(options: LinePatternCfg, canvas: HTMLCanvasElement, d: string) {
const { stroke, lineWidth, strokeOpacity } = options;
const path = new Path2D(d);
const ctx = canvas.getContext('2d');
initCanvas(canvas, w, h);
drawBackground(ctx, lineCfg, w, h);
drawLine(ctx, lineCfg, d);

ctx.globalAlpha = strokeOpacity;
ctx.lineCap = 'square';
ctx.strokeStyle = stroke;
ctx.lineWidth = lineWidth;
ctx.stroke(path);
return ctx.createPattern(canvas, cfg.mode || 'repeat');
}
32 changes: 0 additions & 32 deletions src/utils/pattern/pattern.ts

This file was deleted.

Loading

0 comments on commit 5ee706f

Please sign in to comment.