zoukankan      html  css  js  c++  java
  • javascript 基于原生登录注册系统搭建一个3d网页 ( three.js r114 初探 一)

      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 }
    Func.js

    展示:

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

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

    提取码: 53i3

  • 相关阅读:
    linux shell if 参数
    SHELL输出颜色和闪烁控制
    http层负载均衡之 haproxy实践篇
    linux系统查找大文件脚本
    Nginx的try_files指令和命名location使用实例
    Java SpringMVC实现PC端网页微信扫码支付完整版
    IPTABLES基本例子
    MAC上反编译android apk---apktool, dex2jar, jd-jui安装使用(含手动签名)
    spring mvc 集成freemarker模板
    Python—正则表达式
  • 原文地址:https://www.cnblogs.com/weihexinCode/p/12446245.html
Copyright © 2011-2022 走看看