123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- /*
- * *********************************************************************************************************************
- *
- * !!
- * .F88X
- * X8888Y
- * .}888888N;
- * i888888N; .:! .I$WI:
- * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
- * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
- * +888888N; .8888888Y "&&8Y.}8,
- * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
- * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
- * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
- * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
- * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
- * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
- * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
- * .:R888888I
- * .&888888I Copyright (c) 2009-2020. 博锐尚格科技股份有限公司
- * ~8888'
- * .!88~ All rights reserved.
- *
- * *********************************************************************************************************************
- */
- import { SMatrix, SObject } from "@persagy-web/base";
- import { SPaintEngine } from "./engines/SPaintEngine";
- import {
- SBrush,
- SCanvasPaintEngine,
- SCanvasView,
- SFont,
- SLine,
- SPath,
- SPen,
- SPoint,
- SRect,
- SSize
- } from "./";
- import { SCompositeType } from "./enums/SCompositeType";
- import { SArrow } from "./types/SArrow";
- import { SArrowStyleType } from "./enums/SArrowStyleType";
- import { SShadow } from "./SShadow";
- /**
- * Painter
- *
- * @author 庞利祥(sybotan@126.com)
- */
- export class SPainter extends SObject {
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // 属性定义
- /** 绘制引擎 */
- private readonly engine: SPaintEngine;
- /** 画笔 */
- get pen(): SPen {
- return this.engine.state.pen;
- } // Get pen
- set pen(value: SPen) {
- this.engine.state.pen = value;
- } // Set pen
- /** 画刷 */
- get brush(): SBrush {
- return this.engine.state.brush;
- } // Get brush
- set brush(value: SBrush) {
- this.engine.state.brush = value;
- } // Set brush
- /** 字体属性 */
- get font(): SFont {
- return this.engine.state.font;
- } // Get font
- set font(value: SFont) {
- this.engine.state.font = value;
- this.engine.changeFont(value);
- } // Set font
- /** 融合属性 */
- get composite(): number {
- return this.engine.state._composite;
- } // Get composite
- set composite(value: number) {
- this.engine.state._composite = value;
- } // Set composite
- /** 阴影设置 */
- get shadow(): SShadow {
- return this.engine.state.shadow;
- } // Get shadow
- set shadow(value: SShadow) {
- this.engine.state.shadow = value;
- } // Set shadow
- /** 变换矩阵 */
- get worldTransform(): SMatrix {
- return this.engine.state.matrix;
- } // Get worldTransform
- /**
- * 构造函数
- *
- * @param engine 绘制引擎
- */
- constructor(engine: SCanvasView | SPaintEngine) {
- super();
- if (engine instanceof SCanvasView) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.engine = new SCanvasPaintEngine(engine.canvas!!);
- } else {
- this.engine = engine;
- }
- this.pen = new SPen();
- this.brush = new SBrush();
- this.font = new SFont();
- this.composite = SCompositeType.SourceOver;
- this.shadow = new SShadow();
- } // Constructor()
- /**
- * 保存painter状态
- */
- save(): void {
- this.engine.save();
- } // Function save()
- /**
- * 恢复painter状态
- */
- restore(): void {
- this.engine.restore();
- } // Function restore()
- // =================================================================================================================
- // 变换相关
- /**
- * 平移变换
- *
- * @param x X轴方向平移
- * @param y Y辆方向平移
- */
- translate(x: number, y: number): void {
- this.engine.translate(x, y);
- } // Function translate()
- /**
- * 缩放
- *
- * @param x X轴方向缩放
- * @param y Y辆方向缩放
- */
- scale(x: number, y: number): void {
- this.engine.scale(x, y);
- } // Function scale()
- /**
- * 旋转
- *
- * @param angle 旋转角度(单位弧度)
- */
- rotate(angle: number): void {
- this.engine.rotate(angle);
- } // Function rotate()
- /**
- * 将当前的变形矩阵乘上一个基于自身参数的矩阵
- *
- * @param m11 水平方向的缩放
- * @param m12 水平方向的倾斜偏移
- * @param m21 竖直方向的倾斜偏移
- * @param m22 竖直方向的缩放
- * @param dx 水平方向的移动
- * @param dy 竖直方向的移动
- */
- transform(
- m11: number,
- m12: number,
- m21: number,
- m22: number,
- dx: number,
- dy: number
- ): void {
- this.engine.transform(m11, m12, m21, m22, dx, dy);
- } // Function transform()
- /**
- * 将当前的变形矩阵重置为单位矩阵,再将当前的变形矩阵乘上一个基于自身参数的矩阵
- *
- * @param m11 水平方向的缩放
- * @param m12 水平方向的倾斜偏移
- * @param m21 竖直方向的倾斜偏移
- * @param m22 竖直方向的缩放
- * @param dx 水平方向的移动
- * @param dy 竖直方向的移动
- */
- setTransform(
- m11: number,
- m12: number,
- m21: number,
- m22: number,
- dx: number,
- dy: number
- ): void {
- this.engine.setTransform(m11, m12, m21, m22, dx, dy);
- } // Function transform()
- /**
- * 重置当前变形为单位矩阵。等价于调用setTransform(1, 0, 0, 1, 0, 0)
- */
- resetTransform(): void {
- this.engine.resetTransform();
- } // Function resetTransform()
- // =================================================================================================================
- // 绘制相关
- /**
- * 设置裁剪路径
- *
- * @param path 裁剪路径
- */
- setClip(path: Path2D): void {
- this.engine.setClip(path);
- } // Function setClip()
- /**
- * 清空矩形区域
- *
- * @param rect 矩形
- */
- clearRect(rect: SRect): void;
- /**
- * 清空矩形区域
- *
- * @param leftTop 左上角坐标
- * @param rightBottom 右下角坐标
- */
- clearRect(leftTop: SPoint, rightBottom: SPoint): void;
- /**
- * 清空矩形区域
- *
- * @param leftTop 左上角坐标
- * @param size 大小
- */
- clearRect(leftTop: SPoint, size: SSize): void;
- /**
- * 清空矩形区域
- *
- * @param x X坐标
- * @param y Y坐标
- * @param w 宽度
- * @param h 高度
- */
- clearRect(x: number, y: number, w: number, h: number): void;
- /**
- * 清空矩形区域(重载实现)
- *
- * @param x X坐标 | 左上角坐标 | 矩形
- * @param y Y坐标 | 右下角坐标 | 大小
- * @param w 宽度
- * @param h 高度
- */
- clearRect(
- x: number | SPoint | SRect,
- y?: number | SPoint | SSize,
- w?: number,
- h?: number
- ): void {
- if (x instanceof SRect) {
- this.engine.clearRect(x);
- } else if (x instanceof SPoint && y instanceof SPoint) {
- this.engine.clearRect(new SRect(x, y));
- } else if (x instanceof SPoint && y instanceof SSize) {
- this.engine.clearRect(new SRect(x, y));
- } else {
- this.engine.clearRect(
- new SRect(x as number, y as number, w as number, h as number)
- );
- }
- } // Function clearRect()
- /**
- * 绘制矩形
- *
- * @param rect 矩形
- */
- drawRect(rect: SRect): void;
- /**
- * 绘制矩形
- *
- * @param leftTop 左上角坐标
- * @param rightBottom 右下角坐标
- */
- drawRect(leftTop: SPoint, rightBottom: SPoint): void;
- /**
- * 绘制矩形
- *
- * @param leftTop 左上角坐标
- * @param size 大小
- */
- drawRect(leftTop: SPoint, size: SSize): void;
- /**
- * 绘制矩形
- *
- * @param x X坐标
- * @param y Y坐标
- * @param w 宽度
- * @param h 高度
- */
- drawRect(x: number, y: number, w: number, h: number): void;
- /**
- * 绘制矩形
- *
- * @param x X坐标 | 左上角坐标 | 矩形
- * @param y Y坐标 | 右下角坐标 | 大小
- * @param w 宽度
- * @param h 高度
- */
- drawRect(
- x: number | SPoint | SRect,
- y?: number | SPoint | SSize,
- w?: number,
- h?: number
- ): void {
- if (x instanceof SRect) {
- this.engine.drawRect(x);
- } else if (x instanceof SPoint && y instanceof SPoint) {
- this.engine.drawRect(new SRect(x, y));
- } else if (x instanceof SPoint && y instanceof SSize) {
- this.engine.drawRect(new SRect(x, y));
- } else {
- this.engine.drawRect(
- new SRect(x as number, y as number, w as number, h as number)
- );
- }
- } // Function drawRect()
- /**
- * 绘制带导角矩形
- *
- * @param rect 矩形
- * @param r 导角半径
- */
- drawRoundRect(rect: SRect, r: number): void;
- /**
- * 绘制带导角矩形
- *
- * @param pos 左上角位置
- * @param size 大小
- * @param r 导角半径
- */
- drawRoundRect(pos: SPoint, size: SSize, r: number): void;
- /**
- * 绘制带导角矩形
- *
- * @param x X坐标
- * @param y Y坐标
- * @param w 宽度
- * @param h 高度
- * @param r 导角半径
- */
- drawRoundRect(x: number, y: number, w: number, h: number, r: number): void;
- /**
- * 绘制带导角矩形
- *
- * @param x X坐标
- * @param y Y坐标
- * @param w 宽度
- * @param h 高度
- * @param radius 导角半径
- */
- drawRoundRect(
- x: number | SPoint | SRect,
- y: number | SSize,
- w?: number,
- h?: number,
- radius?: number
- ): void {
- let rect: SRect | null;
- let r: number | null;
- if (x instanceof SRect) {
- rect = x;
- r = y as number;
- } else if (x instanceof SPoint && y instanceof SSize) {
- rect = new SRect(x, y);
- r = w as number;
- } else {
- rect = new SRect(
- x as number,
- y as number,
- w as number,
- h as number
- );
- r = radius as number;
- }
- if (rect != null && r != null) {
- this.engine.drawRoundRect(rect, r);
- }
- } // Function drawRoundRect()
- /**
- * 绘制圆形
- *
- * @param cx 圆心X坐标
- * @param cy 圆心X坐标
- * @param r 圆半径
- */
- drawCircle(cx: number, cy: number, r: number): void {
- this.engine.drawCircle(cx, cy, r);
- } // Function drawCircle()
- /**
- * 绘制椭圆
- *
- * @param cx 圆点X坐标
- * @param cy 圆点Y坐标
- * @param rx 水平半径
- * @param ry 垂直半径
- */
- drawEllipse(cx: number, cy: number, rx: number, ry: number): void {
- this.engine.drawEllipse(cx, cy, rx, ry);
- } // Function drawEllipse()
- /**
- * 绘制一条线段
- *
- * @param line 线段
- */
- drawLine(line: SLine): void;
- /**
- * 绘制一条线段
- *
- * @param p1 启点坐标
- * @param p2 终点坐标
- */
- drawLine(p1: SPoint, p2: SPoint): void;
- /**
- * 绘制一条线段
- *
- * @param x1 启点X坐标
- * @param y1 启点Y坐标
- * @param x2 终点X坐标
- * @param y2 终点Y坐标
- */
- drawLine(x1: number, y1: number, x2: number, y2: number): void;
- /**
- * 绘制一条线段(重载实现)
- *
- * @param x1 启点X坐标 | 起点1坐标 | 线段 |
- * @param y1 启点Y坐标 | 终点坐标
- * @param x2 终点X坐标
- * @param y2 终点Y坐标
- */
- drawLine(
- x1: number | SPoint | SLine,
- y1?: number | SPoint,
- x2?: number,
- y2?: number
- ): void {
- if (x1 instanceof SLine) {
- this.engine.drawLine(x1);
- } else if (x1 instanceof SPoint && y1 instanceof SPoint) {
- this.engine.drawLine(new SLine(x1, y1));
- } else {
- this.engine.drawLine(
- new SLine(
- x1 as number,
- y1 as number,
- x2 as number,
- y2 as number
- )
- );
- }
- } // Function drawLine()
- /**
- * 绘制折线
- *
- * @param points 折线折点
- */
- drawPolyline(points: SPoint[]): void {
- this.engine.drawPolyline(points);
- } // Function drawPolyline()
- /**
- * 绘制多边形
- *
- * @param points 多边形顶点
- */
- drawPolygon(points: SPoint[]): void {
- this.engine.drawPolygon(points);
- } // Function drawPolygon()
- /**
- * 绘制路径
- *
- * @param path 路径
- */
- drawPath(path: SPath): void {
- this.engine.drawPath(path);
- } // Function drawPath()
- /**
- * 绘制文本
- *
- * @param text 文本内容
- * @param x X坐标
- * @param y Y坐标
- * @param maxWidth 最大宽度
- */
- drawText(text: string, x: number, y: number, maxWidth?: number): void {
- this.engine.drawText(text, x, y, maxWidth);
- } // Function drawText()
- /**
- * 绘制图片
- *
- * @param img 图片
- * @param x X坐标
- * @param y Y坐标
- * @param width 宽度
- * @param height 高度
- */
- drawImage(
- img: CanvasImageSource,
- x: number,
- y: number,
- width?: number,
- height?: number
- ): void {
- this.engine.drawImage(img, x, y, width, height);
- } // Function drawImage()
- /**
- * painter转实现view象素
- *
- * @param p 绘制坐标
- */
- toPx(p: number): number {
- return p / this.engine.state.matrix.a;
- } // Function painterToView()
- /**
- * 预测量文本宽度
- *
- * @param text 文本字符
- * @return 文本所占长度像素
- * */
- textWidth(text: string): number {
- return this.engine.textWidth(text);
- }
- /**
- * 绘制带箭头的线段
- *
- * @param line 线段
- * @param style 末端样式
- */
- drawArrowLine(line: SLine, style?: SArrow): void;
- /**
- * 绘制带箭头的线段
- *
- * @param p1 启点坐标
- * @param p2 终点坐标
- * @param style 末端样式
- */
- drawArrowLine(p1: SPoint, p2: SPoint, style?: SArrow): void;
- /**
- * 绘制带箭头的线段
- *
- * @param x1 启点X坐标
- * @param y1 启点Y坐标
- * @param x2 终点X坐标
- * @param y2 终点Y坐标
- * @param style 末端样式
- */
- drawArrowLine(
- x1: number,
- y1: number,
- x2: number,
- y2: number,
- style?: SArrow
- ): void;
- /**
- * 绘制带箭头的线段
- *
- * @param x1 启点X坐标
- * @param y1 启点Y坐标
- * @param x2 终点X坐标
- * @param y2 终点Y坐标
- * @param st 线段两端样式
- */
- drawArrowLine(
- x1: number | SPoint | SLine,
- y1?: number | SPoint | SArrow,
- x2?: number | SArrow,
- y2?: number,
- st?: SArrow
- ): void {
- let line: SLine, style: SArrow;
- if (x1 instanceof SLine) {
- line = x1;
- style = y1 as SArrow;
- } else if (x1 instanceof SPoint && y1 instanceof SPoint) {
- line = new SLine(x1, y1);
- style = x2 as SArrow;
- } else {
- line = new SLine(
- x1 as number,
- y1 as number,
- x2 as number,
- y2 as number
- );
- style = st as SArrow;
- }
- this.engine.drawLine(line);
- if (style) {
- if (style.begin) {
- if (style.begin == SArrowStyleType.Basic) {
- this.drawBasicArrow(line, false);
- } else if (style.begin == SArrowStyleType.Triangle) {
- this.drawTriangleArrow(line, false);
- } else if (style.begin == SArrowStyleType.Diamond) {
- this.drawDiamondArrow(line, false);
- } else if (style.begin == SArrowStyleType.Square) {
- this.drawSquareArrow(line, false);
- } else if (style.begin == SArrowStyleType.Circle) {
- this.drawCircleArrow(line, false);
- }
- }
- if (style.end) {
- if (style.end == SArrowStyleType.Basic) {
- this.drawBasicArrow(line, true);
- } else if (style.end == SArrowStyleType.Triangle) {
- this.drawTriangleArrow(line, true);
- } else if (style.end == SArrowStyleType.Diamond) {
- this.drawDiamondArrow(line, true);
- } else if (style.end == SArrowStyleType.Square) {
- this.drawSquareArrow(line, true);
- } else if (style.end == SArrowStyleType.Circle) {
- this.drawCircleArrow(line, true);
- }
- }
- }
- } // Function drawArrowLine()
- /**
- * 私有计算方法-绘制线段末端标准箭头
- *
- * @param line 要加末端样式的线段
- * @param isEnd 是否为结束位置
- * */
- private drawBasicArrow(line: SLine, isEnd: boolean = true): void {
- // 定义箭头长度
- const d = this.toPx(10);
- // 箭头横坐标
- const x1 = d * Math.cos(Math.PI / 4);
- // 箭头纵坐标
- const y1 = d * Math.sin(Math.PI / 4);
- // 线段与x轴夹角
- const fo = Math.atan(line.dy / line.dx);
- this.save();
- // 是否为终点画箭头
- if (isEnd) {
- this.translate(line.x2, line.y2);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolyline([
- new SPoint(-x1, y1),
- new SPoint(0, 0),
- new SPoint(-x1, -y1)
- ]);
- } else {
- this.translate(line.x1, line.y1);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolyline([
- new SPoint(x1, y1),
- new SPoint(0, 0),
- new SPoint(x1, -y1)
- ]);
- }
- this.restore();
- } // Function drawArrow()
- /**
- * 私有计算方法-绘制线段末端三角形箭头
- *
- * @param line 要加末端样式的线段
- * @param isEnd 是否为结束位置
- * */
- private drawTriangleArrow(line: SLine, isEnd: boolean = true): void {
- // 定义箭头长度
- const d = this.toPx(10);
- // 箭头横坐标
- const x1 = d * Math.cos(Math.PI / 12);
- // 箭头纵坐标
- const y1 = d * Math.sin(Math.PI / 12);
- // 线段与x轴夹角
- const fo = Math.atan(line.dy / line.dx);
- this.save();
- // 是否为终点画箭头
- if (isEnd) {
- this.translate(line.x2, line.y2);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolygon([
- new SPoint(-x1, y1),
- new SPoint(0, 0),
- new SPoint(-x1, -y1)
- ]);
- } else {
- this.translate(line.x1, line.y1);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolygon([
- new SPoint(x1, y1),
- new SPoint(0, 0),
- new SPoint(x1, -y1)
- ]);
- }
- this.restore();
- } // Function drawTriangleArrow()
- /**
- * 私有计算方法-绘制线段末端菱形箭头
- *
- * @param line 要加末端样式的线段
- * @param isEnd 是否为结束位置
- * */
- private drawDiamondArrow(line: SLine, isEnd: boolean = true): void {
- // 定义箭头长度
- const d = this.toPx(5);
- // 箭头横坐标
- const x1 = d * Math.cos(Math.PI / 4);
- // 箭头纵坐标
- const y1 = d * Math.sin(Math.PI / 4);
- // 线段与x轴夹角
- const fo = Math.atan(line.dy / line.dx);
- this.save();
- // 是否为终点画箭头
- if (isEnd) {
- this.translate(line.x2, line.y2);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolygon([
- new SPoint(-x1, y1),
- new SPoint(0, 0),
- new SPoint(-x1, -y1),
- new SPoint(-Math.sqrt(2) * d, 0)
- ]);
- } else {
- this.translate(line.x1, line.y1);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolygon([
- new SPoint(x1, y1),
- new SPoint(0, 0),
- new SPoint(x1, -y1),
- new SPoint(Math.sqrt(2) * d, 0)
- ]);
- }
- this.restore();
- } // Function drawDiamondArrow()
- /**
- * 私有计算方法-绘制线段末端方形箭头
- *
- * @param line 要加末端样式的线段
- * @param isEnd 是否为结束位置
- * */
- private drawSquareArrow(line: SLine, isEnd: boolean = true): void {
- // 定义箭头长度
- const d = this.toPx(5);
- // 线段与x轴夹角
- const fo = Math.atan(line.dy / line.dx);
- this.save();
- // 是否为终点画箭头
- if (isEnd) {
- this.translate(line.x2, line.y2);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolygon([
- new SPoint(-d, d / 2),
- new SPoint(0, d / 2),
- new SPoint(0, -d / 2),
- new SPoint(-d, -d / 2)
- ]);
- } else {
- this.translate(line.x1, line.y1);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawPolygon([
- new SPoint(0, d / 2),
- new SPoint(d, d / 2),
- new SPoint(d, -d / 2),
- new SPoint(0, -d / 2)
- ]);
- }
- this.restore();
- } // Function drawSquareArrow()
- /**
- * 私有计算方法-绘制线段末端圆形箭头
- *
- * @param line 要加末端样式的线段
- * @param isEnd 是否为结束位置
- * */
- private drawCircleArrow(line: SLine, isEnd: boolean = true): void {
- // 定义箭头长度
- const d = this.toPx(5);
- // 线段与x轴夹角
- const fo = Math.atan(line.dy / line.dx);
- // 是否为终点画箭头
- this.save();
- if (isEnd) {
- this.translate(line.x2, line.y2);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawCircle(-d / 2, 0, d / 2);
- } else {
- this.translate(line.x1, line.y1);
- this.rotate((fo * 180) / Math.PI);
- this.engine.drawCircle(d / 2, 0, d / 2);
- }
- this.restore();
- } // Function drawCircleArrow()
- } // Class SPainter
|