主要内容: 使用 threejs 创建 20x20 的网格,鼠标移动时,方块跟随移动,点击时在网格任意位置放置方块,按 shift 时,删除当前位置方块。

流程如下:

  • 创建网格
  • 创建一个与网格同样尺寸的平面
  • 创建一个方块 mesh_1 与网格同样的尺寸
  • 一个与网格同样的方块 geometry_2 , 不加入 scene 中
  • 三个事件:
    • 鼠标移动事件,随着鼠标移动,更改 mesh_1 位置,并重新渲染
    • 鼠标点击事件,在交点位置,创建新 mesh, 若是相交对象不为 平面,则删除当前对象
    • keydown, keyup, 更改是否删除的状态

详细代码如下:


import * as THREE from './build/three.module'
import { stat } from 'fs'; var camera, scene, renderer;
var moveMesh, staticGeo,staticMat, plane;
var objects = [];
var raycaster, mouse;
var isShiftDown = false; function init() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(500, 800, 1300);
camera.lookAt(0, 0, 0); scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0); // lights
var light = new THREE.AmbientLight(0x606060);
scene.add(light); // grids
var grid = new THREE.GridHelper(1000, 20);
scene.add(grid); // plane, 辅助碰撞检测
var planeGeo = new THREE.PlaneBufferGeometry(1000, 1000);
var planMat = new THREE.MeshBasicMaterial({color: 0xffff00, visible : true});
plane = new THREE.Mesh(planeGeo, planMat);
plane.rotateX(-Math.PI /2);
scene.add(plane);
objects.add(plane); // 射线 raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2(); // moveCube;
var moveGeo = new THREE.BoxBufferGeometry(50, 50, 50);
var moveMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true });
moveMesh = new THREE.Mesh(moveGeo, moveMaterial);
scene.add(moveMesh); // static cube
staticGeo = new THREE.BoxBufferGeometry(50, 50, 50);
staticMat = new THREE.MeshLambertMaterial({ color: 0xfeb74c, map: new THREE.TextureLoader().load('textures/square-outline-textured.png') }); renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement);
document.body.addEventListener('mousemove', onDocuementMouseMove, false);
document.body.addEventListener('mousedown', onDocumentMouseDown, false);
document.body.addEventListener('keydown', onDocuementKeyDown, false);
document.body.addEventListener('keyup', onDocuementKeyUp, false); window.addEventListener('resize', onWindowResize, false);
} function onDocumentMouseDown(event) {
event.preventDefault(); // 鼠标位置归一化
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; // 通过摄像机与鼠标更新射线
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
if(intersects.length > 0) {
var intersect = intersects[0];
if (isShiftDown) {
if(intersect.object !== plane) {
scene.remove(intersect.object);
objects.splice(objects.indexOf(intersect.object), 1);
}
}
else
{
var staticMesh = new THREE.Mesh(staticGeo, staticMat);
staticMesh.position.copy(intersect.point).add(intersect.face.normal);
staticMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);
scene.add(staticMesh);
objects.push(staticMesh);
}
} } function onDocuementMouseMove(event) {
event.preventDefault();
// 鼠标位置归一化
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; // 通过摄像机与鼠标更新射线
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects); if(intersects.length > 0) {
intersect = intersects[0];
// 移动位置到目标点
moveMesh.position.copy(intersect.point).add(intersect.face.normal);
// 计算具体方格
moveMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);
}
render();
} function onDocuementKeyDown(event) {
switch (event.keyCode) {
case 16: isShiftDown = true; break;
}
} function onDocuementKeyUp(event) {
switch (event.keyCode) {
case 16: isShiftDown = false; break;
}
} function onWindowResize() {
camera.aspect = window.innerWidth/ window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight); } function render()
{
renderer.render(scene, camera);
}

threejs 学习之的更多相关文章

  1. ThreeJS学习6_几何体相关(BufferGeometry)

    ThreeJS学习6_几何体相关(BufferGeometry) 使用 BufferGeometry 可以有效减少向 GPU 传输几何体相关数据所需的开销 可以自定义顶点位置, 面片索引, 法向量, ...

  2. # ThreeJS学习7_裁剪平面(clipping)

    ThreeJS学习7_裁剪平面(clipping) 目录 ThreeJS学习7_裁剪平面(clipping) 1. 裁剪平面简介 2. 全局裁剪和局部裁剪 3. 被多个裁剪平面裁剪后 4. 被多个裁剪 ...

  3. WebGL和ThreeJs学习6--射线法确定3D空间中所选物体

    一.在 threejs 中如何确定下图3D空间中鼠标点击位置的 object 对象? 二.射线法确定步骤及代码 //Three.js提供一个射线类Raycaster来拾取场景里面的物体.更方便的使用鼠 ...

  4. WebGL和ThreeJs学习5--ThreeJS基本功能控件

      Threejs 2017年6月6日 15:06 Stats: new Stats();性能监视器,性能测试的方法,引入 Stats.js        http://www.hewebgl.com ...

  5. threejs学习笔记(二)

    THREE.WebGLRenderer THREE.Scene THREE.OrthographicCamera正交相机 THREE.PerspectiveCamera透视相机 renderer.se ...

  6. threejs学习笔记(一)

    得到webgl的渲染管线

  7. threejs和3d各种效果的学习

    写给即将开始threejs学习的自己,各种尝试,各种记忆.不要怕,灰色的年华终会过去. 一个技术学习的快慢,以及你的深刻程度,还有你的以后遇到这个东西的时候的反应速度,很大程度上,取决于你的博客的深刻 ...

  8. 初识webgl--我的webgl学习第一课(基于threeJs)

    一,我为什么要学习webgl 一个偶然的机会,在和朋友的聊天过程中,听说了webgl,也许过去也看到过,但是没有特别在意过.原来,JavaScript也可以很好的渲染并在网页上显示三维动画,不用借助插 ...

  9. gis和threejs的学习资料

    *********************************** 基础知识/名词 瓦片/矢量瓦片GeoJson - 绘制GeoJson看数据, geojson规范, 中文版 ********** ...

随机推荐

  1. JAVA开发第一步 - JDK安装与配置

    JDK的安装与环境变量配置是JAVA开发之路的第一步,很多新人在这一步上就卡了很久,浪费了很多时间,甚至有些人就轻易地“从入门到放弃”了.今天我们就来一步步教你如何打倒这第一只拦路虎. 1.JDK下载 ...

  2. [POI2007]洪水pow 题解

    [POI2007]洪水pow 时间限制: 5 Sec  内存限制: 128 MB 题目描述 AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD ...

  3. <float.h>中DBL_TRUE_MIN的定义和作用

    搬运自己2016年11月22日于SegmentFault发表的文章.链接:https://segmentfault.com/a/1190000007565915 在学习C Prime Plus的过程中 ...

  4. 洛谷P2299 Mzc和体委的争夺战 题解

    题目 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过前三弹的都知道).但如此之多的男家丁吸引来了我们的体委(矮胖小伙),他要来与mzc争夺男家丁. mzc很生气,决定与其决斗,但cat的体 ...

  5. Node.js socket 双向通信

    使用场景:  聊天室:大量数据常驻交互: 技术栈: Node.js,     Vue.js || 原生JS 服务端代码: const app = require('http').createServe ...

  6. MD5的简单用法

    非常简单的MD5加密和解密(即用即copy) 点击帮助灯泡引用就可使用 //生成MD5帮助文件文件 public class MD5Help{ ///MD5加密 方法类 public static s ...

  7. C#3.0新增功能09 LINQ 标准查询运算符 02 查询表达式语法

    连载目录    [已更新最新开发文章,点击查看详细] 某些使用更频繁的标准查询运算符具有专用的 C# 语言关键字语法,使用这些语法可以在查询表达式中调用这些运算符. 查询表达式是比基于方法的等效项更具 ...

  8. [WPF自定义控件库]自定义Expander

    1. 前言 上一篇文章介绍了使用Resizer实现Expander简单的动画效果,运行效果也还好,不过只有展开/折叠而缺少了淡入/淡出的动画(毕竟Resizer模仿Expander只是附带的功能).这 ...

  9. mysqli_query 的定义和用法

     定义和用法 mysqli_query() 函数执行某个针对数据库的查询. 语法 mysqli_query(connection,query,resultmode); 参数 描述 connecti ...

  10. hdu3416+hdu6582(最短路+最大流)

    题意 hdu3416: 给一个图,边不能重复选,问有多少个最短路 hdu6582: 给一个图,问最少删除边权多少的边后,最短路长度增加 分析 边不能重复选这个条件可以想到边权为1,跑最大流,所以我们可 ...