import { SPoint } from "./index"; import {SStringBuilder} from "@persagy-web/base/lib"; /** * Path对象 * * @author 庞利祥(sybotan@126.com) */ export class SPath2D { /** 内部path对象 */ _path = new Path2D(); private svgBuilder = new SStringBuilder(); /** * svg数据值 */ svgPath(): string { return this.svgBuilder.toString(" "); } // Function svgPath() /** * 添加路径 * * @param path 添加的路径 */ addPath(path: SPath2D): void { this._path.addPath(path._path); this.svgBuilder.append(path.svgBuilder.toString(" ")) } // Function addPath() /** * 移动到指定位置 * * @param x x坐标 * @param y y坐标 */ moveTo(x: number, y: number): void { this._path.moveTo(x, y); this.svgBuilder.append(`M ${x} ${y}`); } // Function moveTo() /** * 从当前位置到指定位置画直线 * * @param x x坐标 * @param y y坐标 */ lineTo(x: number, y: number): void { this._path.lineTo(x, y); this.svgBuilder.append(`L ${x} ${y}`); } // Function moveTo() /** * 矩形 * * @param x 左上角x坐标 * @param y 左上角y坐标 * @param width 宽度 * @param height 高度 */ rect(x: number, y: number, width: number, height: number): void { let r = x + width; let b = y + height; this._path.moveTo(x, y); this._path.lineTo(r, y); this._path.lineTo(r, b); this._path.lineTo(x, b); this._path.closePath(); this.svgBuilder.append(`M ${x} ${y} L${r} ${y} L${r} ${b} L${x} ${b} Z`); // // 逆时针 // this._path.moveTo(x, y); // this._path.lineTo(r, y); // this._path.lineTo(r, b); // this._path.lineTo(x, b); // this._path.closePath(); // this.svgBuilder.append(`M ${x} ${y} L${r} ${y} L${} ${} L${} ${} L${} ${}`); } // Function rect() /** * 绘制折线 * * @param points 折线折点 */ polyline(points: SPoint[]): void { if (points.length < 2) { return; } points.map((it: SPoint, index: number): void => { if (index == 0) { this._path.moveTo(it.x, it.y); this.svgBuilder.append(`M ${it.x} ${it.y}`); } else { this._path.lineTo(it.x, it.y); this.svgBuilder.append(`L ${it.x} ${it.y}`); } }); } // Function drawPolyline() /** * 绘制多边形 * * @param points 多边形顶点 */ polygon(points: SPoint[]): void { if (points.length < 3) { return; } points.map((it: SPoint, index: number): void => { if (index == 0) { this._path.moveTo(it.x, it.y); this.svgBuilder.append(`M ${it.x} ${it.y}`); } else { this._path.lineTo(it.x, it.y); this.svgBuilder.append(`L ${it.x} ${it.y}`); } }); this._path.closePath(); this.svgBuilder.append(`Z`); } // Functin polygon() /** * 椭圆弧 * * @param x 椭圆所在矩形X坐标 * @param y 椭圆所在矩形Y坐标 * @param width 椭圆所在矩形宽度 * @param height 椭圆所在矩形高度 * @param startAngle 开始角度(单位弧度) * @param endAngle 结束角度(单位弧度) */ static arc( x: number, y: number, width: number, height: number, startAngle: number, endAngle: number ): string { let a = width / 2; let b = height / 2; let p1 = SPath2D.arcPoint(a, b, startAngle); let p2 = SPath2D.arcPoint(a, b, endAngle); let large = SPath2D.largeArcFlag(startAngle, endAngle); p1.x = x + a + p1.x; p1.y = y + b - p1.y; p2.x = x + a + p2.x; p2.y = y + b - p2.y; return `M ${p1.x} ${p1.y} A ${a} ${b} 0 ${large} 0 ${p2.x} ${p2.y}`; } // Function arc() /** * 绘制椭圆弦弧 * * @param x 椭圆所在矩形X坐标 * @param y 椭圆所在矩形Y坐标 * @param width 椭圆所在矩形宽度 * @param height 椭圆所在矩形高度 * @param startAngle 开始角度(单位弧度) * @param endAngle 结束角度(单位弧度) */ static chord( x: number, y: number, width: number, height: number, startAngle: number, endAngle: number ): string { let a = width / 2; let b = height / 2; let p1 = SPath2D.arcPoint(a, b, startAngle); let p2 = SPath2D.arcPoint(a, b, endAngle); let large = SPath2D.largeArcFlag(startAngle, endAngle); p1.x = x + a + p1.x; p1.y = y + b - p1.y; p2.x = x + a + p2.x; p2.y = y + b - p2.y; return `M ${p1.x} ${p1.y} A ${a} ${b} 0 ${large} 0 ${p2.x} ${p2.y} Z`; } // Function chord() /** * 绘制椭圆饼 * * @param x 椭圆所在矩形X坐标 * @param y 椭圆所在矩形Y坐标 * @param width 椭圆所在矩形宽度 * @param height 椭圆所在矩形高度 * @param startAngle 开始角度(单位弧度) * @param endAngle 结束角度(单位弧度) */ static pie( x: number, y: number, width: number, height: number, startAngle: number, endAngle: number ): string { let a = width / 2; let b = height / 2; let p1 = SPath2D.arcPoint(a, b, startAngle); let p2 = SPath2D.arcPoint(a, b, endAngle); let large = SPath2D.largeArcFlag(startAngle, endAngle); p1.x = x + a + p1.x; p1.y = y + b - p1.y; p2.x = x + a + p2.x; p2.y = y + b - p2.y; return `M ${x + a} ${y + b} L ${p1.x} ${ p1.y } A ${a} ${b} 0 ${large} 0 ${p2.x} ${p2.y} Z`; } // Function pie() /** * 计算大弧标志 * * @param startAngle 启动角度(单位弧度) * @param endAngle 结束角度(单位弧度) */ static largeArcFlag(startAngle: number, endAngle: number): number { return ((Math.abs(endAngle - startAngle) * 180) / Math.PI) % 360 > 179.99999 ? 1 : 0; } // Function largeArcFlag() // https://blog.csdn.net/xiamentingtao/article/details/85804823 static arcPoint(a: number, b: number, angle: number): SPoint { let p = new SPoint(); if (angle >= 0) { angle = angle - Math.floor(angle / Math.PI / 2) * 2 * Math.PI; } else { angle = angle + Math.ceil(-angle / Math.PI / 2) * 2 * Math.PI; } if (Math.abs(Math.PI / 2 - angle) <= 0.000001) { p.x = 0; p.y = b; } else if (Math.abs((Math.PI * 3) / 2 - angle) <= 0.000001) { p.x = 0; p.y = -b; } else if (Math.PI / 2 < angle && angle < (Math.PI * 3) / 2) { p.x = -(a * b) / Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle)); p.y = -(a * b * Math.tan(angle)) / Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle)); } else { p.x = (a * b) / Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle)); p.y = (a * b * Math.tan(angle)) / Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle)); } return p; } // Function arcPoint() } // Class SPath2D