UNPKG

@turbox3d/graphic-component-pixi

Version:

Graphic component library based on pixi

127 lines (117 loc) 3.95 kB
import * as THREE from 'three'; import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'; import * as PIXI from 'pixi.js'; interface IXY { x: number; y: number; } interface ITransform { offset?: IXY; size?: number; rotation?: number; } function drawLineByShape(graphics: PIXI.Graphics, curve: THREE.Curve<THREE.Vector2>, matrix: THREE.Matrix3) { const c = curve.toJSON() as any; switch (curve.type) { case 'QuadraticBezierCurve': { const v0 = new THREE.Vector2().fromArray(c.v0).applyMatrix3(matrix); const v1 = new THREE.Vector2().fromArray(c.v1).applyMatrix3(matrix); const v2 = new THREE.Vector2().fromArray(c.v2).applyMatrix3(matrix); graphics.bezierCurveTo(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); break; } case 'LineCurve': { const v = new THREE.Vector2().fromArray(c.v2).applyMatrix3(matrix); graphics.lineTo(v.x, v.y); break; } default: break; } } /** * 绘制字体 * @param {PIXI} graphics graphics * @param {string} string 文本 * @param {ITransform} transform 绘制的 model matrix decompose */ export async function drawText( graphics: PIXI.Graphics, string: string | number, transform?: ITransform, options?: { color?: number; fontUrl?: string; } ) { // generate shapes const defaultOps = { color: 0x131313, fontUrl: '' }; const ops = options || defaultOps; const size = transform?.size || 5; const font = await new FontLoader().loadAsync(ops.fontUrl || defaultOps.fontUrl); const str = string.toString(); const textShapes = font.generateShapes(str, size); // matrix parameter const halfH = size / 2; const halfW = str.length * 0.7 * halfH; const offset = { x: transform?.offset?.x || 0, y: transform?.offset?.y || 0 }; const rotation = transform?.rotation || 0; // compose matrix const matrix = new THREE.Matrix3(); const cos = Math.cos(rotation); const sin = Math.sin(rotation); matrix.set( cos, -sin, -cos * halfW + sin * halfH + offset.x, sin, cos, -sin * halfW - cos * halfH + offset.y, 1, 1, 1 ); // draw for (let i = 0; i < textShapes.length; i++) { graphics.beginFill(ops.color || defaultOps.color); const shape: THREE.Shape = textShapes[i]; const shapeCurveLength = shape.curves.length; const curve = shape.curves[shapeCurveLength - 1]; const v = new THREE.Vector2().fromArray((curve.toJSON() as any).v2).clone().applyMatrix3(matrix); graphics.moveTo(v.x, v.y); for (let j = 0; j < shapeCurveLength; j++) { drawLineByShape(graphics, shape.curves[j], matrix); } const holes = shape.holes; for (let j = 0; j < holes.length; j++) { const hole: THREE.Path = holes[j]; graphics.beginHole(); const v2 = hole.currentPoint.applyMatrix3(matrix); graphics.moveTo(v2.x, v2.y); for (let k = 0; k < hole.curves.length; k++) { drawLineByShape(graphics, hole.curves[k], matrix); } graphics.endHole(); } } } // export function computeFlowLayoutPosition(central: boolean, margin?: string) { // const [posX, posY] = central ? [0 - this.view.width / 2, 0 - this.view.height / 2] : [0, 0]; // const [top, right, bottom, left] = margin?.split(',').map(n => parseInt(n, 10)) || [0, 0, 0, 0]; // const parentNode = this._vNode.parent; // if (parentNode && parentNode.instance instanceof Container2d) { // this.view.position.x = posX + left; // if (parentNode.child === this._vNode) { // this.view.position.y = posY + top; // } // if (this._vNode.sibling) { // const siblingMargin = this._vNode.sibling?.props.margin?.split(',').map(n => parseInt(n, 10)) || [0, 0, 0, 0]; // if (this._vNode.sibling?.instance instanceof Mesh2D) { // ((this._vNode.sibling?.instance as any).view as PIXI.Container).position.y = this.view.position.y + this.view.height + bottom + siblingMargin[0]; // } // } // } // }