redhotmagma-visualization 1.46.0 → 1.46.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Three/Three2D.js CHANGED
@@ -303,9 +303,11 @@ var Three2D = exports.Three2D = /*#__PURE__*/function (_ThreeBase) {
303
303
  var _ref5,
304
304
  animate,
305
305
  duration,
306
+ getViewOffset,
306
307
  designArea,
307
308
  obj,
308
309
  zoom,
310
+ viewOffset,
309
311
  position,
310
312
  _args2 = arguments;
311
313
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
@@ -314,25 +316,26 @@ var Three2D = exports.Three2D = /*#__PURE__*/function (_ThreeBase) {
314
316
  _ref5 = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {
315
317
  animate: false,
316
318
  duration: {}
317
- }, animate = _ref5.animate, duration = _ref5.duration;
319
+ }, animate = _ref5.animate, duration = _ref5.duration, getViewOffset = _ref5.getViewOffset;
318
320
  _context2.next = 3;
319
321
  return this.getScreenshotsReady();
320
322
  case 3:
321
323
  designArea = this._currentDesignArea || (0, _first["default"])(this._designAreaList);
322
324
  obj = designArea && this.findAreaObjectByName(designArea.identifier);
323
325
  zoom = this.calculateZoomForObject(obj);
326
+ viewOffset = getViewOffset && getViewOffset();
324
327
  position = new _three.Vector3();
325
328
  if (obj) {
326
329
  obj.getWorldPosition(position);
327
330
  }
328
331
  position.z = this.camera.position.z;
329
332
  if (animate) {
330
- this.moveCamera(position, zoom, duration);
333
+ this.moveCamera(position, zoom, duration, viewOffset);
331
334
  } else {
332
335
  this.stopAnimation("camera");
333
- this.setCameraPosition(position, zoom);
336
+ this.setCameraPosition(position, zoom, viewOffset);
334
337
  }
335
- case 10:
338
+ case 11:
336
339
  case "end":
337
340
  return _context2.stop();
338
341
  }
@@ -856,13 +859,15 @@ var Three2D = exports.Three2D = /*#__PURE__*/function (_ThreeBase) {
856
859
  * Animates the camera position and zoom to the given target
857
860
  * @param {Vector3} position
858
861
  * @param {number} zoom
859
- * @param {{[position]: number, [zoom]: number}} duration The animation duration in ms
862
+ * @param {{[position]: number, [zoom]: number, [viewOffset]: number}} duration The animation duration in ms
863
+ * @param {object} viewOffset
860
864
  */
861
865
  }, {
862
866
  key: "moveCamera",
863
867
  value: function moveCamera(position, zoom) {
864
868
  var _this7 = this;
865
869
  var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
870
+ var viewOffset = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
866
871
  this.cleanUpCameraAnimations();
867
872
  var animationDef = new _Deferred.DeferredGroup();
868
873
  if (zoom) {
@@ -875,6 +880,16 @@ var Three2D = exports.Three2D = /*#__PURE__*/function (_ThreeBase) {
875
880
  if (position) {
876
881
  new _tween["default"].Tween(this.camera.position, this.cameraTweenGroup).to(position, duration.position || 1000).easing(_tween["default"].Easing.Quadratic.Out).onComplete(animationDef.createResolver()).start();
877
882
  }
883
+ if (viewOffset) {
884
+ if (!this.camera.view) {
885
+ var _this$renderer$getSiz = this.renderer.getSize(new _three.Vector2()),
886
+ width = _this$renderer$getSiz.x,
887
+ height = _this$renderer$getSiz.y;
888
+ this.camera.setViewOffset(width, height, 0, 0, width, height);
889
+ }
890
+ var currentViewOffset = this.camera.view;
891
+ new _tween["default"].Tween(currentViewOffset, this.cameraTweenGroup).to(viewOffset, duration.viewOffset || 1000).easing(_tween["default"].Easing.Quadratic.Out).onComplete(animationDef.createResolver()).start();
892
+ }
878
893
  animationDef.then(function () {
879
894
  return _this7.stopAnimation("camera");
880
895
  });
@@ -1135,11 +1150,18 @@ var Three2D = exports.Three2D = /*#__PURE__*/function (_ThreeBase) {
1135
1150
  }
1136
1151
  }, {
1137
1152
  key: "setCameraPosition",
1138
- value: function setCameraPosition(position, zoom) {
1153
+ value: function setCameraPosition(position, zoom, viewOffset) {
1139
1154
  Object.assign(this.camera.position, position);
1140
1155
  Object.assign(this.camera, {
1141
1156
  zoom: zoom
1142
1157
  });
1158
+ if (viewOffset) {
1159
+ var offsetX = viewOffset.offsetX,
1160
+ offsetY = viewOffset.offsetY,
1161
+ width = viewOffset.width,
1162
+ height = viewOffset.height;
1163
+ this.camera.setViewOffset(width, height, offsetX, offsetY, width, height);
1164
+ }
1143
1165
  this.camera.updateProjectionMatrix();
1144
1166
  }
1145
1167
  }, {
@@ -3,7 +3,48 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.updateFitSizeToElement = void 0;
6
+ exports.updateFitSizeToElement = exports.getRectCenter = void 0;
7
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
8
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
9
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
10
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
12
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
13
+ var getRectCenter = exports.getRectCenter = function getRectCenter(_ref) {
14
+ var width = _ref.width,
15
+ height = _ref.height,
16
+ left = _ref.left,
17
+ top = _ref.top;
18
+ var x = left + width / 2;
19
+ var y = top + height / 2;
20
+ return {
21
+ x: x,
22
+ y: y
23
+ };
24
+ };
25
+ function calculateViewOffset(visualization, element) {
26
+ var canvas = visualization.renderer && visualization.renderer.domElement;
27
+ var containerRect = canvas.getBoundingClientRect();
28
+ var width = containerRect.width,
29
+ height = containerRect.height;
30
+ var _getRectCenter = getRectCenter(containerRect),
31
+ cx = _getRectCenter.x,
32
+ cy = _getRectCenter.y;
33
+ var _getRectCenter2 = getRectCenter(element.getBoundingClientRect()),
34
+ tx = _getRectCenter2.x,
35
+ ty = _getRectCenter2.y;
36
+ var offsetX = cx - tx;
37
+ var offsetY = cy - ty;
38
+ return {
39
+ offsetX: offsetX,
40
+ offsetY: offsetY,
41
+ width: width,
42
+ height: height,
43
+ fullWidth: width,
44
+ fullHeight: height
45
+ };
46
+ }
47
+
7
48
  /**
8
49
  * @param {ThreeBase} visualization
9
50
  * @param {Element} element
@@ -28,7 +69,11 @@ var updateFitSizeToElement = exports.updateFitSizeToElement = function updateFit
28
69
  updateCameraPosition: function updateCameraPosition() {
29
70
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
30
71
  var updateFn = visualization.setCameraPositionToCurrentDesignArea;
31
- updateFn && updateFn.call(visualization, options);
72
+ updateFn && updateFn.call(visualization, _objectSpread(_objectSpread({}, options), {}, {
73
+ getViewOffset: function getViewOffset() {
74
+ return calculateViewOffset(visualization, element);
75
+ }
76
+ }));
32
77
  }
33
78
  };
34
79
  };
@@ -10,7 +10,6 @@ var _cssElementQueries = require("css-element-queries");
10
10
  var _VisualizationProvider = require("./VisualizationProvider");
11
11
  var _VisualizationInterface = require("./VisualizationInterface");
12
12
  var _AlignTargetProvider = require("./AlignTargetProvider");
13
- var _alignToElement = require("./Utils/alignToElement");
14
13
  var _updateFitSizeToElement = require("./Utils/updateFitSizeToElement");
15
14
  var _Constants = require("./Constants");
16
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
@@ -30,6 +29,20 @@ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.g
30
29
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
31
30
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
32
31
  function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
32
+ var didBoundingRectChange = function () {
33
+ var prevRect;
34
+ return function (element) {
35
+ var rect = element.getBoundingClientRect();
36
+ if (!rect.width || !rect.height) {
37
+ return false;
38
+ }
39
+ var result = !prevRect || ["top", "bottom", "left", "right"].some(function (key) {
40
+ return rect[key] !== prevRect[key];
41
+ });
42
+ prevRect = rect;
43
+ return result;
44
+ };
45
+ }();
33
46
  var defaultContainerStyle = {
34
47
  position: "absolute",
35
48
  top: 0,
@@ -66,21 +79,39 @@ var VisualizationContainer = exports.VisualizationContainer = /*#__PURE__*/funct
66
79
  loading: loading
67
80
  });
68
81
  });
69
- _defineProperty(_assertThisInitialized(_this), "onSizeChange", function (size) {
82
+ _defineProperty(_assertThisInitialized(_this), "doAlignment", function () {
83
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
84
+ var _options$animate = options.animate,
85
+ animate = _options$animate === void 0 ? false : _options$animate;
70
86
  var _this$props = _this.props,
71
87
  visualization = _this$props.visualization,
72
88
  alignTargetElement = _this$props.alignTargetElement;
89
+ if (!alignTargetElement) {
90
+ return;
91
+ }
92
+ var _alignTargetElement$g = alignTargetElement.getBoundingClientRect(),
93
+ width = _alignTargetElement$g.width,
94
+ height = _alignTargetElement$g.height;
95
+ if (!width || !height) {
96
+ return;
97
+ }
98
+ (0, _updateFitSizeToElement.updateFitSizeToElement)(visualization, alignTargetElement).updateCameraPosition({
99
+ animate: visualization.isAnimating() || animate
100
+ });
101
+ });
102
+ _defineProperty(_assertThisInitialized(_this), "onSizeChange", function (size) {
103
+ var _this$props2 = _this.props,
104
+ visualization = _this$props2.visualization,
105
+ alignTargetElement = _this$props2.alignTargetElement;
73
106
  if (!visualization.isInitialized()) {
74
107
  return;
75
108
  }
76
109
  visualization.setSize(size);
77
110
  if (alignTargetElement && alignTargetElement.clientWidth > 0 && alignTargetElement.clientHeight > 0) {
78
- (0, _alignToElement.alignToElement)(visualization, alignTargetElement);
79
- (0, _updateFitSizeToElement.updateFitSizeToElement)(visualization, alignTargetElement).updateCameraPosition({
80
- animate: visualization.isAnimating() || !!alignTargetElement
111
+ _this.doAlignment({
112
+ animate: true
81
113
  });
82
114
  }
83
- visualization.render();
84
115
  });
85
116
  _defineProperty(_assertThisInitialized(_this), "containerRef", /*#__PURE__*/_react["default"].createRef());
86
117
  return _this;
@@ -98,12 +129,16 @@ var VisualizationContainer = exports.VisualizationContainer = /*#__PURE__*/funct
98
129
  throw new Error('The provided "three" prop should always be a subclass of VisualizationInterface!');
99
130
  }
100
131
  this.initResizeSensor();
101
- this.updateVisualization();
132
+ this.updateVisualization({}, {
133
+ animate: false
134
+ });
102
135
  }
103
136
  }, {
104
137
  key: "componentDidUpdate",
105
138
  value: function componentDidUpdate(prevProps) {
106
- this.updateVisualization(prevProps);
139
+ this.updateVisualization(prevProps, {
140
+ animate: true
141
+ });
107
142
  }
108
143
  }, {
109
144
  key: "initResizeSensor",
@@ -113,34 +148,37 @@ var VisualizationContainer = exports.VisualizationContainer = /*#__PURE__*/funct
113
148
  }
114
149
  }, {
115
150
  key: "initMutationObserver",
116
- value: function initMutationObserver() {
151
+ value: function initMutationObserver(prevProps) {
152
+ var _this2 = this;
153
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
154
+ animate: true
155
+ };
117
156
  if (this.mutationObserver) {
118
157
  this.mutationObserver.disconnect();
119
158
  }
120
- var _this$props2 = this.props,
121
- visualization = _this$props2.visualization,
122
- alignTargetElement = _this$props2.alignTargetElement;
159
+ var alignTargetElement = this.props.alignTargetElement;
123
160
  if (!alignTargetElement) {
124
161
  return;
125
162
  }
126
- this.mutationObserver = new MutationObserver(function () {
127
- (0, _updateFitSizeToElement.updateFitSizeToElement)(visualization, alignTargetElement).updateCameraPosition({
128
- animate: true
163
+ if (alignTargetElement !== prevProps.alignTargetElement) {
164
+ this.mutationObserver = new MutationObserver(function () {
165
+ _this2.doAlignment(options);
129
166
  });
130
- visualization.render();
131
- });
132
- // do the update only when attributes have changed (e.g. style)
133
- this.mutationObserver.observe(alignTargetElement, {
134
- attributes: true
135
- });
167
+ // do the update only when attributes have changed (e.g. style)
168
+ this.mutationObserver.observe(alignTargetElement, {
169
+ attributes: true
170
+ });
171
+ }
172
+ if (didBoundingRectChange(alignTargetElement)) {
173
+ this.doAlignment(options);
174
+ }
136
175
  }
137
176
  }, {
138
177
  key: "updateVisualization",
139
178
  value: function updateVisualization() {
140
179
  var prevProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
141
- var _this$props3 = this.props,
142
- visualization = _this$props3.visualization,
143
- alignTargetElement = _this$props3.alignTargetElement;
180
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
181
+ var visualization = this.props.visualization;
144
182
  var container = this.containerRef.current;
145
183
  if (visualization !== prevProps.visualization) {
146
184
  if (prevProps.visualization) {
@@ -155,21 +193,14 @@ var VisualizationContainer = exports.VisualizationContainer = /*#__PURE__*/funct
155
193
  // init resize sensor if it's not done in the componentDidUpdate
156
194
  !this.resizeSensor && this.initResizeSensor();
157
195
  }
158
- if ((alignTargetElement && alignTargetElement !== prevProps.alignTargetElement || visualization && visualization !== prevProps.visualization) && alignTargetElement && alignTargetElement.clientWidth > 0 && alignTargetElement.clientHeight > 0) {
159
- (0, _alignToElement.alignToElement)(visualization, alignTargetElement);
160
- (0, _updateFitSizeToElement.updateFitSizeToElement)(visualization, alignTargetElement).updateCameraPosition({
161
- animate: visualization.isAnimating() || !!prevProps.alignTargetElement
162
- });
163
- visualization.render();
164
- }
165
- this.initMutationObserver();
196
+ this.initMutationObserver(prevProps, options);
166
197
  }
167
198
  }, {
168
199
  key: "componentWillUnmount",
169
200
  value: function componentWillUnmount() {
170
- var _this$props4 = this.props,
171
- autoDispose = _this$props4.autoDispose,
172
- visualization = _this$props4.visualization;
201
+ var _this$props3 = this.props,
202
+ autoDispose = _this$props3.autoDispose,
203
+ visualization = _this$props3.visualization;
173
204
  autoDispose && visualization.dispose();
174
205
  this.resizeSensor && this.resizeSensor.detach();
175
206
  this.offObservers && this.offObservers();
@@ -177,34 +208,34 @@ var VisualizationContainer = exports.VisualizationContainer = /*#__PURE__*/funct
177
208
  }, {
178
209
  key: "initVisualization",
179
210
  value: function initVisualization(container) {
180
- var _this2 = this;
211
+ var _this3 = this;
181
212
  var visualization = this.props.visualization;
182
213
  visualization.init(container);
183
214
  var offLoadError = visualization.observable.on(_Constants.EventTypes.LoadError, function (_ref) {
184
215
  var screenshot = _ref.data.screenshot;
185
- return !screenshot && _this2.setState({
216
+ return !screenshot && _this3.setState({
186
217
  broken: true
187
218
  });
188
219
  });
189
220
  var offLoadFinished = visualization.observable.on(_Constants.EventTypes.LoadFinished, function (_ref2) {
190
221
  var screenshot = _ref2.data.screenshot;
191
- return !screenshot && _this2.setState({
222
+ return !screenshot && _this3.setState({
192
223
  broken: false
193
224
  });
194
225
  });
195
226
  this.offObservers = function () {
196
227
  offLoadError();
197
228
  offLoadFinished();
198
- delete _this2.offObservers;
229
+ delete _this3.offObservers;
199
230
  };
200
231
  }
201
232
  }, {
202
233
  key: "render",
203
234
  value: function render() {
204
- var _this$props5 = this.props,
205
- className = _this$props5.className,
206
- ProgressComponent = _this$props5.ProgressComponent,
207
- BrokenComponent = _this$props5.BrokenComponent;
235
+ var _this$props4 = this.props,
236
+ className = _this$props4.className,
237
+ ProgressComponent = _this$props4.ProgressComponent,
238
+ BrokenComponent = _this$props4.BrokenComponent;
208
239
  var broken = this.state.broken;
209
240
  var style = _objectSpread(_objectSpread({}, className ? {} : defaultContainerStyle), broken && BrokenComponent && {
210
241
  display: "none"
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "redhotmagma-visualization",
3
- "version": "1.46.0",
3
+ "version": "1.46.2",
4
4
  "license": "UNLICENSED",
5
5
  "private": false,
6
6
  "main": "./index.js",
7
7
  "dependencies": {
8
8
  "@babel/polyfill": "^7.12.1",
9
- "@configuratorware/scripts": "1.46.0",
9
+ "@configuratorware/scripts": "1.46.2",
10
10
  "@tweenjs/tween.js": "^17.6.0",
11
11
  "console-polyfill": "^0.3.0",
12
12
  "css-element-queries": "^1.2.3",
@@ -16,8 +16,9 @@ import {
16
16
  WebGLRenderer,
17
17
  BufferGeometry,
18
18
  Float32BufferAttribute,
19
- DoubleSide, LinearSRGBColorSpace,
20
- } from 'three';
19
+ DoubleSide,
20
+ LinearSRGBColorSpace,
21
+ } from "three";
21
22
  import TWEEN from "@tweenjs/tween.js";
22
23
  import get from "lodash/get";
23
24
  import first from "lodash/first";
@@ -181,12 +182,15 @@ export class Three2D extends ThreeBase {
181
182
  this._fitSize = sizeObj;
182
183
  }
183
184
 
184
- async setCameraPositionToCurrentDesignArea({ animate, duration } = { animate: false, duration: {} }) {
185
+ async setCameraPositionToCurrentDesignArea(
186
+ { animate, duration, getViewOffset } = { animate: false, duration: {} }
187
+ ) {
185
188
  await this.getScreenshotsReady();
186
189
  const designArea = this._currentDesignArea || first(this._designAreaList);
187
190
 
188
191
  const obj = designArea && this.findAreaObjectByName(designArea.identifier);
189
192
  const zoom = this.calculateZoomForObject(obj);
193
+ const viewOffset = getViewOffset && getViewOffset();
190
194
  const position = new Vector3();
191
195
  if (obj) {
192
196
  obj.getWorldPosition(position);
@@ -194,10 +198,10 @@ export class Three2D extends ThreeBase {
194
198
  position.z = this.camera.position.z;
195
199
 
196
200
  if (animate) {
197
- this.moveCamera(position, zoom, duration);
201
+ this.moveCamera(position, zoom, duration, viewOffset);
198
202
  } else {
199
203
  this.stopAnimation("camera");
200
- this.setCameraPosition(position, zoom);
204
+ this.setCameraPosition(position, zoom, viewOffset);
201
205
  }
202
206
  }
203
207
 
@@ -562,9 +566,10 @@ export class Three2D extends ThreeBase {
562
566
  * Animates the camera position and zoom to the given target
563
567
  * @param {Vector3} position
564
568
  * @param {number} zoom
565
- * @param {{[position]: number, [zoom]: number}} duration The animation duration in ms
569
+ * @param {{[position]: number, [zoom]: number, [viewOffset]: number}} duration The animation duration in ms
570
+ * @param {object} viewOffset
566
571
  */
567
- moveCamera(position, zoom, duration = {}) {
572
+ moveCamera(position, zoom, duration = {}, viewOffset = null) {
568
573
  this.cleanUpCameraAnimations();
569
574
 
570
575
  const animationDef = new DeferredGroup();
@@ -583,6 +588,18 @@ export class Three2D extends ThreeBase {
583
588
  .onComplete(animationDef.createResolver())
584
589
  .start();
585
590
  }
591
+ if (viewOffset) {
592
+ if (!this.camera.view) {
593
+ const { x: width, y: height } = this.renderer.getSize(new Vector2());
594
+ this.camera.setViewOffset(width, height, 0, 0, width, height);
595
+ }
596
+ const currentViewOffset = this.camera.view;
597
+ new TWEEN.Tween(currentViewOffset, this.cameraTweenGroup)
598
+ .to(viewOffset, duration.viewOffset || 1000)
599
+ .easing(TWEEN.Easing.Quadratic.Out)
600
+ .onComplete(animationDef.createResolver())
601
+ .start();
602
+ }
586
603
  animationDef.then(() => this.stopAnimation("camera"));
587
604
  this.startAnimation("camera");
588
605
  }
@@ -821,9 +838,13 @@ export class Three2D extends ThreeBase {
821
838
  this.setMaxZoom(maxZoom > this._minZoom ? maxZoom : this._minZoom);
822
839
  }
823
840
 
824
- setCameraPosition(position, zoom) {
841
+ setCameraPosition(position, zoom, viewOffset) {
825
842
  Object.assign(this.camera.position, position);
826
843
  Object.assign(this.camera, { zoom });
844
+ if (viewOffset) {
845
+ const { offsetX, offsetY, width, height } = viewOffset;
846
+ this.camera.setViewOffset(width, height, offsetX, offsetY, width, height);
847
+ }
827
848
  this.camera.updateProjectionMatrix();
828
849
  }
829
850
 
@@ -1,3 +1,23 @@
1
+ export const getRectCenter = ({ width, height, left, top }) => {
2
+ const x = left + width / 2;
3
+ const y = top + height / 2;
4
+ return {
5
+ x,
6
+ y,
7
+ };
8
+ };
9
+
10
+ function calculateViewOffset(visualization, element) {
11
+ const canvas = visualization.renderer && visualization.renderer.domElement;
12
+ const containerRect = canvas.getBoundingClientRect();
13
+ const { width, height } = containerRect;
14
+ const { x: cx, y: cy } = getRectCenter(containerRect);
15
+ const { x: tx, y: ty } = getRectCenter(element.getBoundingClientRect());
16
+ const offsetX = cx - tx;
17
+ const offsetY = cy - ty;
18
+ return { offsetX, offsetY, width, height, fullWidth: width, fullHeight: height };
19
+ }
20
+
1
21
  /**
2
22
  * @param {ThreeBase} visualization
3
23
  * @param {Element} element
@@ -16,7 +36,13 @@ export const updateFitSizeToElement = (visualization, element) => {
16
36
  return {
17
37
  updateCameraPosition: (options = {}) => {
18
38
  const { setCameraPositionToCurrentDesignArea: updateFn } = visualization;
19
- updateFn && updateFn.call(visualization, options);
39
+ updateFn &&
40
+ updateFn.call(visualization, {
41
+ ...options,
42
+ getViewOffset() {
43
+ return calculateViewOffset(visualization, element);
44
+ },
45
+ });
20
46
  },
21
47
  };
22
48
  };
@@ -4,10 +4,23 @@ import { ResizeSensor } from "css-element-queries";
4
4
  import { withVisualization } from "./VisualizationProvider";
5
5
  import { VisualizationInterface } from "./VisualizationInterface";
6
6
  import { withCurrentTarget } from "./AlignTargetProvider";
7
- import { alignToElement } from "./Utils/alignToElement";
8
7
  import { updateFitSizeToElement } from "./Utils/updateFitSizeToElement";
9
8
  import { EventTypes as VisualizationEventTypes } from "./Constants";
10
9
 
10
+ const didBoundingRectChange = (function() {
11
+ let prevRect;
12
+ return function(element) {
13
+ const rect = element.getBoundingClientRect();
14
+ if (!rect.width || !rect.height) {
15
+ return false;
16
+ }
17
+ const result =
18
+ !prevRect || ["top", "bottom", "left", "right"].some(key => rect[key] !== prevRect[key]);
19
+ prevRect = rect;
20
+ return result;
21
+ };
22
+ })();
23
+
11
24
  const defaultContainerStyle = {
12
25
  position: "absolute",
13
26
  top: 0,
@@ -63,11 +76,11 @@ export class VisualizationContainer extends React.Component {
63
76
 
64
77
  this.initResizeSensor();
65
78
 
66
- this.updateVisualization();
79
+ this.updateVisualization({}, { animate: false });
67
80
  }
68
81
 
69
82
  componentDidUpdate(prevProps) {
70
- this.updateVisualization(prevProps);
83
+ this.updateVisualization(prevProps, { animate: true });
71
84
  }
72
85
 
73
86
  initResizeSensor() {
@@ -75,26 +88,43 @@ export class VisualizationContainer extends React.Component {
75
88
  this.resizeSensor = new ResizeSensor(container, this.onSizeChange);
76
89
  }
77
90
 
78
- initMutationObserver() {
91
+ doAlignment = (options = {}) => {
92
+ const { animate = false } = options;
93
+ const { visualization, alignTargetElement } = this.props;
94
+ if (!alignTargetElement) {
95
+ return;
96
+ }
97
+ const { width, height } = alignTargetElement.getBoundingClientRect();
98
+ if (!width || !height) {
99
+ return;
100
+ }
101
+ updateFitSizeToElement(visualization, alignTargetElement).updateCameraPosition({
102
+ animate: visualization.isAnimating() || animate,
103
+ });
104
+ };
105
+
106
+ initMutationObserver(prevProps, options = { animate: true }) {
79
107
  if (this.mutationObserver) {
80
108
  this.mutationObserver.disconnect();
81
109
  }
82
- const { visualization, alignTargetElement } = this.props;
110
+ const { alignTargetElement } = this.props;
83
111
  if (!alignTargetElement) {
84
112
  return;
85
113
  }
86
- this.mutationObserver = new MutationObserver(() => {
87
- updateFitSizeToElement(visualization, alignTargetElement).updateCameraPosition({
88
- animate: true,
114
+ if (alignTargetElement !== prevProps.alignTargetElement) {
115
+ this.mutationObserver = new MutationObserver(() => {
116
+ this.doAlignment(options);
89
117
  });
90
- visualization.render();
91
- });
92
- // do the update only when attributes have changed (e.g. style)
93
- this.mutationObserver.observe(alignTargetElement, { attributes: true });
118
+ // do the update only when attributes have changed (e.g. style)
119
+ this.mutationObserver.observe(alignTargetElement, { attributes: true });
120
+ }
121
+ if (didBoundingRectChange(alignTargetElement)) {
122
+ this.doAlignment(options);
123
+ }
94
124
  }
95
125
 
96
- updateVisualization(prevProps = {}) {
97
- const { visualization, alignTargetElement } = this.props;
126
+ updateVisualization(prevProps = {}, options = {}) {
127
+ const { visualization } = this.props;
98
128
  const container = this.containerRef.current;
99
129
 
100
130
  if (visualization !== prevProps.visualization) {
@@ -110,20 +140,7 @@ export class VisualizationContainer extends React.Component {
110
140
  // init resize sensor if it's not done in the componentDidUpdate
111
141
  !this.resizeSensor && this.initResizeSensor();
112
142
  }
113
- if (
114
- ((alignTargetElement && alignTargetElement !== prevProps.alignTargetElement) ||
115
- (visualization && visualization !== prevProps.visualization)) &&
116
- alignTargetElement &&
117
- alignTargetElement.clientWidth > 0 &&
118
- alignTargetElement.clientHeight > 0
119
- ) {
120
- alignToElement(visualization, alignTargetElement);
121
- updateFitSizeToElement(visualization, alignTargetElement).updateCameraPosition({
122
- animate: visualization.isAnimating() || !!prevProps.alignTargetElement,
123
- });
124
- visualization.render();
125
- }
126
- this.initMutationObserver();
143
+ this.initMutationObserver(prevProps, options);
127
144
  }
128
145
 
129
146
  componentWillUnmount() {
@@ -162,12 +179,8 @@ export class VisualizationContainer extends React.Component {
162
179
  alignTargetElement.clientWidth > 0 &&
163
180
  alignTargetElement.clientHeight > 0
164
181
  ) {
165
- alignToElement(visualization, alignTargetElement);
166
- updateFitSizeToElement(visualization, alignTargetElement).updateCameraPosition({
167
- animate: visualization.isAnimating() || !!alignTargetElement,
168
- });
182
+ this.doAlignment({ animate: true });
169
183
  }
170
- visualization.render();
171
184
  };
172
185
 
173
186
  containerRef = React.createRef();
@@ -1,72 +0,0 @@
1
- "use strict";
2
-
3
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.getRectCenter = exports.alignToElement = void 0;
8
- function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
9
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
10
- function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
11
- var getRectCenter = exports.getRectCenter = function getRectCenter(_ref) {
12
- var width = _ref.width,
13
- height = _ref.height,
14
- left = _ref.left,
15
- top = _ref.top;
16
- var x = left + width / 2;
17
- var y = top + height / 2;
18
- return {
19
- x: x,
20
- y: y
21
- };
22
- };
23
-
24
- /**
25
- * Calculates the view offset to align the camera with the given element
26
- * @param {ThreeBase} visualization
27
- * @param {Element} element
28
- */
29
- var alignToElement = exports.alignToElement = /*#__PURE__*/function () {
30
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(visualization, element) {
31
- var canvas, containerRect, width, height, _getRectCenter, cx, cy, _getRectCenter2, tx, ty, dx, dy;
32
- return _regeneratorRuntime().wrap(function _callee$(_context) {
33
- while (1) switch (_context.prev = _context.next) {
34
- case 0:
35
- _context.next = 2;
36
- return visualization.getScreenshotsReady();
37
- case 2:
38
- canvas = visualization.renderer && visualization.renderer.domElement;
39
- if (!(visualization && visualization.camera)) {
40
- _context.next = 18;
41
- break;
42
- }
43
- if (element) {
44
- _context.next = 9;
45
- break;
46
- }
47
- visualization.camera.clearViewOffset();
48
- return _context.abrupt("return");
49
- case 9:
50
- if (canvas) {
51
- _context.next = 11;
52
- break;
53
- }
54
- return _context.abrupt("return");
55
- case 11:
56
- containerRect = canvas.getBoundingClientRect();
57
- width = containerRect.width, height = containerRect.height;
58
- _getRectCenter = getRectCenter(containerRect), cx = _getRectCenter.x, cy = _getRectCenter.y;
59
- _getRectCenter2 = getRectCenter(element.getBoundingClientRect()), tx = _getRectCenter2.x, ty = _getRectCenter2.y;
60
- dx = cx - tx;
61
- dy = cy - ty;
62
- visualization.camera.setViewOffset(width, height, dx, dy, width, height);
63
- case 18:
64
- case "end":
65
- return _context.stop();
66
- }
67
- }, _callee);
68
- }));
69
- return function alignToElement(_x, _x2) {
70
- return _ref2.apply(this, arguments);
71
- };
72
- }();
@@ -1,33 +0,0 @@
1
- export const getRectCenter = ({ width, height, left, top }) => {
2
- const x = left + width / 2;
3
- const y = top + height / 2;
4
- return {
5
- x,
6
- y,
7
- };
8
- };
9
-
10
- /**
11
- * Calculates the view offset to align the camera with the given element
12
- * @param {ThreeBase} visualization
13
- * @param {Element} element
14
- */
15
- export const alignToElement = async (visualization, element) => {
16
- await visualization.getScreenshotsReady();
17
- const canvas = visualization.renderer && visualization.renderer.domElement;
18
- if (visualization && visualization.camera) {
19
- if (!element) {
20
- visualization.camera.clearViewOffset();
21
- return;
22
- } else if (!canvas) {
23
- return;
24
- }
25
- const containerRect = canvas.getBoundingClientRect();
26
- const { width, height } = containerRect;
27
- const { x: cx, y: cy } = getRectCenter(containerRect);
28
- const { x: tx, y: ty } = getRectCenter(element.getBoundingClientRect());
29
- const dx = cx - tx;
30
- const dy = cy - ty;
31
- visualization.camera.setViewOffset(width, height, dx, dy, width, height);
32
- }
33
- };