以上一篇入门篇为例来简单的设置下3d模型当中的交互事件,上一篇我们已经完成了在3d页面中添加了一个红色球,下面我们给这个球一个点击事件让它Y轴位置上升,再设置一个鼠标移入到球上时让其变色。

1.其实three.js当中没有事件可以直接选中物体的,我们需要监听window对象来完成与3d页面的交互,通过使用到three.js当中RayCaster对象,用于在三维空间中进行鼠标拾取,原理是:相机与鼠标所在的设备坐标之间的连线与哪些物体相交。相交的物体离屏幕越近的越靠前,所以第一个物体就是我们选中的对象。

第一步:给window对象添加点击事件监听器;

    window.addEventListener('mousedown', mouseDownFuc);

第二步:在事件监听函数里拾取到点击的对象集合;

    function mouseDownFuc(){
let raycaster = new THREE.Raycaster();//创建光线投射对象
let mouse = new THREE.Vector2();//创建二维平面
let intersectsObjArr = getSelsectOBj(mouse,raycaster, e);//通过封装的getSelsectOBj函数获取鼠标选中对象集合,e是点击事件对象
}
//获取事件操作对象
function getSelsectOBj(mouse,raycaster, e) {
//将html坐标系转化为webgl坐标系,并确定鼠标点击位置
mouse.x = e.clientX / renderer.domElement.clientWidth*2-1;
mouse.y = -(e.clientY / renderer.domElement.clientHeight*2)+1;
raycaster.setFromCamera(mouse,camera);//以camera为z坐标,确定所点击物体的3D空间位置
let intersects = raycaster.intersectObjects(scene.children, true);//确定所点击位置上的物体数量集合
return intersects;//返回连线经过的物体集合
}

第三步:判断intersectsObjArr集合长度不为零,确认我们鼠标点击的地方有物体,如果有物体那么intersectsObjArr[0]就是我们选中的对象,通过页面console.log(intersectsObjArr[0])发现intersectsObjArr[0]包含了相交点的许多信息,而我们只需要交点的对象,所以我们需要取到intersectsObjArr[0].object对象;然后我们还需要进行一次判断当前对象就是我们点击的对象,在这里我们还得回到创建物体时给它的name属性一个值进行区分物体。最后给它position属性值的Y轴坐标设为50;

        myBall.name = 'redBall';//创建物体时给它name属性一个名称
if(intersectsObjArr.length > 0){
if(intersectsObjArr[0].object.name == 'redBall'){
intersectsObjArr[0].object.position.y = 50;
}
}

以上就是我们完成了3d页面物体点击事件,然后就是鼠标的移入到物体变色,移出时颜色还原,这和2d页面的移入移出不太一样,因为我们是给window对象加的监听器,然后通过RayCaster对象来拾取到物体的,所以我们这里需要给window对象加鼠标移动事件来判断鼠标是否移动我们的物体上。其步骤同上点击事件一样。

    window.addEventListener('mousemove', mouseMoveFuc);
function mouseMoveFuc(){
let raycaster = new THREE.Raycaster();//创建光线投射对象
let mouse = new THREE.Vector2();//创建二维平面
let intersectsObjArr = getSelsectOBj(mouse,raycaster, e);//通过封装的getSelsectOBj函数获取鼠标选中对象集合,e是点击事件对象
if(intersectsObjArr.length > 0){
if(intersectsObjArr[0].object.name == 'redBall'){
intersectsObjArr[0].object.material = new THREE.MeshPhongMaterial( { color: 'orange'});//移到物体上时颜色变成橘色
document.getElementsByTagName('body')[0].style.cursor = 'pointer';//移到物体上时鼠标显示为手 }
}else{
myBall.material = new THREE.MeshPhongMaterial( { color: 0xff0000});//移出物体时颜色变成原来的红色
document.getElementsByTagName('body')[0].style.cursor = 'default';//移出物体时鼠标显示为默认
}
}

贴上最终代码:运行一下,看下效果

    <!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>event</title>
<style>
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
overflow: hidden;
background: url('img/bgImg.jpg') no-repeat fixed;
background-size: 100% 100%;
}
</style>
</head>
<body>
<script src="lib/three.min.js"></script>
<script src="lib/OrbitControls.js"></script>
<script>
window.onload = function(){
let scene,camera,renderer,myBall;
initThreeScene();
//物体的事件交互
window.addEventListener('mousedown', mouseDownFuc);
window.addEventListener('mousemove', mouseMoveFuc);
function mouseDownFuc (e) {
let raycaster = new THREE.Raycaster();//光线投射,用于确定鼠标点击位置
let mouse = new THREE.Vector2();//创建二维平面
let intersects = getSelsectOBj(mouse,raycaster, e);
if(intersects.length > 0) {
console.log(intersects[0])
if(intersects[0].object.name == 'myBall') {
myBall.position.y = 50;
}
}
}
function mouseMoveFuc (e) {
let raycaster = new THREE.Raycaster();//光线投射,用于确定鼠标点击位置
let mouse = new THREE.Vector2();//创建二维平面
let intersects = getSelsectOBj(mouse,raycaster, e);
if(intersects.length > 0) {
if(intersects[0].object.name == 'myBall') {
myBall.material = new THREE.MeshPhongMaterial( { color: 'orange'});
document.getElementsByTagName('body')[0].style.cursor = 'pointer';
}
}else {
myBall.material = new THREE.MeshPhongMaterial( { color: 0xff0000});
document.getElementsByTagName('body')[0].style.cursor = 'default';
}
}
//获取事件操作对象
function getSelsectOBj(mouse,raycaster, e) {
//将html坐标系转化为webgl坐标系,并确定鼠标点击位置
mouse.x = e.clientX / renderer.domElement.clientWidth*2-1;
mouse.y = -(e.clientY / renderer.domElement.clientHeight*2)+1;
//以camera为z坐标,确定所点击物体的3D空间位置
raycaster.setFromCamera(mouse,camera);
//确定所点击位置上的物体数量
let intersects = raycaster.intersectObjects(scene.children, true);
return intersects;
}
function initThreeScene() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 2000 );
camera.position.set( 0, 50,300 );   
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });//antialias: true;让渲染的平面是光滑的,alpha: true;让渲染的3d背景透明。
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild(renderer.domElement );
// 给场景添加一个环境光
    let ambientLight = new THREE.AmbientLight( 0xf5f5f5);
scene.add( ambientLight );
//辅助线
let grid = new THREE.GridHelper( 400, 30, 0xcccccc, 0xcccccc );
scene.add( grid );
//创建的球
let ball = new THREE.SphereGeometry( 25, 100, 100 );//25:球半径 第一个100:水平分割面的数量. 第二个100:垂直分割面的数量.
let ballColor = new THREE.MeshPhongMaterial( { color: 0xff0000 } );
myBall = new THREE.Mesh( ball , ballColor );
myBall.name = 'myBall';
scene.add( myBall );
let controls =new THREE.OrbitControls(camera, renderer.domElement);
controls.enableZoom =true;//允许缩放
//设置相机移动距离
controls.minDistance = 1;
controls.maxDistance = 2000;
controls.enableRotate =true;
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();
window.onresize = function () {
    camera.aspect = window.innerWidth / window.innerHeight;//相机重置可视范围
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );//渲染器重新渲染可视范围
}
}
}
</script>
</body>
</html>

three.js中的事件的更多相关文章

  1. 怎么理解js中的事件委托

    怎么理解js中的事件委托 时间 2015-01-15 00:59:59  SegmentFault 原文  http://segmentfault.com/blog/sunchengli/119000 ...

  2. js中冒泡事件和捕获事件

    js中冒泡事件和捕获事件: 冒泡事件:冒泡事件是从里向外,即是从被绑定元素开始一直向外到达页面的所有祖先元素都会被触发,这 一过程被称为事件冒泡.这个事件从原始元素开始一直冒泡到DOM树的最上层 捕获 ...

  3. 看懂此文,不再困惑于 JS 中的事件设计

    看懂此文,不再困惑于 JS 中的事件设计 今天刚在关注的微信公众号看到的文章,关于JS事件的,写的很详细也很容易理解,相关的知识点都有总结到,看完就有种很舒畅的感觉,该串起来的知识点都串起来了.反正一 ...

  4. js中冒泡事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. DOM 以及JS中的事件

    [DOM树节点] DOM节点分为三大节点:元素节点,文本节点,属性节点. 文本节点,属性节点为元素节点的两个子节点通过getElment系列方法,可以去到元素节点 [查看节点] 1 document. ...

  6. 从零开始的JS生活(二)——BOM、DOM与JS中的事件

    上回书说道,JS中变量.运算符.分支结构.循环和嵌套循环等内容.本回就由本K给大伙唠唠JS中的BOM.DOM和事件. 一."花心大萝卜"--BOM 1.震惊,FFF团为何对BOM举 ...

  7. js中的事件,内置对象,正则表达式

    [JS中的事件分类] 1.鼠标事件: click/dbclick/mouseover/mouseout/mousemove/mousedown/mouseup 2.键盘事件: keydown: 键盘按 ...

  8. JS中的事件以及DOM 操作

    [DOM树节点] DOM节点分为三大节点:元素节点,文本节点,属性节点. 文本节点,属性节点为元素节点的两个子节点通过getElment系列方法,可以去到元素节点 [查看节点] 1 document. ...

  9. JS中的事件&对象

    一.JS中的事件 (一)JS中的事件分类 1.鼠标事件 click/dblclick/onmouseover/onmouseout 2.HTML事件 onload/onscroll/onsubmit/ ...

  10. JS学习五(js中的事件)

    [JS中的事件分类] 1.鼠标事件 click/bdlclick/onmouseover/onmouseout 2. HTML事件 onload/onscroll/onsubmit/onchange/ ...

随机推荐

  1. tf.variance_scaling_initializer() tensorflow学习:参数初始化

    CNN中最重要的就是参数了,包括W,b. 我们训练CNN的最终目的就是得到最好的参数,使得目标函数取得最小值.参数的初始化也同样重要,因此微调受到很多人的重视,那么tf提供了哪些初始化参数的方法呢,我 ...

  2. [转]Win10下安装Linux子系统

    工作以来一直DotNet系偏C/S, 接触Web开发的时间也不长, 现在主要偏向Web全栈方向, 一直对Linux系统心生向往, 夜深了娃睡了, 打开老旧的笔记本来折腾一下. 准备工作 控制面板 &g ...

  3. 模板——Treap实现名次树

    Treap 是一种通过赋予结点随机权值的一种满足堆性质的二叉搜索树,它很好的解决了二叉搜索树顺序插入组成链式的局限性. 名次树是指在treap的每个结点中添加附加域size,表示以它为根的子树的总结点 ...

  4. 浅谈集合框架四——集合扩展:集合循环输出方式及list输出方式的效率对比

    最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...

  5. 高可用之keepalived的配置文件详解

    ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover ...

  6. 如何用for..of.. 遍历一个普通的对象?

    如何用for..of.. 遍历一个普通的对象? 首先了解一下for..of..: 它是es6新增的一个遍历方法,但只限于迭代器(iterator), 所以普通的对象用for..of遍历 是会报错的.下 ...

  7. HDU 3974 Assign the task

    Assign the task Problem Description There is a company that has N employees(numbered from 1 to N),ev ...

  8. 2018-8-10-WPF-程序生成类库错误

    title author date CreateTime categories WPF 程序生成类库错误 lindexi 2018-08-10 19:16:53 +0800 2018-2-13 17: ...

  9. jquery的offset().top和js的offsetTop的区别,以及jquery的offset().top的实现方法

    jquery的offset().top和js的offsetTop的区别,以及jquery的offset().top的实现方法 offset().top是JQ的方法,需要引入JQ才能使用,它获取的是你绑 ...

  10. Canal常用配置

    Canal 是mysql数据库binlog的增量订阅&消费组件. 基于日志增量订阅&消费支持的业务: 数据库镜像 数据库实时备份 多级索引 (卖家和买家各自分库索引) search b ...