line.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import { Control } from "./control";
  2. import { ValueAndUnit } from "../valueAndUnit";
  3. import { Nullable, Observer, Vector3, Scene, Tools, Matrix } from "babylonjs";
  4. import { Measure } from "../measure";
  5. /** Class used to render 2D lines */
  6. export class Line extends Control {
  7. private _lineWidth = 1;
  8. private _x1 = new ValueAndUnit(0);
  9. private _y1 = new ValueAndUnit(0);
  10. private _x2 = new ValueAndUnit(0);
  11. private _y2 = new ValueAndUnit(0);
  12. private _dash = new Array<number>();
  13. private _connectedControl: Control;
  14. private _connectedControlDirtyObserver: Nullable<Observer<Control>>;
  15. /** Gets or sets the dash pattern */
  16. public get dash(): Array<number> {
  17. return this._dash;
  18. }
  19. public set dash(value: Array<number>) {
  20. if (this._dash === value) {
  21. return;
  22. }
  23. this._dash = value;
  24. this._markAsDirty();
  25. }
  26. /** Gets or sets the control connected with the line end */
  27. public get connectedControl(): Control {
  28. return this._connectedControl;
  29. }
  30. public set connectedControl(value: Control) {
  31. if (this._connectedControl === value) {
  32. return;
  33. }
  34. if (this._connectedControlDirtyObserver && this._connectedControl) {
  35. this._connectedControl.onDirtyObservable.remove(this._connectedControlDirtyObserver);
  36. this._connectedControlDirtyObserver = null;
  37. }
  38. if (value) {
  39. this._connectedControlDirtyObserver = value.onDirtyObservable.add(() => this._markAsDirty());
  40. }
  41. this._connectedControl = value;
  42. this._markAsDirty();
  43. }
  44. /** Gets or sets start coordinates on X axis */
  45. public get x1(): string | number {
  46. return this._x1.toString(this._host);
  47. }
  48. public set x1(value: string | number) {
  49. if (this._x1.toString(this._host) === value) {
  50. return;
  51. }
  52. if (this._x1.fromString(value)) {
  53. this._markAsDirty();
  54. }
  55. }
  56. /** Gets or sets start coordinates on Y axis */
  57. public get y1(): string | number {
  58. return this._y1.toString(this._host);
  59. }
  60. public set y1(value: string | number) {
  61. if (this._y1.toString(this._host) === value) {
  62. return;
  63. }
  64. if (this._y1.fromString(value)) {
  65. this._markAsDirty();
  66. }
  67. }
  68. /** Gets or sets end coordinates on X axis */
  69. public get x2(): string | number {
  70. return this._x2.toString(this._host);
  71. }
  72. public set x2(value: string | number) {
  73. if (this._x2.toString(this._host) === value) {
  74. return;
  75. }
  76. if (this._x2.fromString(value)) {
  77. this._markAsDirty();
  78. }
  79. }
  80. /** Gets or sets end coordinates on Y axis */
  81. public get y2(): string | number {
  82. return this._y2.toString(this._host);
  83. }
  84. public set y2(value: string | number) {
  85. if (this._y2.toString(this._host) === value) {
  86. return;
  87. }
  88. if (this._y2.fromString(value)) {
  89. this._markAsDirty();
  90. }
  91. }
  92. /** Gets or sets line width */
  93. public get lineWidth(): number {
  94. return this._lineWidth;
  95. }
  96. public set lineWidth(value: number) {
  97. if (this._lineWidth === value) {
  98. return;
  99. }
  100. this._lineWidth = value;
  101. this._markAsDirty();
  102. }
  103. /** Gets or sets horizontal alignment */
  104. public set horizontalAlignment(value: number) {
  105. return;
  106. }
  107. /** Gets or sets vertical alignment */
  108. public set verticalAlignment(value: number) {
  109. return;
  110. }
  111. private get _effectiveX2(): number {
  112. return (this._connectedControl ? this._connectedControl.centerX : 0) + this._x2.getValue(this._host);
  113. }
  114. private get _effectiveY2(): number {
  115. return (this._connectedControl ? this._connectedControl.centerY : 0) + this._y2.getValue(this._host);
  116. }
  117. /**
  118. * Creates a new Line
  119. * @param name defines the control name
  120. */
  121. constructor(public name?: string) {
  122. super(name);
  123. this.isHitTestVisible = false;
  124. this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
  125. this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
  126. }
  127. protected _getTypeName(): string {
  128. return "Line";
  129. }
  130. public _draw(context: CanvasRenderingContext2D): void {
  131. context.save();
  132. if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
  133. context.shadowColor = this.shadowColor;
  134. context.shadowBlur = this.shadowBlur;
  135. context.shadowOffsetX = this.shadowOffsetX;
  136. context.shadowOffsetY = this.shadowOffsetY;
  137. }
  138. this._applyStates(context);
  139. context.strokeStyle = this.color;
  140. context.lineWidth = this._lineWidth;
  141. context.setLineDash(this._dash);
  142. context.beginPath();
  143. context.moveTo(this._x1.getValue(this._host), this._y1.getValue(this._host));
  144. context.lineTo(this._effectiveX2, this._effectiveY2);
  145. context.stroke();
  146. context.restore();
  147. }
  148. public _measure(): void {
  149. // Width / Height
  150. this._currentMeasure.width = Math.abs(this._x1.getValue(this._host) - this._effectiveX2) + this._lineWidth;
  151. this._currentMeasure.height = Math.abs(this._y1.getValue(this._host) - this._effectiveY2) + this._lineWidth;
  152. }
  153. protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
  154. this._currentMeasure.left = Math.min(this._x1.getValue(this._host), this._effectiveX2) - this._lineWidth / 2;
  155. this._currentMeasure.top = Math.min(this._y1.getValue(this._host), this._effectiveY2) - this._lineWidth / 2;
  156. }
  157. /**
  158. * Move one end of the line given 3D cartesian coordinates.
  159. * @param position Targeted world position
  160. * @param scene Scene
  161. * @param end (opt) Set to true to assign x2 and y2 coordinates of the line. Default assign to x1 and y1.
  162. */
  163. public moveToVector3(position: Vector3, scene: Scene, end: boolean = false): void {
  164. if (!this._host || this.parent !== this._host._rootContainer) {
  165. Tools.Error("Cannot move a control to a vector3 if the control is not at root level");
  166. return;
  167. }
  168. var globalViewport = this._host._getGlobalViewport(scene);
  169. var projectedPosition = Vector3.Project(position, Matrix.Identity(), scene.getTransformMatrix(), globalViewport);
  170. this._moveToProjectedPosition(projectedPosition, end);
  171. if (projectedPosition.z < 0 || projectedPosition.z > 1) {
  172. this.notRenderable = true;
  173. return;
  174. }
  175. this.notRenderable = false;
  176. }
  177. /**
  178. * Move one end of the line to a position in screen absolute space.
  179. * @param projectedPosition Position in screen absolute space (X, Y)
  180. * @param end (opt) Set to true to assign x2 and y2 coordinates of the line. Default assign to x1 and y1.
  181. */
  182. public _moveToProjectedPosition(projectedPosition: Vector3, end: boolean = false): void {
  183. let x: string = (projectedPosition.x + this._linkOffsetX.getValue(this._host)) + "px";
  184. let y: string = (projectedPosition.y + this._linkOffsetY.getValue(this._host)) + "px";
  185. if (end) {
  186. this.x2 = x;
  187. this.y2 = y;
  188. this._x2.ignoreAdaptiveScaling = true;
  189. this._y2.ignoreAdaptiveScaling = true;
  190. } else {
  191. this.x1 = x;
  192. this.y1 = y;
  193. this._x1.ignoreAdaptiveScaling = true;
  194. this._y1.ignoreAdaptiveScaling = true;
  195. }
  196. }
  197. }