I need help making a 3x3x1 3d Rubik's cube simulator

So I am making a Rubik’s cube simulator and its stickers are grouped accordingly to side, I am using a raycaster element to test what group I press (Either red, blue, green, or orange), when a group is pressed, I need all the stickers to be ungrouped, and each cubie to be grouped according to stickers. then it finds the three pieces that have the colors in the group I pressed, then it uses a animation element to rotate the side 180°, then it ungroups the cubies, ungroups the stickers that make up the cubies, then regroups the stickers on the sides themselves. My current code is:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3x3x1 Rubik's Cube</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
            margin: 0;
        }

        .cube {
            position: relative;
            width: 200px;
            height: 66px;
            transform-style: preserve-3d;
            transform: rotateX(-30deg) rotateY(-45deg);
        }

        .piece {
            position: absolute;
            width: 66px;
            height: 66px;
            border: 1px solid #000;
            box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5);
            transform-style: preserve-3d;
        }

        .face {
            position: absolute;
            width: 66px;
            height: 66px;
            background: rgba(255, 255, 255, 0.9);
            border: 1px solid #ccc;
        }

        .face.front  { transform: translateZ(33px); }
        .face.back   { transform: rotateY(180deg) translateZ(33px); }
        .face.right  { transform: rotateY(90deg) translateZ(100px); }
        .face.left   { transform: rotateY(-90deg) translateZ(100px); }
        .face.top    { transform: rotateX(90deg) translateZ(33px); }
        .face.bottom { transform: rotateX(-90deg) translateZ(33px); }

        .center-piece {
            width: 66px;
            height: 66px;
            transform-style: preserve-3d;
        }

        .center-piece .face {
            width: 66px;
            height: 66px;
        }
    </style>
</head>
<body>
    <div class="cube" id="cube"></div>

    <script>
        let cube = document.getElementById('cube');
        let isDragging = false;
        let previousMousePosition = { x: 0, y: 0 };
        let rotationX = -30;
        let rotationY = -45;

        document.addEventListener('mousedown', (event) => {
            isDragging = true;
            previousMousePosition = { x: event.clientX, y: event.clientY };
        });

        document.addEventListener('mousemove', (event) => {
            if (isDragging) {
                let deltaX = event.clientX - previousMousePosition.x;
                let deltaY = event.clientY - previousMousePosition.y;
                rotationX -= deltaY * 0.5;
                rotationY += deltaX * 0.5;
                cube.style.transform = `rotateX(${rotationX}deg) rotateY(${rotationY}deg)`;
                previousMousePosition = { x: event.clientX, y: event.clientY };
            }
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
        });

        document.addEventListener('mouseleave', () => {
            isDragging = false;
        });

        function createPiece(colors, position, isCenter = false) {
            const piece = document.createElement('div');
            piece.className = isCenter ? 'piece center-piece' : 'piece';
            piece.style.transform = position;

            colors.forEach((color, index) => {
                const face = document.createElement('div');
                face.className = 'face';
                face.style.backgroundColor = color;
                face.style.transform = `rotateY(${index * 90}deg) translateZ(33px)`;
                piece.appendChild(face);
            });

            return piece;
        }

        function addPieces() {
            const pieces = [
                // Top-left corner piece
                { colors: ['white', 'green', 'yellow', 'blue'], position: 'translateX(-66px) translateY(-66px)' },
                // Top-center edge piece
                { colors: ['white', 'green', 'yellow'], position: 'translateX(0) translateY(-66px)' },
                // Top-right corner piece
                { colors: ['white', 'green', 'yellow', 'blue'], position: 'translateX(66px) translateY(-66px)' },
                // Middle-left edge piece
                { colors: ['white', 'green', 'yellow'], position: 'translateX(-66px) translateY(0)' },
                // Middle-right edge piece
                { colors: ['white', 'green', 'yellow'], position: 'translateX(66px) translateY(0)' },
                // Bottom-left corner piece
                { colors: ['white', 'green', 'yellow', 'blue'], position: 'translateX(-66px) translateY(66px)' },
                // Bottom-center edge piece
                { colors: ['white', 'green', 'yellow'], position: 'translateX(0) translateY(66px)' },
                // Bottom-right corner piece
                { colors: ['white', 'green', 'yellow', 'blue'], position: 'translateX(66px) translateY(66px)' },
                // Center piece
                { colors: ['white', 'green', 'yellow', 'blue', 'white', 'orange'], position: 'translateX(0) translateY(0)', isCenter: true },
                // Top face center piece
                { colors: ['red'], position: 'translateX(0) translateY(-66px) translateZ(0) rotateX(90deg)' },
                // Top face fob piece
                { colors: ['red'], position: 'translateX(-66px) translateY(-66px) translateZ(0) rotateX(90deg)' },
                // Top face fob piece
                { colors: ['red'], position: 'translateX(66px) translateY(-66px) translateZ(0) rotateX(90deg)' },
                // Bottom face center piece
                { colors: ['orange'], position: 'translateX(0) translateY(66px) translateZ(0) rotateX(-90deg)' },
                // Bottom face fob piece
                { colors: ['orange'], position: 'translateX(66px) translateY(66px) translateZ(0) rotateX(-90deg)' },
                // Bottom face fob piece
                { colors: ['orange'], position: 'translateX(-66px) translateY(66px) translateZ(0) rotateX(-90deg)' },
                // Front face center piece
                { colors: ['blue'], position: 'translateX(-66px) translateY(0) translateZ(0) rotateY(-90deg)' }
            ];

            pieces.forEach(pieceData => {
                const piece = createPiece(pieceData.colors, pieceData.position, pieceData.isCenter);
                cube.appendChild(piece);
            });
        }

        function rotateGroup(group, axis, angle) {
            const center = { x: 0, y: 0, z: 0 };
            group.forEach(piece => {
                const rect = piece.getBoundingClientRect();
                const pieceCenter = {
                    x: rect.left + rect.width / 2,
                    y: rect.top + rect.height / 2,
                    z: 0
                };
                const dx = pieceCenter.x - center.x;
                const dy = pieceCenter.y - center.y;
                const dz = pieceCenter.z - center.z;

                const newX = center.x + dx * Math.cos(angle) - dy * Math.sin(angle);
                const newY = center.y + dx * Math.sin(angle) + dy * Math.cos(angle);
                const newZ = center.z + dz;

                piece.style.transform = `translate3d(${newX}px, ${newY}px, ${newZ}px) rotate${axis}(${angle}deg)`;
            });
        }

        function handleClick(event) {
            const raycaster = new THREE.Raycaster();
            const mouse = new THREE.Vector2();
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObjects(cube.children);

            if (intersects.length > 0) {
                const clickedPiece = intersects[0].object;
                const group = getGroup(clickedPiece);
                rotateGroup(group, 'Y', Math.PI);
            }
        }

        function getGroup(piece) {
            const group = [];
            cube.children.forEach(child => {
                if (child.position.equals(piece.position)) {
                    group.push(child);
                }
            });
            return group;
        }

        cube.addEventListener('click', handleClick);

        addPieces();
    </script>
</body>
</html>

Would you mind giving a helping hand?
I figured out that you should not load this in jsfiddle.net

I ran the program but all you can do is rotate a 3D image, is there anything else going on here like moving the cubes around etc…

No not really, I just want to make it be able to turn and rotate. I Did add a settings feature for the size of the cube and the color of the background and maybe even the color of the sides.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.