Skip to content

Commit 1572510

Browse files
committed
feat: 给元素添加render
1 parent 6c3208b commit 1572510

File tree

15 files changed

+198
-17
lines changed

15 files changed

+198
-17
lines changed

packages/board-collaboration/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ import type { EBoard, ModelChangeEvent, ModelService } from "@e-board/board-core
22

33
class BoardCollaboration {
44
private modelService: ModelService
5+
// private websocketProvider: WebSocketProvider
56
private disposeList: (() => void)[] = [];
67
constructor(private board: EBoard) {
78
this.modelService = board.getService('modelService')
89
this.init()
910
}
1011

12+
// TODO: 初始化websocketProvider, 监听传入的数据,更新modelService中的数据
13+
1114
private init = () => {
1215
const { dispose } = this.modelService.onModelOperation(
1316
(operation: ModelChangeEvent) => {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { EBoard } from '../../board'
2+
import { IShapeRectangle } from '../rectElement/type'
3+
import { IModel } from '@e-board/board-core'
4+
class BaseRender<T extends Record<string, any>> {
5+
protected board: EBoard
6+
constructor(board: EBoard) {
7+
this.board = board
8+
}
9+
public render = (model: IModel<T>, _: any, isViewChanged: boolean = false): void => {
10+
throw new Error('render method not implemented')
11+
}
12+
}
13+
14+
15+
export { BaseRender }
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { IElement } from "../../services";
22
import { LineCtrlElement } from "./ctrlElement";
3+
import { Render } from "./render";
34
import SaveInfoProvider from "./saveInfoProvider";
45

5-
const lineElement: IElement = {
6+
const lineElement = {
67
type: "line",
78
ctrlElement: LineCtrlElement,
8-
saveInfoProvider: SaveInfoProvider
9-
}
9+
saveInfoProvider: SaveInfoProvider,
10+
render: Render
11+
} satisfies IElement;
1012

1113
export default lineElement;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
3+
4+
5+
import { IModel } from "@e-board/board-core";
6+
7+
import { BaseRender } from "../../baseElement/baseRender";
8+
import { ILineModel } from "../type";
9+
10+
11+
class Render extends BaseRender<ILineModel> {
12+
private transformService = this.board.getService('transformService')
13+
public transformPoint(point: { x: number; y: number }, inverse = false) {
14+
return this.transformService.transformPoint(point, inverse);
15+
}
16+
public render = (
17+
model: IModel<ILineModel>,
18+
_: any,
19+
isViewChanged: boolean = false
20+
) => {
21+
const context = this.board.getCtx();
22+
if (!context) return;
23+
context.save()
24+
const toScreenPoint = isViewChanged
25+
? (point: { x: number; y: number }) => point
26+
: (point: { x: number; y: number }) => this.transformPoint(point);
27+
model.points?.forEach((point, index) => {
28+
const transformedPoint = toScreenPoint(point);
29+
if (index === 0) {
30+
context.moveTo(transformedPoint.x, transformedPoint.y);
31+
} else if (index < 2) {
32+
context.lineTo(transformedPoint.x, transformedPoint.y);
33+
} else {
34+
const p1 = toScreenPoint(model.points![index - 1]);
35+
const p2 = toScreenPoint(point);
36+
const midPointX = (p1.x + p2.x) / 2;
37+
const midPointY = (p1.y + p2.y) / 2;
38+
context.quadraticCurveTo(p1.x, p1.y, midPointX, midPointY);
39+
}
40+
});
41+
context.restore()
42+
};
43+
}
44+
45+
export { Render }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
interface IPoint {
2+
x: number;
3+
y: number;
4+
}
5+
export interface ILineModel {
6+
points?: IPoint[];
7+
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { IElement } from "../../services";
22
import { PictureCtrlElement } from "./ctrlElement";
3+
import { Render } from "./render";
34
import SaveInfoProvider from "./saveInfoProvider";
45

5-
const pictureElement: IElement = {
6+
const pictureElement = {
67
type: "picture",
78
ctrlElement: PictureCtrlElement,
8-
saveInfoProvider: SaveInfoProvider
9-
}
9+
saveInfoProvider: SaveInfoProvider,
10+
render: Render
11+
} satisfies IElement;
1012

1113
export default pictureElement;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { IModel } from "@e-board/board-core";
2+
import { BaseRender } from "../../baseElement/baseRender";
3+
import { IPictureModel } from "../type";
4+
5+
class Render extends BaseRender<IPictureModel> {
6+
private transformService = this.board.getService('transformService')
7+
private renderService = this.board.getService('renderService')
8+
private imageCache = new Map<string, HTMLImageElement>();
9+
public transformPoint(point: { x: number; y: number }, inverse = false) {
10+
return this.transformService.transformPoint(point, inverse);
11+
}
12+
public render = (model: IModel<IPictureModel>, _: any, useWorldCoords = false) => {
13+
const context = this.board.getCtx();
14+
if (!context || !model.imageData || !model.points) return;
15+
16+
context.save();
17+
18+
let img = this.imageCache.get(model.id);
19+
if (!img) {
20+
img = new Image();
21+
img.src = model.imageData;
22+
this.imageCache.set(model.id, img);
23+
}
24+
25+
if (img.complete) {
26+
const zoom = this.transformService.getView().zoom;
27+
const transformedPos = useWorldCoords ? model.points[0] : this.transformPoint(model.points[0]);
28+
const width = useWorldCoords ? (model.width || img.width) : (model.width || img.width) * zoom;
29+
const height = useWorldCoords ? (model.height || img.height) : (model.height || img.height) * zoom;
30+
31+
// 将图片中心对齐到指定位置,而不是左上角
32+
const drawX = transformedPos.x
33+
const drawY = transformedPos.y
34+
35+
context.drawImage(img, drawX, drawY, width, height);
36+
} else {
37+
img.onload = () => {
38+
this.renderService.reRender();
39+
};
40+
}
41+
42+
context.restore();
43+
};
44+
}
45+
46+
47+
export { Render }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
export interface IPictureModel {
3+
imageData?: string;
4+
width?: number;
5+
height?: number;
6+
}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import { IRectangleModel } from "src/plugins/drawShape/type";
12
import { IElement } from "../../services";
23
import { RectCtrlElement } from "./ctrlElement";
4+
import { Render } from "./render";
35
import SaveInfoProvider from "./saveInfoProvider";
46

5-
const rectElement: IElement = {
7+
const rectElement = {
68
type: "rectangle",
79
ctrlElement: RectCtrlElement,
8-
saveInfoProvider: SaveInfoProvider
9-
}
10+
saveInfoProvider: SaveInfoProvider,
11+
render: Render
12+
} satisfies IElement<IRectangleModel>
1013

1114
export default rectElement;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { IModel } from "@e-board/board-core";
2+
3+
import { BaseRender } from "../../baseElement/baseRender";
4+
import { IShapeRectangle } from "../type";
5+
6+
class Render extends BaseRender<IShapeRectangle> {
7+
private transformService = this.board.getService('transformService')
8+
public transformPoint(point: { x: number; y: number }, inverse = false) {
9+
return this.transformService.transformPoint(point, inverse);
10+
}
11+
public render = (
12+
model: IModel<IShapeRectangle>,
13+
_: any,
14+
isViewChanged: boolean = false
15+
) => {
16+
const context = this.board.getCtx();
17+
if (!context) return;
18+
const [point] = model.points!;
19+
if (isViewChanged) {
20+
context.rect(
21+
point.x,
22+
point.y,
23+
model.width,
24+
model.height
25+
)
26+
} else {
27+
const transformedPoint = this.transformPoint({ x: point.x, y: point.y });
28+
const zoom = this.transformService.getView().zoom;
29+
30+
// 绘制矩形
31+
context.rect(
32+
transformedPoint.x,
33+
transformedPoint.y,
34+
model.width * zoom,
35+
model.height * zoom
36+
);
37+
}
38+
39+
if (model.options?.fillStyle) {
40+
context.fillStyle = model.options.fillStyle;
41+
context.fill();
42+
}
43+
};
44+
}
45+
46+
export { Render }

0 commit comments

Comments
 (0)