multiLine.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import { Control } from "./control";
  2. import { MultiLinePoint } from "../multiLinePoint";
  3. import { Nullable, AbstractMesh } from "babylonjs";
  4. import { Measure } from "../measure";
  5. /**
  6. * Class used to create multi line control
  7. */
  8. export class MultiLine extends Control {
  9. private _lineWidth: number = 1;
  10. private _dash: number[];
  11. private _points: Nullable<MultiLinePoint>[];
  12. private _minX: Nullable<number>;
  13. private _minY: Nullable<number>;
  14. private _maxX: Nullable<number>;
  15. private _maxY: Nullable<number>;
  16. /**
  17. * Creates a new MultiLine
  18. * @param name defines the control name
  19. */
  20. constructor(public name?: string) {
  21. super(name);
  22. this.isHitTestVisible = false;
  23. this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  24. this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  25. this._dash = [];
  26. this._points = [];
  27. }
  28. /** Gets or sets dash pattern */
  29. public get dash(): Array<number> {
  30. return this._dash;
  31. }
  32. public set dash(value: Array<number>) {
  33. if (this._dash === value) {
  34. return;
  35. }
  36. this._dash = value;
  37. this._markAsDirty();
  38. }
  39. /**
  40. * Gets point stored at specified index
  41. * @param index defines the index to look for
  42. * @returns the requested point if found
  43. */
  44. public getAt(index: number): MultiLinePoint {
  45. if (!this._points[index]) {
  46. this._points[index] = new MultiLinePoint(this);
  47. }
  48. return this._points[index] as MultiLinePoint;
  49. }
  50. /** Function called when a point is updated */
  51. public onPointUpdate = (): void => {
  52. this._markAsDirty();
  53. }
  54. /**
  55. * Adds new points to the point collection
  56. * @param items defines the list of items (mesh, control or 2d coordiantes) to add
  57. * @returns the list of created MultiLinePoint
  58. */
  59. public add(...items: (AbstractMesh | Control | { x: string | number, y: string | number })[]): MultiLinePoint[] {
  60. return items.map(item => this.push(item));
  61. }
  62. /**
  63. * Adds a new point to the point collection
  64. * @param item defines the item (mesh, control or 2d coordiantes) to add
  65. * @returns the created MultiLinePoint
  66. */
  67. public push(item?: (AbstractMesh | Control | { x: string | number, y: string | number })): MultiLinePoint {
  68. var point: MultiLinePoint = this.getAt(this._points.length);
  69. if (item == null) return point;
  70. if (item instanceof AbstractMesh) {
  71. point.mesh = item;
  72. }
  73. else if (item instanceof Control) {
  74. point.control = item;
  75. }
  76. else if (item.x != null && item.y != null) {
  77. point.x = item.x;
  78. point.y = item.y;
  79. }
  80. return point;
  81. }
  82. /**
  83. * Remove a specific value or point from the active point collection
  84. * @param value defines the value or point to remove
  85. */
  86. public remove(value: number | MultiLinePoint): void {
  87. var index: number;
  88. if (value instanceof MultiLinePoint) {
  89. index = this._points.indexOf(value);
  90. if (index === -1) {
  91. return;
  92. }
  93. }
  94. else {
  95. index = value;
  96. }
  97. var point: Nullable<MultiLinePoint> = this._points[index];
  98. if (!point) {
  99. return;
  100. }
  101. point.dispose();
  102. this._points.splice(index, 1);
  103. }
  104. /** Gets or sets line width */
  105. public get lineWidth(): number {
  106. return this._lineWidth;
  107. }
  108. public set lineWidth(value: number) {
  109. if (this._lineWidth === value) {
  110. return;
  111. }
  112. this._lineWidth = value;
  113. this._markAsDirty();
  114. }
  115. public set horizontalAlignment(value: number) {
  116. return;
  117. }
  118. public set verticalAlignment(value: number) {
  119. return;
  120. }
  121. protected _getTypeName(): string {
  122. return "MultiLine";
  123. }
  124. public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  125. context.save();
  126. if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
  127. context.shadowColor = this.shadowColor;
  128. context.shadowBlur = this.shadowBlur;
  129. context.shadowOffsetX = this.shadowOffsetX;
  130. context.shadowOffsetY = this.shadowOffsetY;
  131. }
  132. this._applyStates(context);
  133. if (this._processMeasures(parentMeasure, context)) {
  134. context.strokeStyle = this.color;
  135. context.lineWidth = this._lineWidth;
  136. context.setLineDash(this._dash);
  137. context.beginPath();
  138. var first: boolean = true; //first index is not necessarily 0
  139. this._points.forEach(point => {
  140. if (!point) {
  141. return;
  142. }
  143. if (first) {
  144. context.moveTo(point._point.x, point._point.y);
  145. first = false;
  146. }
  147. else {
  148. context.lineTo(point._point.x, point._point.y);
  149. }
  150. });
  151. context.stroke();
  152. }
  153. context.restore();
  154. }
  155. protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  156. this._minX = null;
  157. this._minY = null;
  158. this._maxX = null;
  159. this._maxY = null;
  160. this._points.forEach((point, index) => {
  161. if (!point) {
  162. return;
  163. }
  164. point.translate();
  165. if (this._minX == null || point._point.x < this._minX) this._minX = point._point.x;
  166. if (this._minY == null || point._point.y < this._minY) this._minY = point._point.y;
  167. if (this._maxX == null || point._point.x > this._maxX) this._maxX = point._point.x;
  168. if (this._maxY == null || point._point.y > this._maxY) this._maxY = point._point.y;
  169. });
  170. if (this._minX == null) this._minX = 0;
  171. if (this._minY == null) this._minY = 0;
  172. if (this._maxX == null) this._maxX = 0;
  173. if (this._maxY == null) this._maxY = 0;
  174. }
  175. public _measure(): void {
  176. if (this._minX == null || this._maxX == null || this._minY == null || this._maxY == null) {
  177. return;
  178. }
  179. this._currentMeasure.width = Math.abs(this._maxX - this._minX) + this._lineWidth;
  180. this._currentMeasure.height = Math.abs(this._maxY - this._minY) + this._lineWidth;
  181. }
  182. protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  183. if (this._minX == null || this._minY == null) {
  184. return;
  185. }
  186. this._currentMeasure.left = this._minX - this._lineWidth / 2;
  187. this._currentMeasure.top = this._minY - this._lineWidth / 2;
  188. }
  189. public dispose(): void {
  190. while (this._points.length > 0) {
  191. this.remove(this._points.length - 1);
  192. }
  193. super.dispose();
  194. }
  195. }