@houstonp/rubiks-cube 1.4.0 → 1.5.0
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/README.md +46 -42
- package/index.js +114 -51
- package/package.json +2 -3
- package/src/cube/cube.js +18 -14
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Rubiks Cube Web Component
|
|
2
2
|
|
|
3
|
-
This package is a rubiks cube web component built with threejs. Camera animation smoothing is done with the
|
|
3
|
+
This package is a rubiks cube web component built with threejs. Camera animation smoothing is done with the gsap package.
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
@@ -21,7 +21,7 @@ import '@houstonp/rubiks-cube';
|
|
|
21
21
|
<meta charset="utf-8" />
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
|
24
|
-
<rubiks-cube animation-speed="1000" animation-style="exponential" piece-gap="1.04" camera-speed="100"> </rubiks-cube>
|
|
24
|
+
<rubiks-cube animation-speed-ms="1000" animation-style="exponential" piece-gap="1.04" camera-speed="100"> </rubiks-cube>
|
|
25
25
|
<script type="module" src="index.js"></script>
|
|
26
26
|
</body>
|
|
27
27
|
</html>
|
|
@@ -29,12 +29,16 @@ import '@houstonp/rubiks-cube';
|
|
|
29
29
|
|
|
30
30
|
## component attributes
|
|
31
31
|
|
|
32
|
-
| attribute
|
|
33
|
-
|
|
|
34
|
-
| animation-speed
|
|
35
|
-
| animation-style
|
|
36
|
-
| piece-gap
|
|
37
|
-
| camera-speed
|
|
32
|
+
| attribute | accepted values | Description |
|
|
33
|
+
| ---------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
+
| animation-speed-ms | integer greater than or equal to 0 | sets the duration of the animations in milliseconds |
|
|
35
|
+
| animation-style | "exponetial", "next", "fixed", "match" | fixed: fixed animation lengths, next: skips to next animation, exponential: speeds up successive animations, match: matches the speed the frequency of events |
|
|
36
|
+
| piece-gap | greater than 1 | sets the gap between rubiks cube pieces |
|
|
37
|
+
| camera-speed-ms | greater than or equal to 0 | sets the duration of camera animations in milliseconds |
|
|
38
|
+
| camera-radius | greater than or equal to 4 | sets the camera radius |
|
|
39
|
+
| camera-peek-angle-horizontal | decimal between 0 and 1 | sets the horizontal peek angle |
|
|
40
|
+
| camera-peek-angle-vertical | decimal between 0 and 1 | sets the vertical peek angle |
|
|
41
|
+
| camera-field-of-view | integer between 40 and 100 | sets the fielf of view of the camera |
|
|
38
42
|
|
|
39
43
|
## state of the component
|
|
40
44
|
|
|
@@ -156,12 +160,12 @@ var event = new CustomEvent('action', {
|
|
|
156
160
|
|
|
157
161
|
action IDs for camera actions are as follows
|
|
158
162
|
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
-
|
|
163
|
+
- `peek-right` - Camera is moved to the right of the cube so that the right face is visible
|
|
164
|
+
- `peek-left` - Camera is moved to the left of the cube so that the left face is visible
|
|
165
|
+
- `peek-top` - Camera is moved above the cube so that the top face is visible
|
|
166
|
+
- `peek-bottom` - Camera is moved below the cube so that the bottom face is visible
|
|
167
|
+
- `peek-toggle-horizontal` - Camera is moved to the opposite side of the cube in the horizontal plane
|
|
168
|
+
- `peek-toggle-vertical` - Camera is moved to the opposite side of the cube in the vertical plane
|
|
165
169
|
|
|
166
170
|
#### Example
|
|
167
171
|
|
|
@@ -183,15 +187,15 @@ cube.dispatchEvent(event);
|
|
|
183
187
|
|
|
184
188
|
actionIDs for action type "rotation" are as follows
|
|
185
189
|
|
|
186
|
-
-
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
-
|
|
193
|
-
-
|
|
194
|
-
-
|
|
190
|
+
- 'x',
|
|
191
|
+
- 'x2',
|
|
192
|
+
- "x'",
|
|
193
|
+
- 'y',
|
|
194
|
+
- 'y2',
|
|
195
|
+
- "y'",
|
|
196
|
+
- 'z',
|
|
197
|
+
- 'z2',
|
|
198
|
+
- "z'",
|
|
195
199
|
|
|
196
200
|
#### Example
|
|
197
201
|
|
|
@@ -225,25 +229,25 @@ cube.dispatchEvent(event);
|
|
|
225
229
|
|
|
226
230
|
actionIDs for action type "movement" are as follows
|
|
227
231
|
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
-
|
|
233
|
-
-
|
|
234
|
-
-
|
|
235
|
-
-
|
|
236
|
-
-
|
|
237
|
-
-
|
|
238
|
-
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
242
|
-
-
|
|
243
|
-
-
|
|
244
|
-
-
|
|
245
|
-
-
|
|
246
|
-
-
|
|
232
|
+
- 'R',
|
|
233
|
+
- 'R2',
|
|
234
|
+
- "R'",
|
|
235
|
+
- 'L',
|
|
236
|
+
- 'L2',
|
|
237
|
+
- "L'",
|
|
238
|
+
- 'U',
|
|
239
|
+
- 'U2',
|
|
240
|
+
- "U'",
|
|
241
|
+
- 'D',
|
|
242
|
+
- 'D2',
|
|
243
|
+
- "D'",
|
|
244
|
+
- 'F',
|
|
245
|
+
- 'F2',
|
|
246
|
+
- "F'",
|
|
247
|
+
- 'B',
|
|
248
|
+
- 'B2',
|
|
249
|
+
- "B'",
|
|
250
|
+
- etc...
|
|
247
251
|
|
|
248
252
|
#### Example
|
|
249
253
|
|
package/index.js
CHANGED
|
@@ -1,54 +1,105 @@
|
|
|
1
|
-
import { Scene, WebGLRenderer, PerspectiveCamera, AmbientLight, DirectionalLight } from 'three';
|
|
2
|
-
import { Tween, Group, Easing } from '@tweenjs/tween.js';
|
|
1
|
+
import { Scene, WebGLRenderer, PerspectiveCamera, AmbientLight, DirectionalLight, Spherical } from 'three';
|
|
3
2
|
import { OrbitControls } from 'three/examples/jsm/Addons.js';
|
|
4
3
|
import Cube from './src/cube/cube';
|
|
5
4
|
import getRotationDetailsFromNotation from './src/utils/rotation';
|
|
6
5
|
import { debounce } from './src/utils/debouncer';
|
|
6
|
+
import gsap from 'gsap';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
/** @typedef {{ animationStyle: "exponential" | "next" | "fixed" | "match", animationSpeedMs: number, pieceGap: number, cameraSpeedMs: number, cameraRadius: number, cameraPeekAngleHorizontal: number, cameraPeekAngleVertical: number, cameraFieldOfView: number }} Settings */
|
|
9
|
+
/** @type {Settings} */
|
|
10
|
+
const defaultSettings = {
|
|
11
|
+
animationSpeedMs: 100,
|
|
12
|
+
animationStyle: 'fixed',
|
|
13
|
+
pieceGap: 1.04,
|
|
14
|
+
cameraSpeedMs: 100,
|
|
15
|
+
cameraRadius: 5,
|
|
16
|
+
cameraPeekAngleHorizontal: 0.6,
|
|
17
|
+
cameraPeekAngleVertical: 0.6,
|
|
18
|
+
cameraFieldOfView: 75,
|
|
19
|
+
};
|
|
20
|
+
const minGap = 1;
|
|
21
|
+
const minRadius = 4;
|
|
22
|
+
const minFieldOfView = 40;
|
|
23
|
+
const maxFieldOfView = 100;
|
|
24
|
+
const maxAzimuthAngle = (5 * Math.PI) / 16;
|
|
25
|
+
const polarAngleOffset = Math.PI / 2;
|
|
26
|
+
const maxPolarAngle = (5 * Math.PI) / 16;
|
|
13
27
|
|
|
14
28
|
class RubiksCube extends HTMLElement {
|
|
15
29
|
constructor() {
|
|
16
30
|
super();
|
|
17
|
-
/** @type {number} */
|
|
18
|
-
this.animationSpeed = defaultAnimationSpeed;
|
|
19
31
|
this.attachShadow({ mode: 'open' });
|
|
20
32
|
this.shadowRoot.innerHTML = `<canvas id="cube-canvas" style="display:block;"></canvas>`;
|
|
21
33
|
this.canvas = this.shadowRoot.getElementById('cube-canvas');
|
|
22
|
-
/** @type {
|
|
34
|
+
/** @type {Settings} */
|
|
23
35
|
this.settings = {
|
|
24
|
-
|
|
25
|
-
animationStyle: this.getAttribute('animation-style') ||
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
animationSpeedMs: this.getAttribute('animation-speed-ms') || defaultSettings.animationSpeedMs,
|
|
37
|
+
animationStyle: this.getAttribute('animation-style') || defaultSettings.animationStyle,
|
|
38
|
+
pieceGap: this.getAttribute('piece-gap') || defaultSettings.pieceGap,
|
|
39
|
+
cameraSpeedMs: this.getAttribute('camera-speed-ms') || defaultSettings.cameraSpeedMs,
|
|
40
|
+
cameraRadius: this.getAttribute('camera-radius') || defaultSettings.cameraRadius,
|
|
41
|
+
cameraPeekAngleHorizontal: this.getAttribute('camera-peek-angle-horizontal') || defaultSettings.cameraPeekAngleHorizontal,
|
|
42
|
+
cameraPeekAngleVertical: this.getAttribute('camera-peek-angle-vertical') || defaultSettings.cameraPeekAngleVertical,
|
|
43
|
+
cameraFieldOfView: this.getAttribute('camera-field-of-view') || defaultSettings.cameraFieldOfView,
|
|
28
44
|
};
|
|
29
45
|
}
|
|
30
46
|
|
|
31
47
|
static get observedAttributes() {
|
|
32
|
-
return [
|
|
48
|
+
return [
|
|
49
|
+
'animation-style',
|
|
50
|
+
'animation-speed-ms',
|
|
51
|
+
'piece-gap',
|
|
52
|
+
'camera-speed-ms',
|
|
53
|
+
'camera-radius',
|
|
54
|
+
'camera-peek-angle-horizontal',
|
|
55
|
+
'camera-peek-angle-vertical',
|
|
56
|
+
'camera-field-of-view',
|
|
57
|
+
];
|
|
33
58
|
}
|
|
34
59
|
|
|
35
60
|
attributeChangedCallback(name, oldVal, newVal) {
|
|
36
61
|
if (name === 'animation-style') {
|
|
37
62
|
this.settings.animationStyle = newVal;
|
|
38
63
|
}
|
|
39
|
-
if (name === 'animation-speed') {
|
|
64
|
+
if (name === 'animation-speed-ms') {
|
|
40
65
|
var speed = Number(newVal);
|
|
41
|
-
this.settings.
|
|
66
|
+
this.settings.animationSpeedMs = speed > 0 ? speed : 0;
|
|
42
67
|
}
|
|
43
68
|
if (name === 'piece-gap') {
|
|
44
69
|
var gap = Number(newVal);
|
|
45
|
-
this.settings.
|
|
70
|
+
this.settings.pieceGap = gap < minGap ? minGap : gap;
|
|
46
71
|
}
|
|
47
|
-
if (name === 'camera-speed') {
|
|
72
|
+
if (name === 'camera-speed-ms') {
|
|
48
73
|
var speed = Number(newVal);
|
|
49
|
-
this.settings.
|
|
74
|
+
this.settings.cameraSpeedMs = speed > 0 ? speed : 0;
|
|
75
|
+
}
|
|
76
|
+
if (name === 'camera-radius') {
|
|
77
|
+
var radius = Number(newVal);
|
|
78
|
+
this.settings.cameraRadius = radius < minRadius ? minRadius : radius;
|
|
79
|
+
this.dispatchEvent(new CustomEvent('cameraSettingsChanged'));
|
|
80
|
+
}
|
|
81
|
+
if (name === 'camera-peek-angle-horizontal') {
|
|
82
|
+
var angle = Number(newVal);
|
|
83
|
+
angle = angle > 0 ? angle : 0;
|
|
84
|
+
angle = angle < 1 ? angle : 1;
|
|
85
|
+
this.settings.cameraPeekAngleHorizontal = angle > 0 ? angle : 0;
|
|
86
|
+
this.dispatchEvent(new CustomEvent('cameraSettingsChanged'));
|
|
87
|
+
}
|
|
88
|
+
if (name === 'camera-peek-angle-vertical') {
|
|
89
|
+
var angle = Number(newVal);
|
|
90
|
+
angle = angle > 0 ? angle : 0;
|
|
91
|
+
angle = angle < 1 ? angle : 1;
|
|
92
|
+
this.settings.cameraPeekAngleVertical = angle;
|
|
93
|
+
this.dispatchEvent(new CustomEvent('cameraSettingsChanged'));
|
|
94
|
+
}
|
|
95
|
+
if (name == 'camera-field-of-view') {
|
|
96
|
+
var fov = Number(newVal);
|
|
97
|
+
fov = fov > minFieldOfView ? fov : minFieldOfView;
|
|
98
|
+
fov = fov < maxFieldOfView ? fov : maxFieldOfView;
|
|
99
|
+
this.settings.cameraFieldOfView = fov;
|
|
50
100
|
}
|
|
51
101
|
}
|
|
102
|
+
|
|
52
103
|
connectedCallback() {
|
|
53
104
|
this.init();
|
|
54
105
|
}
|
|
@@ -77,22 +128,21 @@ class RubiksCube extends HTMLElement {
|
|
|
77
128
|
).observe(this);
|
|
78
129
|
|
|
79
130
|
// add camera
|
|
80
|
-
const camera = new PerspectiveCamera(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
camera.position.x = 0;
|
|
131
|
+
const camera = new PerspectiveCamera(this.settings.cameraFieldOfView, this.clientWidth / this.clientHeight, 0.1, 2000);
|
|
132
|
+
const cameraSpherical = new Spherical(15, (3 * Math.PI) / 8, -Math.PI / 4);
|
|
133
|
+
camera.position.setFromSpherical(cameraSpherical);
|
|
134
|
+
/** @type {{ Up: boolean, Right: boolean }} */
|
|
135
|
+
const cameraState = { Up: true, Right: true };
|
|
86
136
|
|
|
87
137
|
// add orbit controls for camera
|
|
88
138
|
const controls = new OrbitControls(camera, renderer.domElement);
|
|
89
139
|
controls.enableZoom = false;
|
|
90
140
|
controls.enablePan = false;
|
|
91
141
|
controls.enableDamping = true;
|
|
92
|
-
controls.maxAzimuthAngle =
|
|
93
|
-
controls.minAzimuthAngle = -
|
|
94
|
-
controls.maxPolarAngle =
|
|
95
|
-
controls.minPolarAngle =
|
|
142
|
+
controls.maxAzimuthAngle = maxAzimuthAngle;
|
|
143
|
+
controls.minAzimuthAngle = -maxAzimuthAngle;
|
|
144
|
+
controls.maxPolarAngle = polarAngleOffset + maxPolarAngle;
|
|
145
|
+
controls.minPolarAngle = polarAngleOffset - maxPolarAngle;
|
|
96
146
|
|
|
97
147
|
// add lighting to scene
|
|
98
148
|
const ambientLight = new AmbientLight('white', 0.5);
|
|
@@ -110,10 +160,6 @@ class RubiksCube extends HTMLElement {
|
|
|
110
160
|
const cube = new Cube(this.settings);
|
|
111
161
|
scene.add(cube.group, cube.rotationGroup);
|
|
112
162
|
|
|
113
|
-
// initial camera animation
|
|
114
|
-
const cameraAnimationGroup = new Group();
|
|
115
|
-
cameraAnimationGroup.add(new Tween(camera.position).to({ x: 2.5, y: 2.5, z: 4 }, 1000).easing(Easing.Cubic.InOut).start());
|
|
116
|
-
|
|
117
163
|
const sendState = (eventId) => {
|
|
118
164
|
const event = new CustomEvent('state', { detail: { eventId, state: cube.currentState } });
|
|
119
165
|
this.dispatchEvent(event);
|
|
@@ -121,7 +167,6 @@ class RubiksCube extends HTMLElement {
|
|
|
121
167
|
|
|
122
168
|
// animation loop
|
|
123
169
|
function animate() {
|
|
124
|
-
cameraAnimationGroup.update();
|
|
125
170
|
controls.update();
|
|
126
171
|
|
|
127
172
|
var eventId = cube.update();
|
|
@@ -140,9 +185,9 @@ class RubiksCube extends HTMLElement {
|
|
|
140
185
|
this.addEventListener('action', (e) => {
|
|
141
186
|
/** @type {{eventId: string, action: {type: "movement" | "camera" | "rotation", actionId: string }}} move */
|
|
142
187
|
var move = e.detail.move;
|
|
143
|
-
console.log(move);
|
|
144
188
|
if (move.action.type === 'camera') {
|
|
145
|
-
|
|
189
|
+
updateCameraState(move.action.actionId);
|
|
190
|
+
updateCameraPosition();
|
|
146
191
|
return;
|
|
147
192
|
}
|
|
148
193
|
if (move.action.type === 'movement' || move.action.type === 'rotation') {
|
|
@@ -163,9 +208,9 @@ class RubiksCube extends HTMLElement {
|
|
|
163
208
|
};
|
|
164
209
|
|
|
165
210
|
/**
|
|
166
|
-
* @param {'peek-toggle-horizontal' | 'peek-toggle-vertical' | 'peek-right' | 'peek-left' | 'peek-up' | 'peek-down'} actionId
|
|
211
|
+
* @param {'peek-toggle-horizontal' | 'peek-toggle-vertical' | 'peek-right' | 'peek-left' | 'peek-up' | 'peek-down' } actionId
|
|
167
212
|
*/
|
|
168
|
-
const
|
|
213
|
+
const updateCameraState = (actionId) => {
|
|
169
214
|
if (actionId === 'peek-toggle-horizontal') {
|
|
170
215
|
cameraState.Right = !cameraState.Right;
|
|
171
216
|
} else if (actionId === 'peek-toggle-vertical') {
|
|
@@ -179,19 +224,37 @@ class RubiksCube extends HTMLElement {
|
|
|
179
224
|
} else if (actionId === 'peek-down') {
|
|
180
225
|
cameraState.Up = false;
|
|
181
226
|
}
|
|
182
|
-
cameraAnimationGroup.add(
|
|
183
|
-
new Tween(camera.position)
|
|
184
|
-
.to(
|
|
185
|
-
{
|
|
186
|
-
x: cameraState.Right ? cameraState.RightDistance : -cameraState.RightDistance,
|
|
187
|
-
y: cameraState.Up ? cameraState.UpDistance : -cameraState.UpDistance,
|
|
188
|
-
z: 4,
|
|
189
|
-
},
|
|
190
|
-
this.settings.cameraSpeed,
|
|
191
|
-
)
|
|
192
|
-
.start(),
|
|
193
|
-
);
|
|
194
227
|
};
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @param {number | null} cameraSpeedMs
|
|
231
|
+
* @param {gsap.EaseString | gsap.EaseFunction | undefined} ease
|
|
232
|
+
*/
|
|
233
|
+
const updateCameraPosition = (cameraSpeedMs = this.settings.cameraSpeedMs, ease = 'none') => {
|
|
234
|
+
cameraSpeedMs = cameraSpeedMs ? cameraSpeedMs : this.settings.cameraSpeedMs;
|
|
235
|
+
var phi = polarAngleOffset + (cameraState.Up ? -this.settings.cameraPeekAngleVertical : this.settings.cameraPeekAngleVertical) * maxPolarAngle;
|
|
236
|
+
var theta = (cameraState.Right ? this.settings.cameraPeekAngleHorizontal : -this.settings.cameraPeekAngleHorizontal) * maxAzimuthAngle;
|
|
237
|
+
const startSpherical = new Spherical().setFromVector3(camera.position);
|
|
238
|
+
const targetSpherical = new Spherical(this.settings.cameraRadius, phi, theta);
|
|
239
|
+
gsap.to(startSpherical, {
|
|
240
|
+
radius: targetSpherical.radius,
|
|
241
|
+
theta: targetSpherical.theta,
|
|
242
|
+
phi: targetSpherical.phi,
|
|
243
|
+
duration: cameraSpeedMs / 1000,
|
|
244
|
+
ease: ease,
|
|
245
|
+
onUpdate: function () {
|
|
246
|
+
camera.position.setFromSpherical(startSpherical);
|
|
247
|
+
camera.lookAt(cube.group.position);
|
|
248
|
+
controls.update();
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
this.addEventListener('cameraSettingsChanged', () => {
|
|
254
|
+
updateCameraPosition(); // animate settings changes
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
updateCameraPosition(1000, 'sine.out'); // initial animation
|
|
195
258
|
}
|
|
196
259
|
}
|
|
197
260
|
customElements.define('rubiks-cube', RubiksCube);
|
package/package.json
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@houstonp/rubiks-cube",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Rubiks Cube Web Component built with threejs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Houston Pearse",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"
|
|
9
|
+
"gsap": "^3.14.2",
|
|
10
10
|
"three": "^0.167.1"
|
|
11
11
|
},
|
|
12
|
-
"devDependencies": {},
|
|
13
12
|
"repository": {
|
|
14
13
|
"type": "git",
|
|
15
14
|
"url": "git+https://github.com/houstonpearse/rubiks-cube.git"
|
package/src/cube/cube.js
CHANGED
|
@@ -5,10 +5,10 @@ import { CubeRotation } from './cubeRotation';
|
|
|
5
5
|
|
|
6
6
|
export default class Cube {
|
|
7
7
|
/**
|
|
8
|
-
* @param {
|
|
8
|
+
* @param {import('../..').Settings} settings
|
|
9
9
|
*/
|
|
10
10
|
constructor(settings) {
|
|
11
|
-
/** @type {
|
|
11
|
+
/** @type {import('../..').Settings} */
|
|
12
12
|
this.settings = settings;
|
|
13
13
|
/** @type {Group} */
|
|
14
14
|
this.group = this.createCubeGroup();
|
|
@@ -45,7 +45,11 @@ export default class Cube {
|
|
|
45
45
|
|
|
46
46
|
for (const piece of createCubeState()) {
|
|
47
47
|
var pieceGroup = piece.group;
|
|
48
|
-
pieceGroup.position.set(
|
|
48
|
+
pieceGroup.position.set(
|
|
49
|
+
piece.position.x * this.settings.pieceGap,
|
|
50
|
+
piece.position.y * this.settings.pieceGap,
|
|
51
|
+
piece.position.z * this.settings.pieceGap,
|
|
52
|
+
);
|
|
49
53
|
pieceGroup.rotation.set(piece.rotation.x, piece.rotation.y, piece.rotation.z);
|
|
50
54
|
pieceGroup.userData = {
|
|
51
55
|
position: Object.assign({}, piece.position),
|
|
@@ -61,11 +65,11 @@ export default class Cube {
|
|
|
61
65
|
|
|
62
66
|
/**
|
|
63
67
|
* update the cube and continue any rotations
|
|
64
|
-
* @returns {
|
|
68
|
+
* @returns {string}
|
|
65
69
|
*/
|
|
66
70
|
update() {
|
|
67
71
|
if (this.currentRotation === undefined) {
|
|
68
|
-
if (this._lastGap !== this.settings.
|
|
72
|
+
if (this._lastGap !== this.settings.pieceGap) {
|
|
69
73
|
this.updateGap();
|
|
70
74
|
}
|
|
71
75
|
this.currentRotation = this.rotationQueue.shift();
|
|
@@ -100,9 +104,9 @@ export default class Cube {
|
|
|
100
104
|
if (this.currentRotation === undefined) {
|
|
101
105
|
this.group.children.forEach((piece) => {
|
|
102
106
|
var { x, y, z } = piece.userData.position;
|
|
103
|
-
piece.position.set(x * this.settings.
|
|
107
|
+
piece.position.set(x * this.settings.pieceGap, y * this.settings.pieceGap, z * this.settings.pieceGap);
|
|
104
108
|
});
|
|
105
|
-
this._lastGap = this.settings.
|
|
109
|
+
this._lastGap = this.settings.pieceGap;
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
|
|
@@ -118,15 +122,15 @@ export default class Cube {
|
|
|
118
122
|
*/
|
|
119
123
|
getRotationSpeed() {
|
|
120
124
|
if (this.settings.animationStyle === 'exponential') {
|
|
121
|
-
return this.settings.
|
|
125
|
+
return this.settings.animationSpeedMs / 2 ** this.rotationQueue.length;
|
|
122
126
|
}
|
|
123
127
|
if (this.settings.animationStyle === 'next') {
|
|
124
|
-
return this.rotationQueue.length > 0 ? 0 : this.settings.
|
|
128
|
+
return this.rotationQueue.length > 0 ? 0 : this.settings.animationSpeedMs;
|
|
125
129
|
}
|
|
126
130
|
if (this.settings.animationStyle === 'match') {
|
|
127
131
|
if (this.rotationQueue.length > 0) {
|
|
128
132
|
var lastTimeStamp = this.currentRotation.timestampMs;
|
|
129
|
-
var minGap = this._matchSpeed ?? this.settings.
|
|
133
|
+
var minGap = this._matchSpeed ?? this.settings.animationSpeedMs;
|
|
130
134
|
for (var i = 0; i < this.rotationQueue.length; i++) {
|
|
131
135
|
var gap = this.rotationQueue[i].timestampMs - lastTimeStamp;
|
|
132
136
|
if (gap < minGap) {
|
|
@@ -138,12 +142,12 @@ export default class Cube {
|
|
|
138
142
|
if (this._matchSpeed !== undefined) {
|
|
139
143
|
return this._matchSpeed;
|
|
140
144
|
}
|
|
141
|
-
return this.settings.
|
|
145
|
+
return this.settings.animationSpeedMs;
|
|
142
146
|
}
|
|
143
147
|
if (this.settings.animationStyle === 'fixed') {
|
|
144
|
-
return this.settings.
|
|
148
|
+
return this.settings.animationSpeedMs;
|
|
145
149
|
}
|
|
146
|
-
return this.settings.
|
|
150
|
+
return this.settings.animationSpeedMs;
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
/**
|
|
@@ -160,7 +164,7 @@ export default class Cube {
|
|
|
160
164
|
this.group.children.forEach((piece) => {
|
|
161
165
|
const { x, y, z } = piece.userData.initialPosition;
|
|
162
166
|
const { x: u, y: v, z: w } = piece.userData.initialRotation;
|
|
163
|
-
piece.position.set(x * this.settings.
|
|
167
|
+
piece.position.set(x * this.settings.pieceGap, y * this.settings.pieceGap, z * this.settings.pieceGap);
|
|
164
168
|
piece.rotation.set(u, v, w);
|
|
165
169
|
piece.userData.position.x = x;
|
|
166
170
|
piece.userData.position.y = y;
|