专栏首页前端之攻略three.js鼠标控制物体旋转

three.js鼠标控制物体旋转

当我们需要固定场景背景,固定摄像机的时候。移动旋转物体可以使用Three.js提供的OrbitControls.js,也可以手动写控制器。

原理:获取鼠标点击的位置与移动的距离,根据移动的距离计算出大概旋转的角度。

查看旋转效果

    <script src="../dist/js/three.js"></script>
    <script src="../dist/js/Projector.js"></script>
    <script src="../dist/js/CanvasRenderer.js"></script>
    <script>
    var container;
    var camera, scene, renderer;
    var cube, plane;
    var width, height;

    var targetRotation = 0;
    var targetRotationOnMouseDown = 0;

    var mouseX = 0;
    var mouseXOnMouseDown = 0;

    var windowHalfX = window.innerWidth / 2;
    var windowHalfY = window.innerHeight / 2;
    console.log(window.innerHeight)
    init();
    animate();

    function init() {
        container = document.getElementById('canvasWrap')
        width = document.getElementById('canvasWrap').clientWidth;
        height = document.getElementById('canvasWrap').clientHeight;
        camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
        camera.position.y = 150;
        camera.position.z = 500;

        scene = new THREE.Scene();
        scene.background = new THREE.Color(0xf0f0f0);

        //cube
        var geometry = new THREE.BoxGeometry(200, 200, 200);
        //console.log(geometry.faces.length) //12   一个面有2个三角面片
        for (var i = 0; i < geometry.faces.length; i += 2) {
            var hex = Math.random() * 0xffffff;
            geometry.faces[i].color.setHex(hex);
            geometry.faces[i + 1].color.setHex(hex)

        }
        //vertexColors:THREE.FaceColors  顶点颜色采用上面循环中创建的3角面片的颜色(立方体显示的颜色就是三角面片的颜色)
        //overdraw:0.5 设置的目的避免相邻的2个三角面片有分隔线,相当于重叠部分为0.5
        var material = new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, overdraw: 0.5 }); //
        cube = new THREE.Mesh(geometry, material);
        cube.position.y = 150; //position(0,150,0)
        scene.add(cube);

        //plane
        var geometry = new THREE.PlaneBufferGeometry(200, 200);
        geometry.rotateX(-Math.PI / 2); //从右边看顺时针旋转
        var material = new THREE.MeshBasicMaterial({ color: 0xe0e0e0, overdraw: 0.5 });
        plane = new THREE.Mesh(geometry, material);
        scene.add(plane);

        //CanvasRenderer 有更好的兼容性
        renderer = new THREE.CanvasRenderer();
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(width, height);
        container.appendChild(renderer.domElement);

        document.addEventListener("mousedown", onDocumentMouseDown, false);
        document.addEventListener("touchstart", onDocumentTouchStart, false);
        document.addEventListener("touchmove", onDocumentTouchMove, false);

        window.addEventListener("resize", onWindowResize, false);
    }

    function onWindowResize() {
        windwoHalfX = width / 2;
        windwoHalfY = height / 2;
        camera.aspect = width / height;
        camera.updateProjectionMatrix();

        renderer.setSize(width, height);
    }

    function onDocumentMouseDown(event) {
        event.preventDefault();
        document.addEventListener("mousemove", onDocumentMouseMove, false);
        document.addEventListener("mouseup", onDocumentMouseUp, false);
        document.addEventListener("mouseout", onDocumentMouseOut, false);
        //按下去的时候鼠标相对位置
        mouseXOnMouseDown = event.layerX - windowHalfX;
        //鼠标按下的旋转角度
        targetRotationOnMouseDown = targetRotation;
    }

    function onDocumentMouseMove(event) {
        //移动的时候鼠标相对位置
        mouseX = event.layerX - windowHalfX;
        //移动的时候旋转的角度 = 刚按下鼠标的角度+移动的位置-鼠标按下时的位置
        targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
    }

    function onDocumentMouseUp(event) {
        document.removeEventListener("mousemove", onDocumentMouseMove, false);
        document.removeEventListener("mouseup", onDocumentMouseUp, false);
        document.removeEventListener("mouseout", onDocumentMouseOut, false);
    }

    function onDocumentMouseOut(event) {
        document.removeEventListener("mousemove", onDocumentMouseMove, false);
        document.removeEventListener("mouseup", onDocumentMouseUp, false);
        document.removeEventListener("mouseout", onDocumentMouseOut, false);
    }

    function onDocumentTouchStart(event) {
        if (event.touches.length === 1) {
            event.preventaDefault();
            mouseXOnMouseDown = event.touches[0].layerX - windowHalfX;
            targetRotationMouseDown = targetRotation;
        }
    }

    function onDocumentTouchMove(event) {
        if (event.touches.length === 1) {
            event.preventaDefault();
            mouseX = event.touches[0].layerX - windowHalfX;
            targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;;
        }
    }

    function animate() {
        requestAnimationFrame(animate);
        render();
    }

    function render() {
        // cube.rotation.y 初始值为0
        plane.rotation.y = cube.rotation.y += (targetRotation - cube.rotation.y) * 0.05;
        renderer.render(scene, camera);

    }
    </script>

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用electron实现百度网盘悬浮窗口功能!

    没有使用electron内置的-webkit-app-region: drag 因为使用他那个有很多问题 比如事件无法使用 右键无法使用 以及不能使用手型等!

    李昊天
  • Hive的企业级优化及实战案例

    2、优化二:解释执行计划 语法格式:EXPLAIN [EXTENDED|DEPENDENCY] query 语句示例:explain select dept...

    魏晓蕾
  • 如何使页面交互更流畅

    本篇是基于 FDCon2019 上《让你的网页更丝滑by刘博文》的复盘文。该课题也是博主感兴趣的领域, 后续会结合 React 的 Schedule 与该文进行...

    牧云云
  • 【Kafka】Kafka的代码实现及与Flume的集成

    Kafka分别提供了基于Java和Scala的API,由于Kafka不仅仅只是在大数据中使用到,所以Kafka的Java API应用的比较多。 (1)Kafk...

    魏晓蕾
  • 776. Split BST

    思路: 问题的关键在于进行切分后,树的结构不能改变。影响BST的结构在于输入顺序,所以切分前后,维持输入顺序即可。而BST的层序遍历刚好是最初的输入顺序。所...

    用户1147447
  • 利用官方的vue-cli脚手架来搭建Vue集成开发环境

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/...

    用户1149268
  • Max Chunks To Make Sorted (ver. 1)

    思路: 把数组分成两部分,记作left part 和 right part,求left part 中的最大值,和right part中的最小值,如果最大值比...

    用户1147447
  • spring 自动配置(下) 自动配置总结

    图太大,放不下,请点开大图(不点开大图看的是缩略图),再右键"新标签页打开图片"查看。也可以点开大图保存到本地查看:

    平凡的学生族
  • electron仿制百度网盘客户端2(登录界面制作)

    百度网盘客户端的尺寸是: 主界面 w:662px h:442px 顶部header h:75px bg:#EFF2F6

    李昊天
  • vscode下面开发vue.js项目

    1.首先用官方vue-cli脚手架创建一个vue的集成环境(不会的请阅读上一章节),目录如下:

    用户1149268

扫码关注云+社区

领取腾讯云代金券