用于展示3D动效,就是 跟拍电影一样,需要有3大模块:scene,camera,renderer。

  • scene:场景,用于放置用到的模型。
  • camera:摄像机,拍电影似的,得有个摄像机。
  • renderer:渲染器,很重要,用于与被渲染的dom元素挂钩,也用于 与场景、摄像机 挂钩。

一个动效的制作过程如下:

  1. 得到三大基础模块:scene, camera, renderer

  2. 绘制结果与DOM挂钩

  3. 加载摄像头控制器(可选),用于 旋转、缩放等效果

  4. 添加场景内 模型

  5. 渲染

  6. 事件设置(可选)

示例是一个 星球,顶点上 是 文字。可旋转,缩放:

<html>
<head>
<title>球状旋转_sprite_v2.html</title>
<meta charset="utf-8">
<style>
body { margin: 0; }
</style>
</head>
<body>
</body>
<script src="js/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script>
/**
* 3d加载步骤
* 1、得到三大基础模块:scene, camera, renderer
* 2、绘制结果与DOM挂钩
* 3、加载摄像头控制器(可选)
* 4、添加场景内 模型
* 5、渲染
* 6、事件设置(可选)
*/ var scene, camera, renderer, controls, group;
var container;
var startX, startY;
container = document.createElement( 'div' );
document.body.appendChild( container ); /*1*/
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, window.innerWidth/window.innerHeight, 1, 1000 );
camera.position.z = 50;
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight ); /*2*/
container.appendChild( renderer.domElement ); /*3*/
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.minDistance = 20;
controls.maxDistance = 50;
controls.maxPolarAngle = Math.PI / 2; /*4*/
group = new THREE.Group();
scene.add( group ); var vertices = new THREE.DodecahedronGeometry( 10 ).vertices; //多个精灵
vertices.forEach(function (item, index) {
var sprite = createSpriteTextNoPosition(index);
sprite.position.set(item.x, item.y, item.z);
sprite.clickFlag = true;
sprite.aa = '序号:' + index;
group.add(sprite);
}); /*5*/
var animate = function () {
requestAnimationFrame( animate ); // group.rotation.x += 0.005;
group.rotation.y += 0.005; renderer.render( scene, camera );
};
animate(); /*6*/
//监听移动端touchstart事件
function onTouchStart(e) {
// console.log('触摸开始')
// console.log(e) var touch = e.touches[0]; //获取第一个触点
var x = Number(touch.pageX); //页面触点X坐标
var y = Number(touch.pageY); //页面触点Y坐标
//记录触点初始位置
startX = x;
startY = y;
}
//监听移动端touchEnd事件
function onTouchEnd(e) {
// console.log('触摸结束')
// console.log(e);
if (e.changedTouches[0].pageX == startX && e.changedTouches[0].pageY == startY)
getClickMap(e);
} function getClickMap(event) {
event.preventDefault();
var mouse = {}; mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
if(event.touches) {
mouse.x = (event.changedTouches[0].pageX / window.innerWidth) * 2 - 1;
mouse.y = -(event.changedTouches[0].pageY / window.innerHeight) * 2 + 1;
}
var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5); vector = vector.unproject(camera); var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); var intersects = raycaster.intersectObjects(group.children); //TODO 这个50 距离原点的距离, 正好就是 摄像头 到 球心的距离应该是。
if (intersects.length > 0 && intersects[0].distance < 50 && intersects[0].object.clickFlag) {
console.log(intersects[0].object.aa);
}
}
function createSpriteTextNoPosition(index){
//先用画布将文字画出
let canvas = document.createElement("canvas");
canvas.width = 400;
let ctx = canvas.getContext("2d");
ctx.fillStyle = "#ffff00";
ctx.font = "Bold 100px Arial";
ctx.lineWidth = 4;
ctx.fillText("萨克拉" + index,4,104);
let texture = new THREE.Texture(canvas);
texture.needsUpdate = true;//不设置,会 不出现 //使用Sprite显示文字
let material = new THREE.SpriteMaterial({map:texture});
let textObj = new THREE.Sprite(material);
textObj.scale.set(4, 2, 1);
return textObj;
}
document.addEventListener('mousedown', getClickMap, false);
document.addEventListener('touchstart', onTouchStart, false);
document.addEventListener('touchend', onTouchEnd, false); </script>
</html>

实现过程中遇到了一些问题,这里特做以记录:

1、geometry 带有顶点的 几何图形

2、获取几何图形的顶点,数组
利用属性 vertices

3、group 组的概念,用于 多个模型分组。
常用于 整个组 内容 一起 旋转之类。

4、group.children 可获取到 组内所有的 模型。scene.children同理
5、光投影

6、orbitControls 与移动端 touchmove事件冲突,不能共存
7、利用 touchStart 和 touchEnd 判断是否为点击事件
利用 touch事件对象 的 changedTouches[0];start和 end皆有; 如果 start里的 坐标 等于 end 里的 坐标,则为点击。

8、模型上移
不做其他改变,使用定位,将画布绝对定位 top=-100px;点击事件里 pageY + 100

9、bug:手机浏览器 画布过大,超过屏幕,与google调试不一致;
强行指定canvas给渲染器,并 important 宽高 为100%。

10、球形顶点 多点旋转:点与数据量实施方案
顶点数须大于数据量:遍历顶点,数据量不够则再来一遍。铺满

11、MeshPhongMaterial 镜面材质,需要灯光
12、MeshBasicMaterial 基础材质,普通上色,不需灯光

13、动效切换,清除
a、停止动效 (必须cancelAnimationFrame)
b、清除场景内模型 (需要深清除,内存里的)
移除场景内的子元素,需注意 不要移除 摄像机和灯光(子元素包含了)。
c、有绑定事件的 移除事件

14、canvas文本显示不清晰,
解决:使用textObj.scale.set(4,2,1); 对sprite 进行缩放,参数是 缩放量,三维的。改变前两参数就行

threejs 初识的更多相关文章

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

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

  2. 首个threejs项目-前端填坑指南

    第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来.经过老板20天惨无人道的摧残,终于小有成就. 因为第一次搞 ...

  3. Android动画效果之初识Property Animation(属性动画)

    前言: 前面两篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画).Frame Animation(逐帧动画)Andr ...

  4. 初识Hadoop

    第一部分:              初识Hadoop 一.             谁说大象不能跳舞 业务数据越来越多,用关系型数据库来存储和处理数据越来越感觉吃力,一个查询或者一个导出,要执行很长 ...

  5. python学习笔记(基础四:模块初识、pyc和PyCodeObject是什么)

    一.模块初识(一) 模块,也叫库.库有标准库第三方库. 注意事项:文件名不能和导入的模块名相同 1. sys模块 import sys print(sys.path) #打印环境变量 print(sy ...

  6. 转 threejs中3D视野的缩放实现

    Threejs基础部分学习知道透视相机new THREE.PerspectiveCamera(fov, aspect , near,far)中. fov视野角(拍摄距离)越大,场景中的物体越小.fov ...

  7. Threejs中的材质贴图

    最近项目需要折腾three.js,有关three.js几点说明 1.作用 threejs适合创建简单的模型视图 2.对于复杂的模型图(如:室内模型图)需要美术3D制作,前端导成特定格式文件(如*.mt ...

  8. 初识IOS,Label控件的应用。

    初识IOS,Label控件的应用. // // ViewController.m // Gua.test // // Created by 郭美男 on 16/5/31. // Copyright © ...

  9. UI篇(初识君面)

    我们的APP要想吸引用户,就要把UI(脸蛋)搞漂亮一点.毕竟好的外貌是增进人际关系的第一步,我们程序员看到一个APP时,第一眼就是看这个软件的功能,不去关心界面是否漂亮,看到好的程序会说"我 ...

随机推荐

  1. Linux之安装常用软件

    Linux下安装软件的方法: 1,rpm(不推荐使用) 2,yum安装(使用快捷方便) 3,编译安装 一.安装python3(这里使用的是编译安装) 1,下载python3源码包 在centos下,第 ...

  2. MySql 注意点

    每条操作语句的结束都要加:(遇到:就会执行操作) DELIMITER 其实本身相当 :当存储过程中包含:的时候,就需要用 DELIMITER 来区分 我们会经常看到 DELIMITER $$ 或者DE ...

  3. java开发环境配置——IDEA SVN的使用

    一.安装svn客户端,在idea中配置svn 装小乌龟,TortoiseSVN ,就下图一个要注意的地方,这里默认 command line client tools是不安装的,选上.如果已经安装过了 ...

  4. java-文件读取

    1.利用递归读取文件 (1)NotifyFolder.java package com.etc; import java.io.File; import java.io.IOException; im ...

  5. 利用MingW检验程序运行内存

    今天zhx老师在讲课的时候提到了一种检验程序内存的方法 一般计算内存的方法就是手算,手动计算代码中每个变量所占的内存然后加起来 具体可以参考这篇文章 zhx老师讲的方法可以实现全自动化计算内存 具体怎 ...

  6. 51nod“省选”模测第二场 C 小朋友的笑话(线段树 set)

    题意 题目链接 Sol 直接拿set维护\(li\)连续段.因为set内的区间互不相交,而且每个线段会被至多加入删除一次,所以复杂度是对的. #include<bits/stdc++.h> ...

  7. Djang之cookie和session

    一 会话跟踪 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而10086服务人员就是服务器 ...

  8. Dynamics 365使用Execute Multiple Request删除系统作业实体记录

    摘要: 本人微信公众号:微软动态CRM专家罗勇 ,回复295或者20190112可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me ...

  9. 推荐一款好用的office转换PDF工具

    北京博信施科技有限公司是一家专业从事数据格式转换.数据处理领域研发软件产品和解决方案实施的技术型公司.在当今信息时代,PDF文档格式是在Internet上进行电子文档发行和数字化信息传播的理想文档格式 ...

  10. Android 为TV端助力

    记录两次事情: 第一个给view添加动画效果,需要保证view是可以获取焦点的 第二个给listview,GridView设置选择器 listselector时,要保证他的子item无背景,否则选择器 ...