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