Structural foundation of a 3x3x3 3D cube using CSS 3D Transforms in a browser environment
This system constructs a 3x3x3 3D Rubik's Cube in the browser by combining web-standard CSS 3D Transforms and React state management, without relying on external WebGL libraries or physics engines.
The entire 3D structure is defined as a collection of 27 independent small cube (Cubie) components. Each Cubie holds a logical three-dimensional coordinate system (coordinates taking values of -1, 0, and 1 on the X, Y, and Z axes, respectively) and a 3x3 pose matrix (Matrix3D) indicating its current orientation as properties.
In the initial state, each Cubie holds an identity matrix as its pose matrix and is placed at a predetermined grid position in space.
During the rendering process on the screen, a translation (translate3d) based on logical coordinates and a string converted from the pose matrix into the CSS matrix3d function are synthesized and applied to the transform property of each element.
This matrix3d property directly passes a 4x4 homogeneous coordinate transformation matrix to CSS, transmitting the rotational state calculated on the CPU side to the rendering engine with GPU acceleration.
Furthermore, the 6 faces (stickers) that make up each Cubie are implemented as absolutely positioned DOM elements. The logical coordinates of the initial position are reverse-calculated from the Cubie's ID, and unique background colors of red, orange, yellow, white, green, and blue, along with inward shadow effects, are applied only to the faces exposed to the outside.
The faces hidden inside are set to black, thereby reducing the rendering load and improving the visual 3D effect. By adopting this DOM-based rendering method, it achieves both stable operation and an intuitive appearance even in a lightweight environment that does not have a dedicated 3D drawing context.
Viewpoint control via mouse/touch events and face manipulation mechanism by dragging stickers
In order for users to intuitively grasp and operate the 3D structure, this tool implements two independent interaction layers: viewpoint control by dragging the background area and face rotation manipulation by dragging the sticker area.
When a mousedown or touchstart event fires on the wrapper element for the entire screen, it determines whether the source of the event (target) is a sticker element, and branches the processing into camera operation and cube operation.
The control of the camera (viewpoint) is realized as rotation along the X-axis and Y-axis (rotateX, rotateY) applied to the container element that surrounds the entire cube.
A value obtained by multiplying the drag distance (in pixels) by a certain coefficient is added to the initial angle, and specifically for the X-axis (vertical rotation), the value is clamped within a range of -85 degrees to 85 degrees to prevent the screen from flipping upside down.
This creates a visual effect where a virtual camera orbits around the cube.
On the other hand, the face manipulation mechanism is based on logic that infers the rotation axis (X, Y, Z) and rotation direction (clockwise or counterclockwise) intended by the user from a combination of the drag direction on a specific sticker and the face (U, D, L, R, F, B) to which that sticker belongs.
The moment the drag distance exceeds a threshold (30 pixels), the horizontal and vertical displacements are compared to determine the primary axis of movement.
For example, if a sticker on the front face (F face) is dragged horizontally, it is interpreted as a layer rotation with the Y-axis as the axis of rotation; if it is dragged vertically, it is interpreted as a layer rotation with the X-axis as the axis of rotation.
The inferred rotation command is immediately passed to the animation queue, and the drag state is reset, providing a continuous and error-free operational feel.
Logical update of rotational state via matrix operations and animation via CSS transitions
When a face rotation is requested by a user operation or a system command, the system first executes a visual rotation animation, and then goes through a two-stage process of updating the internal logical state (coordinates and pose matrix) after its completion.
A rotation operation is defined by three parameters: the axis of rotation (X, Y, Z), the target layer (-1, 0, 1), and the direction of rotation (1 or -1).
In the animation phase, "Currently Animating Rotation Information (AnimatingRotation)" is set as the React state. The rendering loop determines whether the current position of each Cubie matches the specified layer, and only for the matching Cubies, it preemptively applies temporary rotation functions (rotateX, rotateY, rotateZ) in addition to the normal transform string.
At this time, interpolation is performed over the time specified by the CSS transition property (e.g., 300ms for manual operation), so smooth rotation by the browser's rendering engine is achieved without calculating the angle for each frame on the JavaScript side.
After the animation time has elapsed, the system transitions to the logical state update phase. A 90-degree rotation matrix corresponding to the specified axis and direction (e.g., [1, 0, 0], [0, 0, -1], [0, 1, 0] for an X-axis clockwise rotation) is multiplied by the target group of Cubies to calculate a new pose matrix.
At the same time, for the logical spatial coordinates (currentX, currentY, currentZ), coordinate transformations accompanying the rotation (e.g., for X-axis rotation, the new Y coordinate becomes the old -Z, and the new Z coordinate becomes the old Y) are applied.
Once the updated state is reflected in the React state and the animation state is cleared simultaneously, the rotation operation is finalized as the base transform based on the new logical state is applied from the next rendering.
Specifications and behavior of the 15-move auto-shuffle function using Math.random
The auto-shuffle function to break the cube into a random state is based on a unique implementation policy that differs from the official scrambling programs used for competitive Rubik's Cubes.
Rather than utilizing complex official scrambles, this system adopts a simpler and more direct approach by generating a 15-move random operation sequence.
When the shuffle is triggered, 15 consecutive rotation operations are applied to the cube through an asynchronous loop. In each step, utilizing the built-in JavaScript function Math.random(), the rotation axis (3 types: X, Y, Z), the rotation layer (3 types: -1, 0, 1), and the rotation direction (2 types: 1, -1) are each independently and randomly selected.
A notable point here is that the options for the rotation layer include "0", which is the middle layer (slice layer). While general competitive scramble sequences (U, D, R, L, F, B) target only the outer faces for rotation, this tool also generates single rotations of the middle layers corresponding to M, E, and S, allowing users to visually enjoy a more three-dimensional and unpredictable breakdown.
By inserting a wait time for the animation between each operation (e.g., 120ms), the user can visually follow the process of the cube transitioning to a random state while rotating at high speed.
In addition, since all 15 operations executed during the shuffle are recorded in the internal history array, they are utilized as foundational data for reverse playback by the auto-solve function described later.
During the execution of the shuffle, solving, or animating, sticker manipulation is blocked, while camera viewpoint controls can remain available.
Implementation of auto-solve using in-page operation history and reverse playback approach
The "auto-solve" function featured in this tool does not calculate the optimal solution from the current state using group theory or search algorithms (such as Iterative Deepening A* or Kociemba's two-phase algorithm).
Instead, it adopts an approach that "reverses the history" of all rotation operations (manual operations and operations by shuffle) performed since the user opened the page.
The system maintains an array with a data structure called MoveRecord (rotation axis, target layer, rotation direction) as the operation history.
Every time a rotation operation is confirmed, its content is pushed to the end of this array. When the user presses the auto-solve button, the system duplicates the history array and begins scanning backward (in reverse order) from the end to the beginning.
At each step, it calls the performMove function using parameters where the sign of the recorded rotation direction is inverted (direction * -1), canceling out the original operations one by one.
The advantage of this method is that it operates extremely stably on the browser's main thread without worrying about an explosive increase in the search space.
Because there is no need to download complex state recognition modules or massive heuristic tables, its lightweight nature as a local process is guaranteed.
Once the series of reverse playbacks is complete and the cube returns to its initial state (the state where all Cubies have correct coordinates and identity matrices), the history array is cleared, ready to record new operations again.
In this way, the auto-solve function is designed to function as a "reversal of the time axis" rather than a "resolution of the state."
Functional limitations of the current system and intended use cases
Because this system is designed for users to easily experience a 3D Rubik's Cube on a browser and enjoy the feeling of 3D manipulation, there are several intentional functional limitations.
The most significant limitation is that it does not have the function of a "solution search tool" that inputs an arbitrary cube configuration brought from outside (such as a scrambled physical cube) and presents the steps to solve it.
As described in the previous chapter, since the auto-solve relies on the operation history within the page, it cannot resolve an arbitrary state where no history exists.
Also, functions for speedcubing time attack competitions (such as an inspection timer in milliseconds, WCA-compliant scramble notation display, strict move counting, and a scoreboard function), advanced shading using WebGL, and simulation of friction and inertia by a physics engine are not implemented.
Furthermore, it does not have a state persistence function using the browser's local storage or IndexedDB, so reloading the page will reset the cube to its initial state.
Given these limitations, the optimal use cases for this tool are as a demonstration of 3D expression using CSS 3D Transforms, training of spatial awareness through intuitive drag operations, or casual relaxation visually enjoying random shuffles and history reverse playback.
Since it does not communicate with external servers and all processing is completed as client-side JavaScript, its operation depends on the browser's support for CSS 3D and input events.