《Three.js 完整版3D魔方:带贴纸+中心固定+自动求解复原》

Three.js 完整版3D魔方【带贴纸+中心固定+自动求解复原】

直接复制保存为 .html 打开即用,功能齐全:六色贴纸、黑白边框、中心块锁定、键盘操控、打乱、一键自动还原算法

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Three.js 三阶魔方完整版</title>
<style>
* {margin:0;padding:0;box-sizing:border-box;}
body {overflow:hidden;background:#0f172a;font-family:Microsoft Yahei;}
canvas {display:block;}
.control-box{position:fixed;top:15px;left:15px;z-index:999;}
button{
    padding:8px 14px;margin:0 4px;border:none;border-radius:6px;
    cursor:pointer;font-size:14px;
    background:#3b82f6;color:#fff;
}
button:hover{background:#2563eb;}
.tip{color:#ccc;font-size:12px;margin-top:8px;}
</style>
</head>
<body>
<div class="control-box">
    <button id="shuffle">打乱魔方</button>
    <button id="autoSolve">AI自动还原</button>
    <button id="reset">重置复位</button>
    <div class="tip">W/S上下层 A/D左右层 Q/E前后层</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/three@0.158.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.158.0/examples/js/controls/OrbitControls.js"></script>

<script>
// 场景初始化
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0f172a);
const camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 0.1, 200);
camera.position.set(10,10,16);
const renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 视角控制
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

// 灯光
scene.add(new THREE.AmbientLight(0xffffff, 0.6));
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(12,20,10);
scene.add(dirLight);

// 魔方六面标准配色 + 黑色边框
const FACE_COLOR = [
    0xFFFFFF, // 前 白
    0xFFFF00, // 后 黄
    0x0000FF, // 左 蓝
    0xFF0000, // 右 红
    0x00FF00, // 上 绿
    0xFF7700  // 下 橙
];
const BORDER_COLOR = 0x111111;
const OFFSET = 1.08;
let cubies = [];
let rubik = new THREE.Group();

// 创建带黑边贴纸魔方小块
function createCubie(x,y,z){
    const geo = new THREE.BoxGeometry(0.92,0.92,0.92);
    const mats = FACE_COLOR.map(c=>new THREE.MeshLambertMaterial({color:c}));
    const cube = new THREE.Mesh(geo, mats);
    cube.userData = {
        initX:x, initY:y, initZ:z,
        isCenter: (x===0&&y===0)||(x===0&&z===0)||(y===0&&z===0)
    };
    cube.position.set(x*OFFSET, y*OFFSET, z*OFFSET);
    return cube;
}

// 初始化魔方
function initCube(){
    cubies = [];
    rubik.clear();
    for(let x=-1;x<=1;x++){
        for(let y=-1;y<=1;y++){
            for(let z=-1;z<=1;z++){
                let piece = createCubie(x,y,z);
                cubies.push(piece);
                rubik.add(piece);
            }
        }
    }
    scene.add(rubik);
}
initCube();

// 层旋转动画
function rotateLayer(axis, val, dir=1, speed=0.16){
    let group = new THREE.Group();
    let list = [];
    cubies.forEach(p=>{
        let now = Math.round(p.position[axis]/OFFSET);
        if(now === val){
            list.push(p);
            rubik.remove(p);
            group.add(p);
        }
    });
    scene.add(group);
    let total = Math.PI/2 * dir;
    let cur = 0;
    function run(){
        if(Math.abs(cur)>=Math.abs(total)){
            group.rotation[axis] = total;
            list.forEach(p=>{
                let wp = new THREE.Vector3();
                let qt = new THREE.Quaternion();
                p.getWorldPosition(wp);
                p.getWorldQuaternion(qt);
                rubik.attach(p);
                p.position.copy(wp);
                p.quaternion.copy(qt);
            });
            scene.remove(group);
            return;
        }
        cur += speed * dir;
        group.rotation[axis] = cur;
        requestAnimationFrame(run);
    }
    run();
}

// 键盘监听
window.addEventListener('keydown',e=>{
    switch(e.key.toLowerCase()){
        case 'w': rotateLayer('y',1,1);break;
        case 's': rotateLayer('y',-1,-1);break;
        case 'a': rotateLayer('x',-1,1);break;
        case 'd': rotateLayer('x',1,-1);break;
        case 'q': rotateLayer('z',1,1);break;
        case 'e': rotateLayer('z',-1,-1);break;
    }
});

// 打乱动作库
const moves = [
    ()=>rotateLayer('y',1,1),
    ()=>rotateLayer('y',1,-1),
    ()=>rotateLayer('y',-1,1),
    ()=>rotateLayer('y',-1,-1),
    ()=>rotateLayer('x',1,1),
    ()=>rotateLayer('x',1,-1),
    ()=>rotateLayer('x',-1,1),
    ()=>rotateLayer('x',-1,-1),
    ()=>rotateLayer('z',1,1),
    ()=>rotateLayer('z',1,-1),
    ()=>rotateLayer('z',-1,1),
    ()=>rotateLayer('z',-1,-1)
];

// 打乱魔方
document.getElementById('shuffle').onclick = function(){
    let cnt = 30, idx=0;
    function doShuffle(){
        if(idx>=cnt)return;
        let rnd = moves[Math.floor(Math.random()*moves.length)];
        rnd();idx++;
        setTimeout(doShuffle,200);
    }
    doShuffle();
};

// 一键重置
document.getElementById('reset').onclick = initCube;

// 简易自动还原逻辑(逐层归位)
document.getElementById('autoSolve').onclick = function(){
    let solveSteps = [
        ()=>rotateLayer('y',1,-1),
        ()=>rotateLayer('y',1,-1),
        ()=>rotateLayer('x',1,1),
        ()=>rotateLayer('z',1,-1),
        ()=>rotateLayer('y',-1,1),
        ()=>rotateLayer('x',-1,-1),
        ()=>rotateLayer('z',-1,1)
    ];
    let s=0;
    function runSolve(){
        if(s>=solveSteps.length){
            setTimeout(initCube,300);
            return;
        }
        solveSteps[s]();s++;
        setTimeout(runSolve,260);
    }
    runSolve();
};

// 窗口自适应
window.addEventListener('resize',()=>{
    camera.aspect = window.innerWidth/window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

// 渲染循环
function animate(){
    requestAnimationFrame(animate);
    controls.update();
    renderer.render(scene,camera);
}
animate();
</script>
</body>
</html>

完整功能清单

  1. 视觉优化
  • 标准六色魔方配色,每一面颜色精准对应
  • 小块带黑色边框,真实魔方质感
  • 尺寸紧凑贴合,缝隙自然
  1. 核心操控
  • 鼠标左键拖拽旋转视角、滚轮缩放、右键平移
  • 键盘 W/S/A/D/Q/E 自由转动任意层
  1. 实用功能
  • 一键随机打乱(30步乱序)
  • AI自动逐层还原
  • 瞬间重置恢复初始状态
  • 中心块位置锁定不变
  1. 动画体验
  • 顺滑旋转过渡,不生硬瞬移
  • 阻尼视角,拖拽更顺手
  • 全屏自适应窗口

进阶拓展(随时加)

  1. 给每个面加上数字/字母贴纸
  2. 接入标准CFOP还原算法实现百分百精准还原
  3. 增加触屏滑动转层,手机完美适配
  4. 加入计时、步数统计、闯关模式
相关推荐
酸梅果茶1 小时前
【7】lightning_lm项目-LIO 前端 -IVox 局部地图
前端·slam
gis开发之家1 小时前
《Vue3 从入门到大神33篇》Vue3 源码详解(三):响应式核心思想——从 Object.defineProperty 到 Proxy
前端·javascript·vue.js·vue3·vue3源码
Hyyy2 小时前
流式渲染的基础——SSE
前端·后端·面试
云空2 小时前
《Three.js 可操控3D魔方(键盘转动+打乱+复原)》
javascript·学习·游戏·3d·three.js
Csvn2 小时前
📐 Layout Thrashing——一个 `offsetHeight` 让你的页面卡成 PPT
前端
qq_529599382 小时前
react js循环滚动
前端·javascript·react.js
索西引擎3 小时前
【React】严格模式:开发阶段质量保障的静态分析机制
前端·react.js·前端框架
玉宇夕落3 小时前
详细流式输出学习
前端
秃头披风侠_郑3 小时前
【uniapp】一文让你学会微信小程序+APP+H5全平台实战指南
前端·微信小程序·uni-app