diff --git a/packages/docs/cn/src/article/visual.md b/packages/docs/cn/src/article/visual.md index 0d9f0a658..b54d0b382 100644 --- a/packages/docs/cn/src/article/visual.md +++ b/packages/docs/cn/src/article/visual.md @@ -116,9 +116,152 @@ class Container extends Vertex { ## 四:基础图形的封装 -在多数二维绘图业务场景中,复杂图形往往可以简化为基础图形的巧妙组合。核心的基础元素包括圆形、多边形以及贝塞尔曲线,它们是实现图形构建的基本单位。 +在多数二维绘图业务场景中,复杂图形往往可以简化为基础图形的组合。核心的基础元素包括圆形、多边形以及贝塞尔曲线,它们是实现图形构建的基本单位。 -此外,还有一些频繁使用的基础图形,如矩形、圆角矩形和椭圆,同样不可或缺。我们将这些统称为“基础图形库”,通过它们的灵活组合,能够轻松构建出满足各种业务需求的图形场景。 +此外,还有一些常用的基础图形,如矩形、圆角矩形和椭圆。我们将这些统称为“基础图形库”,通过它们的灵活组合,能够轻松构建出满足各种需求的二维场景。 + +首先我们定一个`Graphics`类,继承自 `Container` 类,表示绘制各种图形的容器。 + +```ts +class Graphics extends Container {} +``` + +绘制的过程中,我们需要考虑是填充还是描边图形。因此,需要定义两个属性: +`lineStyle`和`fillStyle`,用来表示 line 的属性,和 fill 的属性。 + +line 的属性有:color,alpha,visible,width,[cap](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap),[join](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin),[miterLimit](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/miterLimit) + +填充的属性有:color,alpha,visible + +我们可以用两个类去描述这些数据,Fill 类: + +```ts +class Fill { + public color = '#ffffff'; + public alpha = 1.0; + public visible = false; + + constructor() { + this.reset(); + } + + public clone(): Fill { + const obj = new Fill(); + obj.color = this.color; + obj.alpha = this.alpha; + obj.visible = this.visible; + return obj; + } + + public reset(): void { + this.color = '#ffffff'; + this.alpha = 1; + this.visible = false; + } +} +``` + +Line 类既有 Fill 类的所有属性,还有些其他的属性,所以可以继承 Fill 类: + +```ts +class Line extends Fill { + public width = 0; + public cap = LINE_CAP.BUTT; + public join = LINE_JOIN.MITER; + public miterLimit = 10; + + public clone(): Line { + const obj = new Line(); + obj.color = this.color; + obj.alpha = this.alpha; + obj.visible = this.visible; + obj.width = this.width; + obj.cap = this.cap; + obj.join = this.join; + obj.miterLimit = this.miterLimit; + return obj; + } + + public reset(): void { + super.reset(); + this.color = '#ffffff'; + this.width = 0; + this.cap = LINE_CAP.BUTT; + this.join = LINE_JOIN.MITER; + this.miterLimit = 10; + } +} +``` + +因此,`Graphics`类的属性如下: + +```ts +class Graphics extends Container { + private _lineStyle = new Line(); + private _fillStyle = new Fill(); + constructor() { + super(); + this.type = GRAPHICS; + } +} +``` + +还需要增加一些画线的方法和填充的方法: + +```ts +class Graphics extends Container { + private _lineStyle = new Line(); + private _fillStyle = new Fill(); + constructor() { + super(); + this.type = GRAPHICS; + } + public lineStyle(width: number, color?: string, alpha?: number): Graphics; + public lineStyle(options: ILineStyleOptions): Graphics; + public lineStyle(options: ILineStyleOptions | number, color: string = '0x000000', alpha: number = 1): Graphics { + this.startPoly(); + if (typeof options === 'object') { + Object.assign(this._lineStyle, options); + } else { + const opts: ILineStyleOptions = { width: options, color, alpha }; + Object.assign(this._lineStyle, opts); + } + this._lineStyle.visible = true; + return this; + } + // 如果要填充图形,则需要先调用这个函数给画笔设置填充色 + public beginFill(color = '#000000', alpha = 1): Graphics { + this._fillStyle.color = color; + this._fillStyle.alpha = alpha; + if (this._fillStyle.alpha > 0) { + this._fillStyle.visible = true; + } + return this; + } + /** + * 结束填充模式 + */ + public endFill = (): Graphics => { + this.startPoly(); + this._fillStyle.reset(); + return this; + }; +} +``` + +接下来是绘制各种基础图形了,先从最简单的圆形开始。Graphics 类事绘制各种图形的容器,因此所有的基础图形绘制方法都在 Graphics 类上。增加绘制圆形的方法: + +```ts + /** + * 画圆 + * @param x 圆心 X 坐标 + * @param y 圆心 Y 坐标 + * @param radius 半径 + */ + public drawCircle = (x: number, y: number, radius: number): Graphics => { + return this.drawShape(new Circle(x, y, radius)); + }; +``` diff --git a/packages/ranuts/index.html b/packages/ranuts/index.html index 220e793aa..7fbf7d79d 100644 --- a/packages/ranuts/index.html +++ b/packages/ranuts/index.html @@ -17,8 +17,9 @@ const app = new Application({ view: document.getElementById('hierarchy'), }); + console.log('app', app); const blackGraphic = new Graphics(); - blackGraphic.beginFill('black'); + blackGraphic.beginFill('white'); blackGraphic.drawRect(0, 0, 300, 300); const redGraphic = new Graphics(); @@ -39,13 +40,18 @@ container2.addChild(greenGraphic); const yellowGraphic = new Graphics(); - yellowGraphic.beginFill('yellow'); + // yellowGraphic.beginFill('yellow'); + yellowGraphic.lineStyle({ width: 30, color: 'yellow', cap: 'round', join: 'round' }); yellowGraphic.drawRect(0, 0, 250, 150); app.stage.addChild(container2); app.stage.addChild(yellowGraphic); + + app.render(); + setTimeout(() => { yellowGraphic.position.set(200, 0); + app.render(); }, 1000); diff --git a/packages/ranuts/src/utils/visual/application.ts b/packages/ranuts/src/utils/visual/application.ts index 39f7160fb..e5a12d992 100644 --- a/packages/ranuts/src/utils/visual/application.ts +++ b/packages/ranuts/src/utils/visual/application.ts @@ -7,24 +7,29 @@ export class Application { private renderer: Renderer; public stage = new Container(); public view: HTMLCanvasElement; + public requestAnimationId?: number; constructor(options: IApplicationOptions) { - const { view } = options; + const { view = document.createElement('canvas') } = options || {}; this.view = view; this.renderer = getRenderer(options); // this.start(); - this.render(); + // this.render(); } - - public render(): void { + public render = (): void => { this.renderer.render(this.stage); - } - - private start() { + }; + public start = (): number => { const func = () => { this.render(); - requestAnimationFrame(func); + return requestAnimationFrame(func); }; - func(); - } + this.requestAnimationId = func(); + return this.requestAnimationId; + }; + public destroy = (): void => { + if (this.requestAnimationId !== undefined) { + cancelAnimationFrame(this.requestAnimationId); + } + }; } diff --git a/packages/ranuts/src/utils/visual/enums.ts b/packages/ranuts/src/utils/visual/enums.ts index 18f1afb70..f298f6757 100644 --- a/packages/ranuts/src/utils/visual/enums.ts +++ b/packages/ranuts/src/utils/visual/enums.ts @@ -32,3 +32,7 @@ export const MAX_VERTEX_COUNT = 65536; // 支持的最大的顶点数量 export const BYTES_PER_VERTEX = 12; // 每个顶点占多少字节 export const CONTAINER = 'container'; + +export const GRAPHICS = 'graphics'; + +export const OBJECT = 'object'; diff --git a/packages/ranuts/src/utils/visual/graphics/graphics.ts b/packages/ranuts/src/utils/visual/graphics/graphics.ts index 0d2a18983..181201161 100644 --- a/packages/ranuts/src/utils/visual/graphics/graphics.ts +++ b/packages/ranuts/src/utils/visual/graphics/graphics.ts @@ -10,6 +10,7 @@ import { RoundedRectangle } from '@/utils/visual/shape/roundedRectangle'; import { Ellipse } from '@/utils/visual/shape/ellipse'; import { toRgbaLittleEndian } from '@/utils/visual/render/utils'; import { batchPool } from '@/utils/visual/render/utils/batch'; +import { GRAPHICS } from '@/utils/visual/enums'; import type { GraphicsBatch } from '@/utils/visual/render/utils/batch'; import type { Shape } from '@/utils/visual/shape/shape'; import type { BatchRenderer } from '@/utils/visual/render/batchRenderer'; @@ -27,13 +28,12 @@ export class Graphics extends Container { constructor() { super(); - this.type = 'graphics'; + this.type = GRAPHICS; } public lineStyle(width: number, color?: string, alpha?: number): Graphics; public lineStyle(options: ILineStyleOptions): Graphics; public lineStyle(options: ILineStyleOptions | number, color: string = '0x000000', alpha: number = 1): Graphics { this.startPoly(); - if (typeof options === 'object') { Object.assign(this._lineStyle, options); } else { @@ -43,50 +43,43 @@ export class Graphics extends Container { this._lineStyle.visible = true; return this; } - public resetLineStyle(): void { + public resetLineStyle = (): void => { this._lineStyle.reset(); - } - protected drawShape(shape: Shape): Graphics { + }; + protected drawShape = (shape: Shape): Graphics => { this.geometry.drawShape(shape, this._fillStyle.clone(), this._lineStyle.clone()); return this; - } + }; /** * 清空已有的 path,开始新的 path */ - protected startPoly(): void { + protected startPoly = (): void => { const len = this.currentPath.points.length; - if (len > 2) { // 如果超过 2 个点,那么就算一个合法的 path this.drawShape(this.currentPath); } - this.currentPath = new Polygon(); - } + }; // 如果要填充图形,则需要先调用这个函数给画笔设置填充色 - public beginFill(color = '#000000', alpha = 1): Graphics { + public beginFill = (color = '#000000', alpha = 1): Graphics => { // 在填充参数变化之前,先将已有的 path 画出来 this.startPoly(); - this._fillStyle.color = color; this._fillStyle.alpha = alpha; - if (this._fillStyle.alpha > 0) { this._fillStyle.visible = true; } - return this; - } + }; /** * 结束填充模式 */ - public endFill(): Graphics { + public endFill = (): Graphics => { this.startPoly(); - this._fillStyle.reset(); - return this; - } + }; /** * 画矩形 * @param x x 坐标 @@ -94,18 +87,18 @@ export class Graphics extends Container { * @param width 宽度 * @param height 高度 */ - public drawRect(x: number, y: number, width: number, height: number): Graphics { + public drawRect = (x: number, y: number, width: number, height: number): Graphics => { return this.drawShape(new Rectangle(x, y, width, height)); - } + }; /** * 画圆 * @param x 圆心 X 坐标 * @param y 圆心 Y 坐标 * @param radius 半径 */ - public drawCircle(x: number, y: number, radius: number): Graphics { + public drawCircle = (x: number, y: number, radius: number): Graphics => { return this.drawShape(new Circle(x, y, radius)); - } + }; /** * 画圆角矩形 * @param x x 坐标 @@ -114,9 +107,9 @@ export class Graphics extends Container { * @param height 高度 * @param radius 圆角半径 */ - public drawRoundedRect(x: number, y: number, width: number, height: number, radius: number): Graphics { + public drawRoundedRect = (x: number, y: number, width: number, height: number, radius: number): Graphics => { return this.drawShape(new RoundedRectangle(x, y, width, height, radius)); - } + }; /** * 画椭圆 * @param x 椭圆中心 x 坐标 @@ -125,30 +118,30 @@ export class Graphics extends Container { * @param radiusY 椭圆 y 轴半径 */ - public drawEllipse(x: number, y: number, radiusX: number, radiusY: number): Graphics { + public drawEllipse = (x: number, y: number, radiusX: number, radiusY: number): Graphics => { return this.drawShape(new Ellipse(x, y, radiusX, radiusY)); - } + }; /** * 画多边形 * @param points 多边形顶点坐标数组,每 2 个元素算一组 (x,y) */ - public drawPolygon(points: number[]): Graphics { + public drawPolygon = (points: number[]): Graphics => { const poly = new Polygon(points); poly.closeStroke = true; return this.drawShape(poly); - } + }; - public moveTo(x: number, y: number): Graphics { + public moveTo = (x: number, y: number): Graphics => { this.startPoly(); this.currentPath.points[0] = x; this.currentPath.points[1] = y; return this; - } + }; - public lineTo(x: number, y: number): Graphics { + public lineTo = (x: number, y: number): Graphics => { if (this.currentPath.points.length === 0) { this.moveTo(x, y); return this; @@ -158,82 +151,66 @@ export class Graphics extends Container { const points = this.currentPath.points; const fromX = points[points.length - 2]; const fromY = points[points.length - 1]; - if (fromX !== x || fromY !== y) { points.push(x, y); } - return this; - } + }; - public closePath(): Graphics { + public closePath = (): Graphics => { this.currentPath.closeStroke = true; this.startPoly(); - return this; - } + }; - public containsPoint(p: Point): boolean { + public containsPoint = (p: Point): boolean => { // 如果设置了 hitArea 则只判断 hitArea if (this.hitArea) { return this.hitArea.contains(p); } - return this.geometry.containsPoint(p); - } + }; // 二阶贝塞尔曲线 // 采样多个点,然后连成一个近似于二阶贝塞尔曲线的直边多边形 - public quadraticCurveTo(cpX: number, cpY: number, toX: number, toY: number): Graphics { + public quadraticCurveTo = (cpX: number, cpY: number, toX: number, toY: number): Graphics => { const len = this.currentPath.points.length; - if (len === 0) { this.currentPath.points = [0, 0]; } - const P0X = this.currentPath.points[len - 2]; const P0Y = this.currentPath.points[len - 1]; const P1X = cpX; const P1Y = cpY; const P2X = toX; const P2Y = toY; - // 求出这条二阶贝塞尔曲线的长度 const curveLength = getQuadraticBezierLength(P0X, P0Y, P1X, P1Y, P2X, P2Y); - let segmentsCount = Math.ceil(curveLength / 10); // 每10个像素采样一次 - // 最大 2048 份 if (segmentsCount > 2048) { segmentsCount = 2048; } - // 最小 8 份 if (segmentsCount < 8) { segmentsCount = 8; } - // 计算出采样点的坐标然后放入 points 数组 for (let i = 1; i <= segmentsCount; i++) { const t = i / segmentsCount; - // 直接套用二阶贝塞尔曲线的公式 const x = (1 - t) * (1 - t) * P0X + 2 * t * (1 - t) * P1X + t * t * P2X; const y = (1 - t) * (1 - t) * P0Y + 2 * t * (1 - t) * P1Y + t * t * P2Y; - this.currentPath.points.push(x, y); } - return this; - } + }; // 三阶贝塞尔曲线 // 采样多个点,然后连成一个近似于三阶贝塞尔曲线的直边多边形 - public bezierCurveTo(cpX: number, cpY: number, cpX2: number, cpY2: number, toX: number, toY: number): Graphics { + public bezierCurveTo = (cpX: number, cpY: number, cpX2: number, cpY2: number, toX: number, toY: number): Graphics => { const len = this.currentPath.points.length; - if (len === 0) { this.currentPath.points = [0, 0]; } - const P0X = this.currentPath.points[len - 2]; const P0Y = this.currentPath.points[len - 1]; const P1X = cpX; @@ -242,26 +219,20 @@ export class Graphics extends Container { const P2Y = cpY2; const P3X = toX; const P3Y = toY; - // 求出这条三阶贝塞尔曲线的长度 const curveLength = getBezierLength(P0X, P0Y, P1X, P1Y, P2X, P2Y, P3X, P3Y); - let segmentsCount = Math.ceil(curveLength / 10); // 每10个像素采样一次 - - // 最大2048份 + // 最大 2048 份 if (segmentsCount > 2048) { segmentsCount = 2048; } - // 最小 8 份 if (segmentsCount < 8) { segmentsCount = 8; } - // 计算出采样点的坐标然后放入 points 数组 for (let i = 1; i <= segmentsCount; i++) { const t = i / segmentsCount; - // 直接套用三阶贝塞尔曲线的公式 const x = (1 - t) * (1 - t) * (1 - t) * P0X + @@ -273,92 +244,77 @@ export class Graphics extends Container { 3 * t * (1 - t) * (1 - t) * P1Y + 3 * t * t * (1 - t) * P2Y + t * t * t * P3Y; - this.currentPath.points.push(x, y); } return this; - } + }; // 圆弧arc - public arc( + public arc = ( cx: number, cy: number, radius: number, startAngle: number, endAngle: number, anticlockwise = false, - ): Graphics { + ): Graphics => { if (!anticlockwise) { while (endAngle < startAngle) { endAngle += Math.PI * 2; } - if (endAngle - startAngle > Math.PI * 2) { endAngle = startAngle + Math.PI * 2; } } - if (anticlockwise) { while (endAngle > startAngle) { startAngle += Math.PI * 2; } - if (startAngle - endAngle > Math.PI * 2) { endAngle = startAngle - Math.PI * 2; } } - const diff = endAngle - startAngle; - if (diff === 0) { return this; } - const startX = cx + Math.cos(startAngle) * radius; const startY = cy + Math.sin(startAngle) * radius; - this.lineTo(startX, startY); - const curveLen = Math.abs(diff) * radius; // 角度 (弧度制) 乘以半径等于弧长 let segmentsCount = Math.ceil(curveLen / 10); - // 最大 2048 份 if (segmentsCount > 2048) { segmentsCount = 2048; } - // 最小 8 份 if (segmentsCount < 8) { segmentsCount = 8; } - for (let i = 1; i <= segmentsCount; i++) { const angle = startAngle + diff * (i / segmentsCount); const x = cx + Math.cos(angle) * radius; const y = cy + Math.sin(angle) * radius; this.lineTo(x, y); } - return this; - } + }; - public arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): Graphics { + public arcTo = (x1: number, y1: number, x2: number, y2: number, radius: number): Graphics => { if (!this.currentPath) return this; const len = this.currentPath.points.length; - /** - * 如果画笔当前没有落点,则该操作相当于moveTo(x1, y1) - * 如果半径为0,则该操作也相当于lineTo(x1, y1) + * 如果画笔当前没有落点,则该操作相当于 moveTo(x1, y1) + * 如果半径为 0,则该操作也相当于 lineTo(x1, y1) */ if (len === 0 || radius === 0) { this.lineTo(x1, y1); return this; } - /** - * 假设画笔落点为P0,控制点1为P1,控制点2为P2,如果向量P0P1和向量P1P2的夹角太小或者夹角接近180度, - * 或者向量P0P1或向量P1P2其中一个的长度为0, - * 那么该操作也相当于moveTo(x1, y1), + * 假设画笔落点为 P0,控制点 1 为 P1,控制点 2 为 P2,如果向量 P0P1 和向量 P1P2 的夹角太小或者夹角接近 180 度, + * 或者向量 P0P1 或向量 P1P2 其中一个的长度为 0, + * 那么该操作也相当于 moveTo(x1, y1), * 我们用叉积来判断这种情况 */ const a1 = this.currentPath.points[len - 1] - y1; @@ -371,7 +327,6 @@ export class Graphics extends Container { this.lineTo(x1, y1); return this; } - const dd = a1 * a1 + b1 * b1; const cc = a2 * a2 + b2 * b2; const tt = a1 * a2 + b1 * b2; @@ -388,47 +343,37 @@ export class Graphics extends Container { const startAngle = Math.atan2(py - cy, px - cx); const endAngle = Math.atan2(qy - cy, qx - cx); const anticlockwise = b1 * a2 > b2 * a1; - return this.arc(cx + x1, cy + y1, radius, startAngle, endAngle, anticlockwise); - } - public clear(): Graphics { + }; + public clear = (): Graphics => { this.geometry.clear(); this._lineStyle.reset(); this._fillStyle.reset(); this.currentPath = new Polygon(); - return this; - } + }; /** * 调用 canvas API 绘制自身 */ - protected renderCanvas(render: CanvasRenderer): void { + protected renderCanvas = (render: CanvasRenderer): void => { this.startPoly(); - const ctx = render.ctx; const { a, b, c, d, tx, ty } = this.transform.worldTransform; - ctx.setTransform(a, b, c, d, tx, ty); - const graphicsData = this.geometry.graphicsData; - for (let i = 0; i < graphicsData.length; i++) { const data = graphicsData[i]; const { lineStyle, fillStyle, shape } = data; - if (fillStyle.visible) { ctx.fillStyle = fillStyle.color; } - if (lineStyle.visible) { ctx.lineWidth = lineStyle.width; ctx.lineCap = lineStyle.cap; ctx.lineJoin = lineStyle.join; ctx.strokeStyle = lineStyle.color; } - ctx.beginPath(); - if (shape instanceof Rectangle) { const rectangle = shape; const { x, y, width, height } = rectangle; @@ -441,13 +386,10 @@ export class Graphics extends Container { ctx.strokeRect(x, y, width, height); } } - if (shape instanceof Circle) { const circle = shape; const { x, y, radius } = circle; - ctx.arc(x, y, radius, 0, 2 * Math.PI); - if (fillStyle.visible) { ctx.globalAlpha = fillStyle.alpha * this.worldAlpha; ctx.fill(); @@ -457,11 +399,9 @@ export class Graphics extends Container { ctx.stroke(); } } - if (shape instanceof RoundedRectangle) { const roundedRectangle = shape; const { x, y, width, height, radius } = roundedRectangle; - ctx.moveTo(x + radius, y); ctx.arc(x + radius, y + radius, radius, Math.PI * 1.5, Math.PI, true); ctx.lineTo(x, y + height - radius); @@ -471,7 +411,6 @@ export class Graphics extends Container { ctx.lineTo(x + width, y + radius); ctx.arc(x + width - radius, y + radius, radius, 0, Math.PI * 1.5, true); ctx.closePath(); - if (fillStyle.visible) { ctx.globalAlpha = fillStyle.alpha * this.worldAlpha; ctx.fill(); @@ -481,68 +420,50 @@ export class Graphics extends Container { ctx.stroke(); } } - if (shape instanceof Ellipse) { const ellipse = shape; const { x, y, radiusX, radiusY } = ellipse; - ctx.ellipse(x, y, radiusX, radiusY, 0, 0, Math.PI * 2); - if (fillStyle.visible) { ctx.globalAlpha = fillStyle.alpha * this.worldAlpha; ctx.fill(); } - if (lineStyle.visible) { ctx.globalAlpha = lineStyle.alpha * this.worldAlpha; ctx.stroke(); } } - if (shape instanceof Polygon) { const polygon = shape; - const { points, closeStroke } = polygon; - ctx.moveTo(points[0], points[1]); - for (let i = 2; i < points.length; i += 2) { ctx.lineTo(points[i], points[i + 1]); } - if (closeStroke) { ctx.closePath(); } - if (fillStyle.visible) { ctx.globalAlpha = fillStyle.alpha * this.worldAlpha; ctx.fill(); } - if (lineStyle.visible) { ctx.globalAlpha = lineStyle.alpha * this.worldAlpha; ctx.stroke(); } } } - } + }; - public buildBatches(batchRenderer: BatchRenderer): void { + public buildBatches = (batchRenderer: BatchRenderer): void => { this.startPoly(); - this.worldId = this.transform.worldId; - this.geometry.buildVerticesAndTriangulate(); - const batchParts = this.geometry.batchParts; - for (let i = 0; i < batchParts.length; i++) { const { style, vertexStart, vertexCount, indexStart, indexCount } = batchParts[i]; - const { color, alpha } = style; - const rgba = toRgbaLittleEndian(color, alpha * this.worldAlpha); - const batch = batchPool.get(this.type) as GraphicsBatch; batch.vertexCount = vertexCount; batch.indexCount = indexCount; @@ -550,23 +471,19 @@ export class Graphics extends Container { batch.vertexOffset = vertexStart; batch.indexOffset = indexStart; batch.graphics = this; - this.batches[i] = batch; batchRenderer.addBatch(this.batches[i]); } - this.batchCount = batchParts.length; - } + }; - public updateBatches(floatView: Float32Array): void { + public updateBatches = (floatView: Float32Array): void => { if (this.worldId === this.transform.worldId) { return; } - this.worldId = this.transform.worldId; - for (let i = 0; i < this.batchCount; i++) { this.batches[i].updateVertices(floatView); } - } + }; } diff --git a/packages/ranuts/src/utils/visual/graphics/graphicsGeometry.ts b/packages/ranuts/src/utils/visual/graphics/graphicsGeometry.ts index f5a2114b7..ea2b96978 100644 --- a/packages/ranuts/src/utils/visual/graphics/graphicsGeometry.ts +++ b/packages/ranuts/src/utils/visual/graphics/graphicsGeometry.ts @@ -15,7 +15,6 @@ export class GraphicsGeometry { * 每个 batchPart 代表一个 fill 或者一个 stroke */ public batchParts: BatchPart[] = []; - /** * 顶点数组,每 2 个元素代表一个顶点 */ @@ -49,9 +48,7 @@ export class GraphicsGeometry { * 将所有子图形都转化成顶点并且进行三角剖分 */ public buildVerticesAndTriangulate(): void { - if (!this.dirty) { - return; - } + if (!this.dirty) return; this.dirty = false; for (let i = this.shapeIndex; i < this.graphicsData.length; i++) { const data = this.graphicsData[i]; diff --git a/packages/ranuts/src/utils/visual/style/fill.ts b/packages/ranuts/src/utils/visual/style/fill.ts index a0ee90c5b..d5dab8fac 100644 --- a/packages/ranuts/src/utils/visual/style/fill.ts +++ b/packages/ranuts/src/utils/visual/style/fill.ts @@ -9,11 +9,9 @@ export class Fill { public clone(): Fill { const obj = new Fill(); - obj.color = this.color; obj.alpha = this.alpha; obj.visible = this.visible; - return obj; } diff --git a/packages/ranuts/src/utils/visual/style/line.ts b/packages/ranuts/src/utils/visual/style/line.ts index e9e348444..d01271f78 100644 --- a/packages/ranuts/src/utils/visual/style/line.ts +++ b/packages/ranuts/src/utils/visual/style/line.ts @@ -9,7 +9,6 @@ export class Line extends Fill { public clone(): Line { const obj = new Line(); - obj.color = this.color; obj.alpha = this.alpha; obj.visible = this.visible; @@ -17,13 +16,11 @@ export class Line extends Fill { obj.cap = this.cap; obj.join = this.join; obj.miterLimit = this.miterLimit; - return obj; } public reset(): void { super.reset(); - this.color = '#ffffff'; this.width = 0; this.cap = LINE_CAP.BUTT; diff --git a/packages/ranuts/src/utils/visual/types.ts b/packages/ranuts/src/utils/visual/types.ts index bba4a7020..3a73ee30a 100644 --- a/packages/ranuts/src/utils/visual/types.ts +++ b/packages/ranuts/src/utils/visual/types.ts @@ -2,7 +2,7 @@ import type { LINE_CAP, LINE_JOIN, RENDERER_TYPE } from '@/utils/visual/enums'; export interface IApplicationOptions { prefer?: RENDERER_TYPE.CANVAS | RENDERER_TYPE.WEB_GL | RENDERER_TYPE.WEB_GPU; // 使用哪种 renderer - view: HTMLCanvasElement; + view?: HTMLCanvasElement; backgroundColor?: string; backgroundAlpha?: number; }