SCircleCornerPolylineItem.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * *********************************************************************************************************************
  3. *
  4. * !!
  5. * .F88X
  6. * X8888Y
  7. * .}888888N;
  8. * i888888N; .:! .I$WI:
  9. * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
  10. * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
  11. * +888888N; .8888888Y "&&8Y.}8,
  12. * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
  13. * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
  14. * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
  15. * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
  16. * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
  17. * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
  18. * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
  19. * .:R888888I
  20. * .&888888I Copyright (c) 2009-2021. 博锐尚格科技股份有限公司
  21. * ~8888'
  22. * .!88~ All rights reserved.
  23. *
  24. * *********************************************************************************************************************
  25. */
  26. import {
  27. SGraphItem,
  28. SGraphStyleItem,
  29. SLineStyle
  30. } from "@persagy-web/graph/lib";
  31. import { SPoint, SPainter, SRect, SPath } from "@persagy-web/draw";
  32. /**
  33. * 圆角折线 item
  34. *
  35. * @author 郝建龙 <haojianlong@sagacloud.com>
  36. */
  37. export default class SCircleCornerPolylineItem extends SGraphStyleItem {
  38. /** X 坐标最小值 */
  39. private minX = Number.MAX_SAFE_INTEGER;
  40. /** X 坐标最大值 */
  41. private maxX = Number.MIN_SAFE_INTEGER;
  42. /** Y 坐标最小值 */
  43. private minY = Number.MAX_SAFE_INTEGER;
  44. /** Y 坐标最大值 */
  45. private maxY = Number.MIN_SAFE_INTEGER;
  46. /** 折点信息 */
  47. pointList: SPoint[] = [];
  48. /** 圆角半径 */
  49. private _radius: number = 5;
  50. get radius(): number {
  51. return this._radius;
  52. }
  53. set radius(v: number) {
  54. if (v === this._radius) {
  55. return;
  56. }
  57. this._radius = v;
  58. this.update();
  59. }
  60. /** 圆角半径是否需要转像素值 */
  61. radiusIsPx: boolean = false;
  62. /** path 对象 */
  63. path: SPath = new SPath();
  64. /**
  65. * 构造函数
  66. */
  67. constructor(parent: SGraphItem | null, list: SPoint[]) {
  68. super(parent);
  69. this.pointList = list;
  70. }
  71. /**
  72. * Item 对象边界区域
  73. *
  74. * @return 外接矩阵
  75. */
  76. boundingRect(): SRect {
  77. if (this.pointList.length) {
  78. this.minX = this.pointList[0].x;
  79. this.maxX = this.pointList[0].x;
  80. this.minY = this.pointList[0].y;
  81. this.maxY = this.pointList[0].y;
  82. this.pointList.forEach((it): void => {
  83. let x = it.x,
  84. y = it.y;
  85. // 如果数据 x 坐标小于 x 坐标最小值
  86. if (x < this.minX) {
  87. this.minX = x;
  88. }
  89. // 如果数据 y 坐标小于 y 坐标最小值
  90. if (y < this.minY) {
  91. this.minY = y;
  92. }
  93. // 如果数据 x 坐标大于 x 坐标最小值
  94. if (x > this.maxX) {
  95. this.maxX = x;
  96. }
  97. // 如果数据 y 坐标大于 y 坐标最小值
  98. if (y > this.maxY) {
  99. this.maxY = y;
  100. }
  101. });
  102. }
  103. return new SRect(
  104. this.minX,
  105. this.minY,
  106. this.maxX - this.minX,
  107. this.maxY - this.minY
  108. );
  109. }
  110. /**
  111. * 根据点集生成 path 对象
  112. *
  113. * @param list 需要生成的点击
  114. * @param r 拐点处圆角半径
  115. */
  116. generatePath(list: SPoint[], r: number = 0): void {
  117. const len = list.length;
  118. if (len) {
  119. this.path = new SPath();
  120. this.path.moveTo(list[0].x, list[0].y);
  121. for (let i = 1; i < len - 1; i++) {
  122. const temp = list[i];
  123. const next = list[i + 1];
  124. this.path.arcTo(temp.x, temp.y, next.x, next.y, r);
  125. }
  126. const last = list[len - 1];
  127. this.path.lineTo(last.x, last.y);
  128. }
  129. }
  130. /**
  131. * Item 绘制操作
  132. *
  133. * @param painter 绘制对象
  134. */
  135. onDraw(painter: SPainter): void {
  136. // 绘制基本图形
  137. painter.pen.color = this.strokeColor;
  138. // 线宽是否缩放
  139. if (this.widthIsPx) {
  140. painter.pen.lineWidth = painter.toPx(this.lineWidth);
  141. } else {
  142. painter.pen.lineWidth = this.lineWidth;
  143. }
  144. // 虚线
  145. if (this.lineStyle == SLineStyle.Dashed) {
  146. painter.pen.lineDash = [
  147. painter.toPx(this.lineWidth * 3),
  148. painter.toPx(this.lineWidth * 7)
  149. ];
  150. } else if (this.lineStyle == SLineStyle.Dotted) {
  151. // 点线
  152. painter.pen.lineDash = [
  153. painter.toPx(this.lineWidth),
  154. painter.toPx(this.lineWidth)
  155. ];
  156. }
  157. const temp = JSON.parse(JSON.stringify(this.pointList));
  158. // 折线点数2个以上
  159. if (temp.length > 2) {
  160. let radius = this.radius;
  161. if (this.radiusIsPx) {
  162. radius = painter.toPx(this.radius);
  163. }
  164. this.generatePath(temp, radius);
  165. painter.drawPath(this.path);
  166. } else {
  167. // 否则
  168. painter.drawPolyline(temp);
  169. }
  170. }
  171. }