traceView.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import {mat3} from 'gl-matrix';
  2. import clamp from 'sentry/utils/number/clamp';
  3. // Computes the transformation matrix that is used to render scaled
  4. // elements to the DOM and draw the view.
  5. export class TraceView {
  6. // Represents the space of the entire trace, for example
  7. // a trace starting at 0 and ending at 1000 would have a space of [0, 1000]
  8. to_origin: number = 0;
  9. trace_space: DOMView = DOMView.Empty();
  10. // The view defines what the user is currently looking at, it is a subset
  11. // of the trace space. For example, if the user is currently looking at the
  12. // trace from 500 to 1000, the view would be represented by [x, width] = [500, 500]
  13. trace_view: DOMView = DOMView.Empty();
  14. // Represents the pixel space of the entire trace - this is the container
  15. // that we render to. For example, if the container is 1000px wide, the
  16. // pixel space would be [0, 1000]
  17. trace_physical_space: DOMView = DOMView.Empty();
  18. // the encapsulating container that the entire view is rendered to
  19. trace_container_physical_space: DOMView = DOMView.Empty();
  20. public readonly MAX_ZOOM_PRECISION_MS = 1;
  21. setTracePhysicalSpace(
  22. container_space: [x: number, y: number, width: number, height: number],
  23. space: [x: number, y: number, width: number, height: number]
  24. ) {
  25. this.trace_container_physical_space = new DOMView(
  26. 0,
  27. 0,
  28. container_space[2],
  29. container_space[3]
  30. );
  31. this.trace_physical_space = new DOMView(0, 0, space[2], space[3]);
  32. }
  33. setTraceSpace(space: [x: number, y: number, width: number, height: number]) {
  34. this.to_origin = space[0];
  35. this.trace_space = new DOMView(0, 0, space[2], space[3]);
  36. this.trace_view = new DOMView(0, 0, space[2], space[3]);
  37. }
  38. setTraceView(view: {width?: number; x?: number}) {
  39. // In cases where a trace might have a single error, there is no concept of a timeline
  40. if (this.trace_view.width === 0) {
  41. return;
  42. }
  43. const x = view.x ?? this.trace_view.x;
  44. const width = view.width ?? this.trace_view.width;
  45. this.trace_view.x = clamp(
  46. x,
  47. 0,
  48. Math.max(this.trace_space.width - width, this.MAX_ZOOM_PRECISION_MS)
  49. );
  50. this.trace_view.width = clamp(
  51. width,
  52. this.MAX_ZOOM_PRECISION_MS,
  53. this.trace_space.width - this.trace_view.x
  54. );
  55. }
  56. getConfigSpaceCursor(cursor: {x: number; y: number}): [number, number] {
  57. const left_percentage = cursor.x / this.trace_physical_space.width;
  58. const left_view = left_percentage * this.trace_view.width;
  59. return [this.trace_view.x + left_view, 0];
  60. }
  61. }
  62. /**
  63. * Helper class that handles computing transformations between different views to and from DOM space
  64. */
  65. class DOMView {
  66. public x: number;
  67. public y: number;
  68. public width: number;
  69. public height: number;
  70. constructor(x: number, y: number, width: number, height: number) {
  71. this.x = x;
  72. this.y = y;
  73. this.width = width;
  74. this.height = height;
  75. }
  76. static From(view: DOMView): DOMView {
  77. return new DOMView(view.x, view.y, view.width, view.height);
  78. }
  79. static Empty(): DOMView {
  80. return new DOMView(0, 0, 1000, 1);
  81. }
  82. serialize() {
  83. return [this.x, this.y, this.width, this.height];
  84. }
  85. between(to: DOMView): mat3 {
  86. return mat3.fromValues(
  87. to.width / this.width,
  88. 0,
  89. 0,
  90. to.height / this.height,
  91. 0,
  92. 0,
  93. to.x - this.x * (to.width / this.width),
  94. to.y - this.y * (to.height / this.height),
  95. 1
  96. );
  97. }
  98. transform(mat: mat3): [number, number, number, number] {
  99. const x = this.x * mat[0] + this.y * mat[3] + mat[6];
  100. const y = this.x * mat[1] + this.y * mat[4] + mat[7];
  101. const width = this.width * mat[0] + this.height * mat[3];
  102. const height = this.width * mat[1] + this.height * mat[4];
  103. return [x, y, width, height];
  104. }
  105. get center() {
  106. return this.x + this.width / 2;
  107. }
  108. get left() {
  109. return this.x;
  110. }
  111. get right() {
  112. return this.x + this.width;
  113. }
  114. get top() {
  115. return this.y;
  116. }
  117. get bottom() {
  118. return this.y + this.height;
  119. }
  120. }