three.js鼠标事件

实现功能:
1.左键点击方块并移动鼠标,方块跟随鼠标移动。
2.右键点击方块并移动鼠标,方块旋转。
3.鼠标滚动可以放大或缩小方块。

代码实现如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Three.js_MouseEvent</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    </style>
    <script type="text/javascript" src="three.js-master/build/three.js"></script>
    <script type="text/javascript" src="three.js-master/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<div id="output">

</div>
<script>
    function init() {
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(15, 15, 15);
        camera.lookAt(scene.position);
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        var cube = new THREE.Mesh(new THREE.BoxGeometry(3, 3, 3), new THREE.MeshBasicMaterial({
            color: 0x0051ba,
            wireframe: true
        }));
        scene.add(cube);
        document.getElementById("output").appendChild(renderer.domElement);

        render();

        function render() {
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

        document.addEventListener('mousedown', onMouseDown);
        document.addEventListener('mouseup', onMouseUp);
        document.addEventListener('wheel', onMouseWheel);
        //阻止右键菜单呼出事件
        document.oncontextmenu = function (event) {
            event.preventDefault();
        };

        var liftMouseDown, rightMouseDown;
        var selectObj, lastPosition;
        var lastIntersection, nowIntersection;
        var mouseX, mouseY;

        function onMouseDown(event) {
            var rayCaster = getRay(event);
            var intersects = rayCaster.intersectObjects([cube]);//参数需为数组
            //左键点击并且点击的是物体时
            if (event.button === 0 && intersects[0]) {
                selectObj = intersects[0].object;//储存当前点击的对象
                liftMouseDown = true;
                lastPosition = selectObj.position;//储存当前物体坐标位置
                lastIntersection = getIntersection(event);//获取点击时的交点
                document.addEventListener('mousemove', onMouseMove);
            }
            //右键点击屏幕时
            if (event.button === 2) {
                mouseX = event.clientX;
                mouseY = event.clientY;
                rightMouseDown = true;
                document.addEventListener('mousemove', onMouseMove);
            }
        }

        function onMouseUp(event) {
            liftMouseDown = false;
            rightMouseDown = false;
            document.removeEventListener('mousemove', onMouseMove);
        }

        function onMouseMove(event) {
            //左键点击状态下移动,网格跟随鼠标移动
            if (liftMouseDown) {
                nowIntersection = getIntersection(event);//获得移动后当前的交点
                var offset = new THREE.Vector3();
                //现在的交点减去之前的交点能够得到一个位移向量,再加上之前的物体坐标,就等于现在的物体坐标
                selectObj.position.copy(offset.subVectors(nowIntersection, lastIntersection).add(lastPosition));
                lastIntersection = nowIntersection;
                lastPosition = offset;
            }
            //右键点击状态下移动,网格自身跟随鼠标旋转
            if (rightMouseDown) {
                var deltaX = event.clientX - mouseX;
                mouseX = event.clientX;
                var deltaY = event.clientY - mouseY;
                mouseY = event.clientY;
                rotation(deltaX, deltaY);
            }
        }

        //旋转物体
        function rotation(x, y) {
            cube.rotation.y += x / 100;
            cube.rotation.x += y / 100;
        }

        //鼠标中键滚动时放大或者缩小
        function onMouseWheel(event) {
            if (event.wheelDelta > 0) {
                cube.scale.copy(cube.scale.add(new THREE.Vector3(0.1, 0.1, 0.1)))
            } else {
                cube.scale.copy(cube.scale.sub(new THREE.Vector3(0.1, 0.1, 0.1)))
            }
        }

        //根据鼠标点击的点和相机建立一条射线
        function getRay(event) {
            event.preventDefault();
            var mouse = new THREE.Vector2();
            var rayCaster = new THREE.Raycaster();
            var rect = renderer.domElement.getBoundingClientRect();
            mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
            mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
            rayCaster.setFromCamera(mouse, camera);
            return rayCaster;
        }

        //获取射线与屏幕平面的交点
        function getIntersection(event) {
            var plane = new THREE.Plane();
            //通过相机位置生成法向量,该法向量和一个点可以建立一个平面
            plane.setFromNormalAndCoplanarPoint(camera.getWorldDirection(plane.normal), new THREE.Vector3(0, 0, 0));
            var rayCaster = getRay(event);
            var worldPoint = new THREE.Vector3();
            //获得射线和平面相交的世界坐标
            rayCaster.ray.intersectPlane(plane, worldPoint);
            return worldPoint;
        }
    }

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

欢迎评论!

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值