Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

javascript 3d网页 基于 three.js (一)

weihexin 2020-03-09 10:34:00 阅读数:12 评论数:0 点赞数:0 收藏数:0

 "use strict"
//加载js文件
loadFile([
 "./js/lib/WebGL.js",//检查 是否支持webGL 插件
"./js/lib/three_114.min.js",//3d库
"js/func.js"
], main);

//创建一个ajax请求, 前往index.php验证用户是否已登录
//如果Ajax返回的是false说明用户还没有登录成功,并前往 view.php, 
//否则ajax返回用户信息对象
function main(){
 new Ajax({
 url:"./php/index.php",
 method:"get",
 success:(data)=>{
 let d = JSON.parse(data);
 if(d === false){location.href = "./login/view.php"; return;}
 showUserInfo(d.val, new View());//用户信息视图
showThreeView();//场景3d视图
 }
  });
 }

//退出
function exit(){
 if(new Func().isRun({id:"testId"}) !== true){console.log("你点得太快了,服务器跟不上"); return;}
 new Ajax({
 url:"./php/exit.php",
 method:"get",
 success:(data)=>{main();}
  });
 }

//创建html p元素
function create(v, fel, content){
 let p = v.add(fel, "p");
 p.innerHTML = content || "";
 return p;
 }

//创建登录成功后的主页内容
function showUserInfo(user, v){//console.log(user);
var lid = v.get("loginBoxId");

var elem_name = create(v, lid, "你好: " + user.UserName);
 elem_name.innerHTML += "<input type = 'button' id = 'exitId' value = '退 出' />";
 v.get('exitId').onclick = ()=>{exit();}//退出按钮
create(v, lid, "我知道你的邮箱是: " + user.Email);

switch(user.Like.length){
 case 1 :
 create(v, lid, "我还知道你喜欢: " + user.Like[0]);
 break;
 case 2 :
 create(v, lid, "我还知道你喜欢: " + user.Like[0]);
 create(v, lid, "还有: " + user.Like[1]);
 break;
 case 3 :
 create(v, lid, "我还知道你喜欢: " + user.Like[0]);
 create(v, lid, "还有: " + user.Like[1]);
 create(v, lid, "还有: " + user.Like[2]);
 break;
 default : break;
  }
 lid.style = "visibility:visible;";
 //lid居中显示
/* let x = Math.round((v.client.w/2) - (lid.offsetWidth/2));
  let y = Math.round((v.client.h/2) - (lid.offsetHeight/2)) - 16;
  lid.style = "left:"+x+"px; top:"+y+"px; visibility:visible;"; */
}

//创建 主页 3d 视图
/*
 键盘 w a s d移动
  鼠标 点击滑动旋转
 */
function showThreeView(){

var three = new Three();

//场景
var scene = three.createScene();

//相机
var camera = three.createCamera(); //console.log(camera);
//渲染器
var renderer = three.createRenderer();

//灯光
var light = three.createLight(scene);

//控制器
 three.createControl(camera, renderer);

//动画循环
 three.animate(scene, camera, renderer);

//创建地面
 three.createGround();

//创建院墙
three.createWall({isSetY:true});

//创建铁门
 three.createGate();

 console.log(three);
 alert("键盘 w a s d移动, 鼠标 点击滑动旋转");
 }
 "use strict"
/**方法类

*/
class Func{

 constructor(){}

//获取一个字符串的长度 包含中文
 getStrLen(str){
 let len = 0, i, c;
 for (i = 0; i < str.length; i++){
 c = str.charCodeAt(i);
 if((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)){len++;}else{len+=2;}
  }
 return len;
  }

//获取目标范围随机数(n保留浮点数数量)
 getran(min, max, n){
 return Number((Math.random() * (max - min) + min).toFixed(n || 0));//包含max
 }

//获取2点距离
 getPosLen(sdot, edot){
 return parseInt(Math.sqrt(Math.pow(Math.abs(sdot.x - edot.x), 2) + Math.pow(Math.abs(sdot.y - edot.y), 2)));
  }

//检测是否是pc端
 isPC(){
 let userAgent = navigator.userAgent;
 let agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
 let ispc = true, v;
 for(v = 0; v < agents.length; v++){
 if (userAgent.indexOf(agents[v]) > 0){ispc = false; break;}
  }
 return ispc;
  }

//防止多次提交或执行(在规定时间段内只允许执行一次) 默认 3000ms
 isRun(object){
 //object = {id: string 必须, isExit, time}
//isEnit : boolean 可选 如果为 true 则删除对应 id 的对象
//time : number 可选 默认间隔时间 3000 秒
var v = object || {};
 if(this.list === undefined){Func.prototype.list = {};}
 if(v.id === undefined || typeof(v.id) !== "string"){return "参数id错误";}
 if(v.isExit === true){delete(this.list[v.id]); return "删除对象: "+v.id;}
 var o = this.list[v.id];
 if(!o){this.list[v.id] = {time:v.time || 3000, nowTime:new Date().getTime()}; return true;}
 var t = new Date().getTime() - o.nowTime;
 if(t < o.time){return o.time - t;}
 o.nowTime = new Date().getTime();
 return true;
  }

}

/** 创建Ajax请求:
  obj = {
  url: string 必须, 请求路径
  method: string 可选, post 或 get请求, 默认post请求
  data: string 可选, 要发送的数据, 默认为""
  asy: boolean 可选, 是否异步执行, 默认为true
  success: function 可选, 成功回调
  error: function 可选, 失败回调
  run: function 可选, 请求中回调
  }

 xhr.readyState:
  0: 请求未初始化
  1: 服务器连接已建立
  2: 请求已接收
  3: 请求处理中
  4: 请求已完成,且响应已就绪
  xhr.status:
  200: "OK"
  404: 未找到页面
 */
class Ajax{

 constructor(obj){
 let o = obj || {}
 this.url = o.url || null;
 this.method = o.method || "post";
 this.data = o.data || "";
 this.asy = o.asy || true;
 this.callback_suc = o.success || function (){};
 this.callback_err = o.error || function (){};
 this.callback_run = o.run || function (){};
 this.request();
  }

 request(){
 if(!this.url){this.callback_err(); return;}
 let xhr = new XMLHttpRequest();
 xhr.onreadystatechange = (e)=>{
 if(e.target.readyState === 4 && e.target.status === 200){
 this.callback_suc(e.target.responseText);
 return;
  }
 this.callback_run(e);
  }
 xhr.onerror = (e)=>{
 this.callback_err(e);
  }
 if(this.method == "get"){
 xhr.open(this.method, this.url, this.asy);
  xhr.send();
 return;
  }
 xhr.open(this.method, this.url, this.asy);
 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
 xhr.send(this.data);
  }

}

/** 视图类

*/
class View{

 constructor(){
 if(!this.client){View.prototype.client = this.getClient();}
  }

//创建html元素
 add(fel, elemName, id, cls){
 //创建一个元素
let el = document.createElement(elemName);
 //设置el id 和 class
if(id){el.setAttribute('id',id);}
 if(cls){el.className = cls;}
 //把el添加到fel并显示(渲染el)
if(fel){fel.appendChild(el);}
 return el;
  }

//删除html元素
 remove(){
 let k, arg = arguments, err = [];
 for(k = 0; k < arg.length; k++){
 if(this.isEl(arg[k]) === false){err.push(arg[k]); continue;}
  arg[k].parentNode.removeChild(arg[k]);
  }
 if(err.length > 0){return {err:'这里有一些删除失败的元素', arr:err};}
 return true;
  }

//id获取html元素
 get(id){
 return document.getElementById(id);
  }

//获取可视宽高
 getClient(){
 return {
 w:document.documentElement.clientWidth || document.body.clientWidth,
 h:document.documentElement.clientHeight || document.body.clientHeight
  };
  }

//通过parentNode检查元素是否存在于页面中
 isEl(el){
 if(typeof(el) !== 'object'){return false;}
 //被删除之后的html元素object的 parentNode等于null
if(!el.parentNode){return false;}
 return true;
  }

//元素绑定事件
 addEvent(target, ev, callback){
 target.addEventListener(ev, function(e){if(callback){callback(e);}}, false);
  }

}

/** 3d库
  three.js --- version number 114
  create scene
 */
class Three{

 constructor(){
 if (WEBGL.isWebGLAvailable() === false){
 alert("你不支持WebGL");
 return;
  }
 this.view = new View();
 THREE.Cache.enabled = true;//加载器启用缓存
this.clock = new THREE.Clock();//
 this.group = new THREE.Group();//创建一个 分组
this.textures = this.createTexture();//存放 纹理 的对象
 }

//创建 场景
 createScene(){
 var scene = new THREE.Scene();
 //scene.fog = new THREE.Fog(0xcce0ff, 800, 1000);//线性雾
scene.background = new THREE.CubeTextureLoader()
 .setPath('img/cube/skyboxsun25deg/')
 .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );
 if(this.group){scene.add(this.group);}
 return scene;
  }

//创建 相机
 createCamera(){
 var camera = new THREE.PerspectiveCamera(75, this.view.client.w/this.view.client.h, 1, 5000);
camera.position.set(0, 150, 300);//相机起始位置
return camera;
  }

//创建 渲染器
 createRenderer(){
 var renderer = new THREE.WebGLRenderer({
 antialias : true,//抗割齿
powerPreference:"high-performance"//选择高性能GPU渲染
 });
 renderer.setSize(this.view.client.w, this.view.client.h);//设置渲染大小
renderer.setPixelRatio(window.devicePixelRatio);//渲染矫正
renderer.gammaFactor = 2.2;//着色校正
renderer.physicallyCorrectLights = true;//使其精确照明
renderer.shadowMap.enabled = true;//渲染阴影
//renderer.autoClear = true;//每帧自动清理缓存
if(!renderer.extensions.get('WEBGL_depth_texture')){console.log("深度纹理扩展获取失败:WEBGL_depth_texture");}
  document.body.appendChild(renderer.domElement);
 renderer.domElement.style.zIndex = "0";
 renderer.domElement.style.position = "absolute";
 renderer.domElement.style.top = "0px";
 renderer.domElement.style.left = "0px";
 return renderer;
  }

//创建 灯光
 createLight(scene){
 scene.add(new THREE.AmbientLight(0x696969));//环境光(无处不在的光,太阳光)
var l_d = 1000, light = new THREE.DirectionalLight(0xF0F8FF, 1);//平行光(产生阴影的光)
light.position.set(-3000, 3000, -3000);
 light.position.multiplyScalar(1);
 //阴影
light.castShadow = true;
 light.shadow.mapSize.width = 1024;
 light.shadow.mapSize.height = 1024;
 light.shadow.camera.left = -l_d;
 light.shadow.camera.right = l_d;
 light.shadow.camera.top = l_d;
 light.shadow.camera.bottom = -l_d;
 light.shadow.camera.near = 1;
 light.shadow.camera.far = 6000;
  scene.add(light);
 return light;
  }

//创建 控制器
 createControl(camera, renderer){
 var create = ()=>{
 let control = new THREE.OrbitControls(camera, renderer.domElement);
 control.target = new THREE.Vector3(0, 100, 0);//相机焦点
//control.minPolarAngle = Math.PI * 0.3;//向上最大角度
//control.maxPolarAngle = Math.PI * 0.4;//向下最大角度
control.minDistance = 1;//最小距离
control.maxDistance = 1000;//最大距离
control.autoRotateSpeed = 10;//自动旋转速度
control.panSpeed = 100;//鼠标旋转速度
control.enableZoom = true;//是否启用缩放
control.enableKeys = true;//是否启用键盘
control.keyPanSpeed = 100;//按键速度
control.keys.LEFT = 65;//key a左
control.keys.UP = 87;//key w前
control.keys.RIGHT = 68;//key d右
control.keys.BOTTOM = 83;//key s后
this.control = control;
  }
 loadFile("./js/lib/OrbitControls.js", create);//加载 控制器 插件
 }

//创建 动画循环
 animate(scene, camera, renderer){
 requestAnimationFrame(()=>{this.animate(scene, camera, renderer);});
 if(this.control !== undefined && this.clock !== undefined){
 this.control.update(this.clock.getDelta());//更新控制器
 }
  renderer.render(scene, camera);
  }

//创建纹理
 createTexture(){
 var load = new THREE.TextureLoader();

var texture_ground = load.load("img/texture/ground.jpg");
 texture_ground.wrapS = texture_ground.wrapT = THREE.RepeatWrapping;
 texture_ground.repeat.set(20, 20);//x y 平铺次数
texture_ground.anisotropy = 2;//纹理的清晰度(值为2的幕:1, 2, 4, 8, ... 512, 1024, 2048, ...)
var texture_wall = load.load("img/texture/wall.jpg");
 texture_wall.wrapS = texture_wall.wrapT = THREE.RepeatWrapping;
 texture_wall.repeat.set(2.2, 2.2);
 texture_wall.anisotropy = 1024;//贴图画质
texture_wall.minFilter = THREE.NearestFilter;//深度纹理贴图:
texture_wall.magFilter = THREE.NearestFilter;//深度纹理贴图:
var texture_gate = load.load("img/texture/gate.jpg");
 texture_gate.wrapS = texture_gate.wrapT = THREE.RepeatWrapping;
 texture_gate.repeat.set(0.03, 0.03);
 texture_gate.anisotropy = 1024;

return {ground:texture_ground, wall:texture_wall, gate:texture_gate};
  }

//创建地面 land
 createGround(group){
 var gro = group || this.group, w = 10000, h = 10000;
 //gro.add(new THREE.GridHelper(w, 100));//添加网格辅助线
var mesh = new THREE.Mesh(//创建 物体
new THREE.PlaneBufferGeometry(w, h), // geometry 几何体
new THREE.MeshLambertMaterial({map:this.textures.ground}) // material 材质
 );
 mesh.receiveShadow = true;//接受阴影
mesh.rotation.x = -(Math.PI*0.5);//旋转90度
mesh.matrixAutoUpdate = false;//不实时更新矩阵,提升性能
mesh.updateMatrix();//更新一次矩阵, 让其旋转90度
 gro.add(mesh);
 return mesh;
  }

//创建围墙
 createWall(object){
 var o = object || {};
 var gro = o.group || this.group;
 var w = 256, h = 256, d = 40;
 var mesh = new THREE.Mesh(
 new THREE.BoxBufferGeometry(w, h, d),
 new THREE.MeshLambertMaterial({map:this.textures.wall})
  );
 mesh.castShadow = true;//投射阴影
mesh.receiveShadow = true;//接收阴影
mesh.customDepthMaterial = new THREE.MeshDepthMaterial({depthPacking: THREE.RGBADepthPacking});//添加阴影
if(o.isSetY === true){mesh.position.y = h / 2 + 1;}//调整坐标 y
mesh.matrixAutoUpdate = false;//不实时更新矩阵,提升性能
mesh.updateMatrix();//更新一次矩阵
 gro.add(mesh);
 return mesh;
  }

//创建一块 小钢门...
 createGate(group){
 var gro = group || this.group, w = 256, h = 256;
 var shape = new THREE.Shape(), w2 = w/2, h2 = h/2;
 shape.moveTo(-w2, h2); shape.lineTo(w2, h2); shape.lineTo(w2, -h2);
 shape.lineTo(-w2, -h2); shape.lineTo(-w2, h2);
 var geometry = new THREE.ExtrudeBufferGeometry(shape, {
 depth:0,
 bevelThickness:2,
 bevelSize:3,
 bevelSegments:1
 });
 var material = new THREE.MeshLambertMaterial({map:this.textures.gate});
 var mesh = new THREE.Mesh(geometry, [material, material]);
 mesh.castShadow = true;
 mesh.receiveShadow = true;
 mesh.customDepthMaterial = new THREE.MeshDepthMaterial({depthPacking: THREE.RGBADepthPacking});
 mesh.position.set(300, h/2+1, 0);
 gro.add(mesh);
 return mesh;
  }

}
Func.js

 

展示:

three.js 版本号为 114 (需要 php 服务器环境才能运行, 如果此demo不能运行 或 有什么疑问 请联系我: 3247940050@qq.com)

完整代码: https://pan.baidu.com/s/1qVt50gecNB2wTr8doMMwmw

提取码: 53i3

 

版权声明
本文为[weihexin]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/weihexinCode/p/12446245.html