欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-09 19:58:58
1 "use strict" 2 3 //加载js文件 4 loadFile([ 5 "./js/lib/WebGL.js",//检查 是否支持webGL 插件 6 "./js/lib/three_114.min.js",//3d库 7 "js/func.js" 8 ], main); 9 10 / ......
  1 "use strict"
  2 
  3 //加载js文件
  4 loadfile([
  5     "./js/lib/webgl.js",//检查 是否支持webgl 插件
  6     "./js/lib/three_114.min.js",//3d库
  7     "js/func.js"
  8 ], main);
  9 
 10 //创建一个ajax请求, 前往index.php验证用户是否已登录
 11 //如果ajax返回的是false说明用户还没有登录成功,并前往 view.php, 
 12 //否则ajax返回用户信息对象
 13 function main(){
 14     new ajax({
 15         url:"./php/index.php",
 16         method:"get",
 17         success:(data)=>{
 18             let d = json.parse(data);
 19             if(d === false){location.href = "./login/view.php"; return;}
 20             showuserinfo(d.val, new view());//用户信息视图
 21             showthreeview();//场景3d视图
 22         }
 23     });
 24 }
 25 
 26 //退出
 27 function exit(){
 28     if(new func().isrun({id:"testid"}) !== true){console.log("你点得太快了,服务器跟不上"); return;}
 29     new ajax({
 30         url:"./php/exit.php",
 31         method:"get",
 32         success:(data)=>{main();}
 33     });
 34 }
 35 
 36 //创建html p元素
 37 function create(v, fel, content){
 38     let p = v.add(fel, "p");
 39     p.innerhtml = content || "";
 40     return p;
 41 }
 42 
 43 //创建登录成功后的主页内容
 44 function showuserinfo(user, v){//console.log(user);
 45     
 46     var lid = v.get("loginboxid");
 47     
 48     var elem_name = create(v, lid, "你好: " + user.username);
 49     elem_name.innerhtml += "<input type = 'button' id = 'exitid' value = '退 出' />";
 50     v.get('exitid').onclick = ()=>{exit();}//退出按钮
 51     
 52     create(v, lid, "我知道你的邮箱是: " + user.email);
 53     
 54     switch(user.like.length){
 55         case 1 : 
 56             create(v, lid, "我还知道你喜欢: " + user.like[0]); 
 57             break;
 58         case 2 : 
 59             create(v, lid, "我还知道你喜欢: " + user.like[0]); 
 60             create(v, lid, "还有: " + user.like[1]); 
 61             break;
 62         case 3 : 
 63             create(v, lid, "我还知道你喜欢: " + user.like[0]); 
 64             create(v, lid, "还有: " + user.like[1]); 
 65             create(v, lid, "还有: " + user.like[2]); 
 66             break;
 67         default : break;
 68     }
 69     lid.style = "visibility:visible;";
 70     //lid居中显示
 71     /* let x = math.round((v.client.w/2) - (lid.offsetwidth/2));
 72     let y = math.round((v.client.h/2) - (lid.offsetheight/2)) - 16;
 73     lid.style = "left:"+x+"px; top:"+y+"px; visibility:visible;"; */
 74 }
 75 
 76 
 77 //创建 主页 3d 视图
 78 /*
 79     键盘 w a s d移动
 80     鼠标 点击滑动旋转
 81 */
 82 function showthreeview(){
 83     
 84     var three = new three();
 85     
 86     //场景
 87     var scene = three.createscene();
 88     
 89     //相机
 90     var camera = three.createcamera(); //console.log(camera);
 91     
 92     //渲染器
 93     var renderer = three.createrenderer();
 94     
 95     //灯光
 96     var light = three.createlight(scene);
 97     
 98     //控制器
 99     three.createcontrol(camera, renderer);
100     
101     //动画循环
102     three.animate(scene, camera, renderer);
103     
104     //创建地面
105     three.createground();
106     
107     //创建院墙
108     three.createwall({issety:true});
109     
110     //创建铁门
111     three.creategate();
112     
113     console.log(three);
114     alert("键盘 w a s d移动, 鼠标 点击滑动旋转");
115 }
  1 "use strict"
  2 
  3 /**方法类
  4 
  5 */
  6 class func{
  7     
  8     constructor(){}
  9     
 10     //获取一个字符串的长度  包含中文
 11     getstrlen(str){
 12         let len = 0, i, c;
 13         for (i = 0; i < str.length; i++){
 14             c = str.charcodeat(i);
 15             if((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)){len++;}else{len+=2;}
 16         }
 17         return len;
 18     }
 19     
 20     //获取目标范围随机数(n保留浮点数数量)
 21     getran(min, max, n){
 22         return number((math.random() * (max - min) + min).tofixed(n || 0));//包含max
 23     }
 24     
 25     //获取2点距离
 26     getposlen(sdot, edot){
 27         return parseint(math.sqrt(math.pow(math.abs(sdot.x - edot.x), 2) + math.pow(math.abs(sdot.y - edot.y), 2)));
 28     }
 29     
 30     //检测是否是pc端
 31     ispc(){
 32         let useragent = navigator.useragent;
 33         let agents = ["android", "iphone", "symbianos", "windows phone", "ipad", "ipod"];
 34         let ispc = true, v;
 35         for(v = 0; v < agents.length; v++){
 36             if (useragent.indexof(agents[v]) > 0){ispc = false; break;}
 37         }
 38         return ispc;
 39     }
 40     
 41     //防止多次提交或执行(在规定时间段内只允许执行一次) 默认 3000ms
 42     isrun(object){
 43         //object = {id: string 必须, isexit, time}
 44         //isenit : boolean 可选 如果为 true 则删除对应 id 的对象
 45         //time : number 可选 默认间隔时间 3000 秒
 46         var v = object || {};
 47         if(this.list === undefined){func.prototype.list = {};}
 48         if(v.id === undefined || typeof(v.id) !== "string"){return "参数id错误";}
 49         if(v.isexit === true){delete(this.list[v.id]); return "删除对象: "+v.id;}
 50         var o = this.list[v.id];
 51         if(!o){this.list[v.id] = {time:v.time || 3000, nowtime:new date().gettime()}; return true;}
 52         var t = new date().gettime() - o.nowtime;
 53         if(t < o.time){return o.time - t;}
 54         o.nowtime = new date().gettime();
 55         return true;
 56     }
 57     
 58 }
 59 
 60 
 61 
 62 /** 创建ajax请求:
 63     obj = {
 64         url: string    必须, 请求路径
 65         method: string    可选, post 或 get请求, 默认post请求
 66         data: string    可选, 要发送的数据, 默认为""
 67         asy: boolean    可选, 是否异步执行, 默认为true
 68         success: function    可选, 成功回调
 69         error: function    可选, 失败回调
 70         run: function    可选, 请求中回调
 71     }
 72     
 73     xhr.readystate:
 74     0: 请求未初始化
 75     1: 服务器连接已建立
 76     2: 请求已接收
 77     3: 请求处理中
 78     4: 请求已完成,且响应已就绪
 79     xhr.status:
 80     200: "ok"
 81     404: 未找到页面
 82 */
 83 class ajax{
 84     
 85     constructor(obj){
 86         let o = obj || {}
 87         this.url = o.url || null;
 88         this.method = o.method || "post";
 89         this.data = o.data || "";
 90         this.asy = o.asy || true;
 91         this.callback_suc = o.success || function (){};
 92         this.callback_err = o.error || function (){};
 93         this.callback_run = o.run || function (){};
 94         this.request();
 95     }
 96     
 97     request(){
 98         if(!this.url){this.callback_err(); return;}
 99         let xhr = new xmlhttprequest();
100         xhr.onreadystatechange = (e)=>{
101             if(e.target.readystate === 4 && e.target.status === 200){
102                 this.callback_suc(e.target.responsetext);
103                 return;
104             }
105             this.callback_run(e);
106         }
107         xhr.onerror = (e)=>{
108             this.callback_err(e);
109         }
110         if(this.method == "get"){
111             xhr.open(this.method, this.url, this.asy);
112             xhr.send();
113             return;
114         }
115         xhr.open(this.method, this.url, this.asy);
116         xhr.setrequestheader("content-type", "application/x-www-form-urlencoded");
117         xhr.send(this.data);
118     }
119     
120 }
121 
122 
123 
124 /** 视图类
125 
126 */
127 class view{
128     
129     constructor(){
130         if(!this.client){view.prototype.client = this.getclient();}
131     }
132     
133     //创建html元素
134     add(fel, elemname, id, cls){
135         //创建一个元素
136         let el = document.createelement(elemname);
137         //设置el id 和 class
138         if(id){el.setattribute('id',id);}
139         if(cls){el.classname = cls;}
140         //把el添加到fel并显示(渲染el)
141         if(fel){fel.appendchild(el);}
142         return el;
143     }
144 
145     //删除html元素
146     remove(){
147         let k, arg = arguments, err = [];
148         for(k = 0; k < arg.length; k++){
149             if(this.isel(arg[k]) === false){err.push(arg[k]); continue;}
150             arg[k].parentnode.removechild(arg[k]);
151         }
152         if(err.length > 0){return {err:'这里有一些删除失败的元素', arr:err};}
153         return true;
154     }
155 
156     //id获取html元素
157     get(id){
158         return document.getelementbyid(id);
159     }
160     
161     //获取可视宽高
162     getclient(){
163         return {
164             w:document.documentelement.clientwidth || document.body.clientwidth, 
165             h:document.documentelement.clientheight || document.body.clientheight
166         };
167     }
168     
169     //通过parentnode检查元素是否存在于页面中
170     isel(el){
171         if(typeof(el) !== 'object'){return false;}
172         //被删除之后的html元素object的 parentnode等于null
173         if(!el.parentnode){return false;}
174         return true;
175     }
176     
177     //元素绑定事件
178     addevent(target, ev, callback){
179         target.addeventlistener(ev, function(e){if(callback){callback(e);}}, false);
180     }
181 
182 }
183 
184 
185 
186 /** 3d库
187     three.js --- version number 114
188     create scene
189 */
190 class three{
191     
192     constructor(){
193         if (webgl.iswebglavailable() === false){
194             alert("你不支持webgl");
195             return;
196         }
197         this.view = new view();
198         three.cache.enabled = true;//加载器启用缓存
199         this.clock = new three.clock();//
200         this.group = new three.group();//创建一个 分组
201         this.textures = this.createtexture();//存放 纹理 的对象
202     }
203 
204     //创建 场景
205     createscene(){
206         var scene = new three.scene();
207         //scene.fog = new three.fog(0xcce0ff, 800, 1000);//线性雾
208         scene.background = new three.cubetextureloader()
209         .setpath('img/cube/skyboxsun25deg/')
210         .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );
211         if(this.group){scene.add(this.group);}
212         return scene;
213     }
214     
215     //创建 相机
216     createcamera(){
217         var camera = new three.perspectivecamera(75, this.view.client.w/this.view.client.h, 1, 5000);
218         camera.position.set(0, 150, 300);//相机起始位置
219         return camera;
220     }
221     
222     //创建 渲染器
223     createrenderer(){
224         var renderer = new three.webglrenderer({
225             antialias : true,//抗割齿
226             powerpreference:"high-performance"//选择高性能gpu渲染
227         });
228         renderer.setsize(this.view.client.w, this.view.client.h);//设置渲染大小
229         renderer.setpixelratio(window.devicepixelratio);//渲染矫正
230         renderer.gammafactor = 2.2;//着色校正
231         renderer.physicallycorrectlights = true;//使其精确照明
232         renderer.shadowmap.enabled = true;//渲染阴影
233         //renderer.autoclear = true;//每帧自动清理缓存
234         if(!renderer.extensions.get('webgl_depth_texture')){console.log("深度纹理扩展获取失败:webgl_depth_texture");}
235         document.body.appendchild(renderer.domelement);
236         renderer.domelement.style.zindex = "0";
237         renderer.domelement.style.position = "absolute";
238         renderer.domelement.style.top = "0px";
239         renderer.domelement.style.left = "0px";
240         return renderer;
241     }
242     
243     //创建 灯光
244     createlight(scene){
245         scene.add(new three.ambientlight(0x696969));//环境光(无处不在的光,太阳光)
246         var l_d = 1000, light = new three.directionallight(0xf0f8ff, 1);//平行光(产生阴影的光)
247         light.position.set(-3000, 3000, -3000);
248         light.position.multiplyscalar(1);
249         //阴影
250         light.castshadow = true;
251         light.shadow.mapsize.width = 1024;
252         light.shadow.mapsize.height = 1024;
253         light.shadow.camera.left = -l_d;
254         light.shadow.camera.right = l_d;
255         light.shadow.camera.top = l_d;
256         light.shadow.camera.bottom = -l_d;
257         light.shadow.camera.near = 1;
258         light.shadow.camera.far = 6000;
259         scene.add(light);
260         return light;
261     }
262     
263     //创建 控制器
264     createcontrol(camera, renderer){
265         var create = ()=>{
266             let control = new three.orbitcontrols(camera, renderer.domelement);
267             control.target = new three.vector3(0, 100, 0);//相机焦点
268             //control.minpolarangle = math.pi * 0.3;//向上最大角度
269             //control.maxpolarangle = math.pi * 0.4;//向下最大角度
270             control.mindistance = 1;//最小距离
271             control.maxdistance = 1000;//最大距离
272             control.autorotatespeed = 10;//自动旋转速度
273             control.panspeed = 100;//鼠标旋转速度
274             control.enablezoom = true;//是否启用缩放
275             control.enablekeys = true;//是否启用键盘
276             control.keypanspeed = 100;//按键速度
277             control.keys.left = 65;//key a左
278             control.keys.up = 87;//key w前
279             control.keys.right = 68;//key d右
280             control.keys.bottom = 83;//key s后
281             this.control = control;
282         }
283         loadfile("./js/lib/orbitcontrols.js", create);//加载 控制器 插件
284     }
285     
286     //创建 动画循环
287     animate(scene, camera, renderer){
288         requestanimationframe(()=>{this.animate(scene, camera, renderer);});
289         if(this.control !== undefined && this.clock !== undefined){
290             this.control.update(this.clock.getdelta());//更新控制器
291         }
292         renderer.render(scene, camera);
293     }
294     
295     //创建纹理
296     createtexture(){
297         var load = new three.textureloader();
298         
299         var texture_ground = load.load("img/texture/ground.jpg");
300         texture_ground.wraps = texture_ground.wrapt = three.repeatwrapping;
301         texture_ground.repeat.set(20, 20);//x y 平铺次数
302         texture_ground.anisotropy = 2;//纹理的清晰度(值为2的幕:1, 2, 4, 8, ... 512, 1024, 2048, ...)
303         
304         var texture_wall = load.load("img/texture/wall.jpg");
305         texture_wall.wraps = texture_wall.wrapt = three.repeatwrapping;
306         texture_wall.repeat.set(2.2, 2.2);
307         texture_wall.anisotropy = 1024;//贴图画质
308         texture_wall.minfilter = three.nearestfilter;//深度纹理贴图:
309         texture_wall.magfilter = three.nearestfilter;//深度纹理贴图:
310 
311         var texture_gate = load.load("img/texture/gate.jpg");
312         texture_gate.wraps = texture_gate.wrapt = three.repeatwrapping;
313         texture_gate.repeat.set(0.03, 0.03);
314         texture_gate.anisotropy = 1024;
315         
316         return {ground:texture_ground, wall:texture_wall, gate:texture_gate};
317     }
318     
319     //创建地面 land
320     createground(group){
321         var gro = group || this.group, w = 10000, h = 10000;
322         //gro.add(new three.gridhelper(w, 100));//添加网格辅助线
323         var mesh = new three.mesh(//创建 物体
324             new three.planebuffergeometry(w, h), // geometry 几何体
325             new three.meshlambertmaterial({map:this.textures.ground}) // material 材质
326         );
327         mesh.receiveshadow = true;//接受阴影
328         mesh.rotation.x = -(math.pi*0.5);//旋转90度
329         mesh.matrixautoupdate = false;//不实时更新矩阵,提升性能
330         mesh.updatematrix();//更新一次矩阵, 让其旋转90度
331         gro.add(mesh);
332         return mesh;
333     }
334     
335     //创建围墙
336     createwall(object){
337         var o = object || {};
338         var gro = o.group || this.group;
339         var w = 256, h = 256, d = 40;
340         var mesh = new three.mesh(
341             new three.boxbuffergeometry(w, h, d),
342             new three.meshlambertmaterial({map:this.textures.wall})
343         );
344         mesh.castshadow = true;//投射阴影
345         mesh.receiveshadow = true;//接收阴影
346         mesh.customdepthmaterial = new three.meshdepthmaterial({depthpacking: three.rgbadepthpacking});//添加阴影
347         if(o.issety === true){mesh.position.y = h / 2 + 1;}//调整坐标 y
348         mesh.matrixautoupdate = false;//不实时更新矩阵,提升性能
349         mesh.updatematrix();//更新一次矩阵
350         gro.add(mesh);
351         return mesh;
352     }
353     
354     //创建一块 小钢门...
355     creategate(group){
356         var gro = group || this.group, w = 256, h = 256;
357         var shape = new three.shape(), w2 = w/2, h2 = h/2;
358         shape.moveto(-w2, h2); shape.lineto(w2, h2); shape.lineto(w2, -h2);
359         shape.lineto(-w2, -h2); shape.lineto(-w2, h2);
360         var geometry = new three.extrudebuffergeometry(shape, {
361             depth:0,
362             bevelthickness:2,
363             bevelsize:3,
364             bevelsegments:1
365         });
366         var material = new three.meshlambertmaterial({map:this.textures.gate});
367         var mesh = new three.mesh(geometry, [material, material]);
368         mesh.castshadow = true;
369         mesh.receiveshadow = true;
370         mesh.customdepthmaterial = new three.meshdepthmaterial({depthpacking: three.rgbadepthpacking});
371         mesh.position.set(300, h/2+1, 0);
372         gro.add(mesh);
373         return mesh;
374     }
375     
376 }

 

展示:

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

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

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

提取码: 53i3

 

上一篇: Nginx学习笔记

下一篇: jQuery的语法