|  |  | 
 |  |  | <!doctype html> | 
 |  |  | <!DOCTYPE html> | 
 |  |  | <html> | 
 |  |  | <head> | 
 |  |  |     <meta charset="utf-8"> | 
 |  |  |     <title>HTML5 Canvas矩阵粒子波浪背景动画特效</title> | 
 |  |  |    <head> | 
 |  |  |       <meta charset="utf-8"> | 
 |  |  |       <title>wcs │ login of wcs</title> | 
 |  |  |       <style> | 
 |  |  |          * { | 
 |  |  |             padding: 0; | 
 |  |  |             margin: 0; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |     <style> | 
 |  |  |         html,body { | 
 |  |  |             height:100%; | 
 |  |  |         } | 
 |  |  |         body { | 
 |  |  |             margin:0; | 
 |  |  |             background:#000; | 
 |  |  |         } | 
 |  |  |         canvas { | 
 |  |  |             display:block; | 
 |  |  |         } | 
 |  |  |         .waves { | 
 |  |  |             position:absolute; | 
 |  |  |             left:0; | 
 |  |  |             top:0; | 
 |  |  |             right:0; | 
 |  |  |             bottom:0; | 
 |  |  |         } | 
 |  |  |          .container { | 
 |  |  |             display: flex; | 
 |  |  |             height: 100vh; | 
 |  |  |             width: 100%; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .form_main { | 
 |  |  |             width: 300px; | 
 |  |  |             display: flex; | 
 |  |  |             flex-direction: column; | 
 |  |  |             align-items: center; | 
 |  |  |             justify-content: center; | 
 |  |  |             background-color: rgba(255, 255, 255, 0.6); | 
 |  |  |             padding: 50px 30px 50px 30px; | 
 |  |  |             border-radius: 30px; | 
 |  |  |             box-shadow: 0px 0px 40px rgba(0, 0, 0, 0.062); | 
 |  |  |         } | 
 |  |  |          .left-box { | 
 |  |  |             height: 100%; | 
 |  |  |             width: 70%; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .heading { | 
 |  |  |             font-size: 2.5em; | 
 |  |  |             color: #2e2e2e; | 
 |  |  |             font-weight: 700; | 
 |  |  |             margin: 15px 0 0px 0; | 
 |  |  |         } | 
 |  |  |          .login-video { | 
 |  |  |             height: 100%; | 
 |  |  |             overflow: hidden; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .inputContainer { | 
 |  |  |             width: 100%; | 
 |  |  |             position: relative; | 
 |  |  |             display: flex; | 
 |  |  |             align-items: center; | 
 |  |  |             justify-content: center; | 
 |  |  |         } | 
 |  |  |          .form-main { | 
 |  |  |             width: 300px; | 
 |  |  |             display: flex; | 
 |  |  |             flex-direction: column; | 
 |  |  |             align-items: center; | 
 |  |  |             justify-content: center; | 
 |  |  |             background-color: rgba(255, 255, 255, 0.6); | 
 |  |  |             padding: 50px 30px 50px 30px; | 
 |  |  |             border-radius: 20px; | 
 |  |  |             box-shadow: 0px 0px 40px rgba(0, 0, 0, 0.062); | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .inputIcon { | 
 |  |  |             position: absolute; | 
 |  |  |             left: 10px; | 
 |  |  |         } | 
 |  |  |          .heading { | 
 |  |  |             font-size: 2.5em; | 
 |  |  |             color: #2e2e2e; | 
 |  |  |             font-weight: 700; | 
 |  |  |             margin: 15px 0 0px 0; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .inputField { | 
 |  |  |             width: 100%; | 
 |  |  |             height: 40px; | 
 |  |  |             background-color: transparent; | 
 |  |  |             border: none; | 
 |  |  |             border-bottom: 2px solid rgb(173, 173, 173); | 
 |  |  |             border-radius: 30px; | 
 |  |  |             margin: 10px 0; | 
 |  |  |             color: black; | 
 |  |  |             font-size: .8em; | 
 |  |  |             font-weight: 500; | 
 |  |  |             box-sizing: border-box; | 
 |  |  |             padding-left: 30px; | 
 |  |  |         } | 
 |  |  |          .inputContainer { | 
 |  |  |             width: 100%; | 
 |  |  |             position: relative; | 
 |  |  |             display: flex; | 
 |  |  |             align-items: center; | 
 |  |  |             justify-content: center; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .inputField:focus { | 
 |  |  |             outline: none; | 
 |  |  |             border-bottom: 2px solid rgb(199, 114, 255); | 
 |  |  |         } | 
 |  |  |          .inputIcon { | 
 |  |  |             position: absolute; | 
 |  |  |             left: 10px; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .inputField::placeholder { | 
 |  |  |             color: rgb(80, 80, 80); | 
 |  |  |             font-size: 1em; | 
 |  |  |             font-weight: 500; | 
 |  |  |         } | 
 |  |  |          .inputField { | 
 |  |  |             width: 100%; | 
 |  |  |             height: 40px; | 
 |  |  |             background-color: transparent; | 
 |  |  |             border: none; | 
 |  |  |             border-bottom: 2px solid rgb(173, 173, 173); | 
 |  |  |             border-radius: 30px; | 
 |  |  |             margin: 10px 0; | 
 |  |  |             color: black; | 
 |  |  |             font-size: .8em; | 
 |  |  |             font-weight: 500; | 
 |  |  |             box-sizing: border-box; | 
 |  |  |             padding-left: 30px; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         #login-button { | 
 |  |  |             position: relative; | 
 |  |  |             width: 100%; | 
 |  |  |             border: 2px solid #8000ff; | 
 |  |  |             background-color: #8000ff; | 
 |  |  |             height: 40px; | 
 |  |  |             color: white; | 
 |  |  |             font-size: .8em; | 
 |  |  |             font-weight: 500; | 
 |  |  |             letter-spacing: 1px; | 
 |  |  |             border-radius: 30px; | 
 |  |  |             margin: 10px; | 
 |  |  |             cursor: pointer; | 
 |  |  |             overflow: hidden; | 
 |  |  |         } | 
 |  |  |          .inputField:focus { | 
 |  |  |             outline: none; | 
 |  |  |             border-bottom: 2px solid rgb(199, 114, 255); | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         #login-button::after { | 
 |  |  |             content: ""; | 
 |  |  |             position: absolute; | 
 |  |  |             background-color: rgba(255, 255, 255, 0.253); | 
 |  |  |             height: 100%; | 
 |  |  |             width: 150px; | 
 |  |  |             top: 0; | 
 |  |  |             left: -200px; | 
 |  |  |             border-bottom-right-radius: 100px; | 
 |  |  |             border-top-left-radius: 100px; | 
 |  |  |             filter: blur(10px); | 
 |  |  |             transition-duration: .5s; | 
 |  |  |         } | 
 |  |  |          .inputField::placeholder { | 
 |  |  |             color: rgb(80, 80, 80); | 
 |  |  |             font-size: 1em; | 
 |  |  |             font-weight: 500; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .login-box { | 
 |  |  |             height: 100%; | 
 |  |  |             display: flex; | 
 |  |  |             justify-content: center; | 
 |  |  |             align-items: center; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         #login-button:hover::after { | 
 |  |  |             transform: translateX(600px); | 
 |  |  |             transition-duration: .5s; | 
 |  |  |         } | 
 |  |  |          .login-button { | 
 |  |  |             position: relative; | 
 |  |  |             width: 100%; | 
 |  |  |             border: 2px solid #8000ff; | 
 |  |  |             background-color: #8000ff; | 
 |  |  |             height: 40px; | 
 |  |  |             color: white; | 
 |  |  |             font-size: .8em; | 
 |  |  |             font-weight: 500; | 
 |  |  |             letter-spacing: 1px; | 
 |  |  |             border-radius: 30px; | 
 |  |  |             margin: 10px; | 
 |  |  |             cursor: pointer; | 
 |  |  |             overflow: hidden; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .signupContainer { | 
 |  |  |             margin: 0; | 
 |  |  |             display: flex; | 
 |  |  |             flex-direction: column; | 
 |  |  |             align-items: center; | 
 |  |  |             justify-content: center; | 
 |  |  |             gap: 20px; | 
 |  |  |         } | 
 |  |  |          .login-button::after { | 
 |  |  |             content: ""; | 
 |  |  |             position: absolute; | 
 |  |  |             background-color: rgba(255, 255, 255, 0.253); | 
 |  |  |             height: 100%; | 
 |  |  |             width: 150px; | 
 |  |  |             top: 0; | 
 |  |  |             left: -200px; | 
 |  |  |             border-bottom-right-radius: 100px; | 
 |  |  |             border-top-left-radius: 100px; | 
 |  |  |             filter: blur(10px); | 
 |  |  |             transition-duration: .5s; | 
 |  |  |          } | 
 |  |  |  | 
 |  |  |         .signupContainer p { | 
 |  |  |             font-size: .9em; | 
 |  |  |             font-weight: 500; | 
 |  |  |             color: black; | 
 |  |  |         } | 
 |  |  |          .login-button:hover::after { | 
 |  |  |             transform: translateX(600px); | 
 |  |  |             transition-duration: .5s; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .right-box { | 
 |  |  |             height: 100%; | 
 |  |  |             width: 30%; | 
 |  |  |             background: #f6f6f6; | 
 |  |  |             position: relative; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .login-copyright { | 
 |  |  |             position: absolute; | 
 |  |  |             bottom: 20px; | 
 |  |  |             right: 20px; | 
 |  |  |             font-size: 14px; | 
 |  |  |             width: 100%; | 
 |  |  |             display: flex; | 
 |  |  |             justify-content: center; | 
 |  |  |             align-items: center; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .copyright-text { | 
 |  |  |             margin-right: 20px; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .copyright-img { | 
 |  |  |             width: 40px; | 
 |  |  |             height: 40px; | 
 |  |  |             position: relative; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .copyright-img > img { | 
 |  |  |             width: 100%; | 
 |  |  |             height: 100%; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .copyright-img-large { | 
 |  |  |             width: 140px; | 
 |  |  |             height: 140px; | 
 |  |  |             position: absolute; | 
 |  |  |             top: -140px; | 
 |  |  |             left: -50px; | 
 |  |  |             display: none; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          .copyright-img-large > img { | 
 |  |  |             width: 100%; | 
 |  |  |             height: 100%; | 
 |  |  |          } | 
 |  |  |       </style> | 
 |  |  |    </head> | 
 |  |  |    <body> | 
 |  |  |       <div class="container"> | 
 |  |  |          <div class="left-box"> | 
 |  |  |             <div class="login-video"> | 
 |  |  |                <video src="../static/wcs/images/banner.mp4" height="100%" loop autoplay muted="false" | 
 |  |  |                   controlslist="nodownload" disablepictureinpicture></video> | 
 |  |  |             </div> | 
 |  |  |          </div> | 
 |  |  |  | 
 |  |  |         .signupContainer a { | 
 |  |  |             font-size: .7em; | 
 |  |  |             font-weight: 500; | 
 |  |  |             background-color: #2e2e2e; | 
 |  |  |             color: white; | 
 |  |  |             text-decoration: none; | 
 |  |  |             padding: 8px 15px; | 
 |  |  |             border-radius: 20px; | 
 |  |  |         } | 
 |  |  |          <div class="right-box"> | 
 |  |  |             <div class="login-box"> | 
 |  |  |                <div class="form-main"> | 
 |  |  |                   <p style="text-align: center;"><img class="loginLogoUrl" src="../static/wcs/images/logo.png" alt="" style="width: 80%"> | 
 |  |  |                   </p> | 
 |  |  |                   <p style="margin-top: -10px;"><span class="login100-form-title p-t-20 p-b-45" | 
 |  |  |                         style="color: #868686;font-size: 24px">WCS</span></p> | 
 |  |  |                   <div class="inputContainer"> | 
 |  |  |                      <svg viewBox="0 0 16 16" fill="#2e2e2e" height="16" width="16" | 
 |  |  |                         xmlns="http://www.w3.org/2000/svg" class="inputIcon"> | 
 |  |  |                         <path | 
 |  |  |                            d="M13.106 7.222c0-2.967-2.249-5.032-5.482-5.032-3.35 0-5.646 2.318-5.646 5.702 0 3.493 2.235 5.708 5.762 5.708.862 0 1.689-.123 2.304-.335v-.862c-.43.199-1.354.328-2.29.328-2.926 0-4.813-1.88-4.813-4.798 0-2.844 1.921-4.881 4.594-4.881 2.735 0 4.608 1.688 4.608 4.156 0 1.682-.554 2.769-1.416 2.769-.492 0-.772-.28-.772-.76V5.206H8.923v.834h-.11c-.266-.595-.881-.964-1.6-.964-1.4 0-2.378 1.162-2.378 2.823 0 1.737.957 2.906 2.379 2.906.8 0 1.415-.39 1.709-1.087h.11c.081.67.703 1.148 1.503 1.148 1.572 0 2.57-1.415 2.57-3.643zm-7.177.704c0-1.197.54-1.907 1.456-1.907.93 0 1.524.738 1.524 1.907S8.308 9.84 7.371 9.84c-.895 0-1.442-.725-1.442-1.914z"> | 
 |  |  |                         </path> | 
 |  |  |                      </svg> | 
 |  |  |                      <input placeholder="请输入用户名" id="username" name="username" class="inputField" type="text"> | 
 |  |  |                   </div> | 
 |  |  | 					 | 
 |  |  |                   <div class="inputContainer"> | 
 |  |  |                      <svg viewBox="0 0 16 16" fill="#2e2e2e" height="16" width="16" | 
 |  |  |                         xmlns="http://www.w3.org/2000/svg" class="inputIcon"> | 
 |  |  |                         <path | 
 |  |  |                            d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"> | 
 |  |  |                         </path> | 
 |  |  |                      </svg> | 
 |  |  |                      <input placeholder="请输入密码" id="password" name="pass" class="inputField" type="password"> | 
 |  |  |                   </div> | 
 |  |  | 					 | 
 |  |  |                   <input type="button" id="login-button" class="login-button" value="登录"> | 
 |  |  |  | 
 |  |  |     </style> | 
 |  |  | </head> | 
 |  |  | <body> | 
 |  |  |                   <div style="display: none;margin-top: 5px;width: 100%;" id="updateLicense"> | 
 |  |  |                      <form enctype="multipart/form-data" style="display: none;"> | 
 |  |  |                         <input id="license" type="file" name="file" > | 
 |  |  |                      </form> | 
 |  |  |                      <input type="button" id="submitLicense" class="login-button" style="margin: 0;" value="更新许可证"> | 
 |  |  |                   </div> | 
 |  |  |                </div> | 
 |  |  |             </div> | 
 |  |  | 				 | 
 |  |  |             <div class="login-copyright"> | 
 |  |  | <!--               <div class="copyright-text">Copyright ©2023 wcs</div>--> | 
 |  |  |                <div id="copyright-img1" class="copyright-img"> | 
 |  |  |                   <img class="copyright-img-url" src="../static/wcs/images/weixin_qrcode.jpg" /> | 
 |  |  |                   <div id="copyright-img-large1" class="copyright-img-large"><img class="copyright-img-url" src="../static/wcs/images/weixin_qrcode.jpg" /></div> | 
 |  |  |                </div> | 
 |  |  |             </div> | 
 |  |  |          </div> | 
 |  |  |       </div> | 
 |  |  | 		 | 
 |  |  |       <script type="text/javascript" src="../static/wms/js/jquery/jquery-3.3.1.min.js"></script> | 
 |  |  |       <script type="text/javascript" src="../static/wms/js/tools/md5.js"></script> | 
 |  |  |       <script type="text/javascript" src="../static/wms/layer/layer.js"></script> | 
 |  |  |       <script type="text/javascript" src="../static/wms/js/common.js"></script> | 
 |  |  |       <script> | 
 |  |  |           // remember pwd | 
 |  |  |           $(function () { | 
 |  |  |             $.ajax({ | 
 |  |  |                url: baseUrl+"/loginInformation", | 
 |  |  |                data: {}, | 
 |  |  |                method: 'GET', | 
 |  |  |                success: function (res) { | 
 |  |  |                   var data = res.data | 
 |  |  |                   $(".copyright-text").text(data.loginCopyrightText); | 
 |  |  |                   $(".copyright-img-url").attr("src", data.loginCopyrightImg1); | 
 |  |  |                   $(".loginLogoUrl").attr("src", data.loginLogo); | 
 |  |  |  | 
 |  |  | <div class="waves"> | 
 |  |  |     <div style="position: absolute;left: calc(50% - 200px);top: 25%;"> | 
 |  |  |         <div class="form_main"> | 
 |  |  |             <p style="text-align: center;"><img src="../static/image/logo.png" alt="" style="width: 80%"></p> | 
 |  |  |             <p style="margin-top: -15px;"><span class="login100-form-title p-t-20 p-b-45" style="color: #868686;font-size: 24px">WCS</span></p> | 
 |  |  |             <div class="inputContainer"> | 
 |  |  |                 <svg viewBox="0 0 16 16" fill="#2e2e2e" height="16" width="16" xmlns="http://www.w3.org/2000/svg" class="inputIcon"> | 
 |  |  |                     <path d="M13.106 7.222c0-2.967-2.249-5.032-5.482-5.032-3.35 0-5.646 2.318-5.646 5.702 0 3.493 2.235 5.708 5.762 5.708.862 0 1.689-.123 2.304-.335v-.862c-.43.199-1.354.328-2.29.328-2.926 0-4.813-1.88-4.813-4.798 0-2.844 1.921-4.881 4.594-4.881 2.735 0 4.608 1.688 4.608 4.156 0 1.682-.554 2.769-1.416 2.769-.492 0-.772-.28-.772-.76V5.206H8.923v.834h-.11c-.266-.595-.881-.964-1.6-.964-1.4 0-2.378 1.162-2.378 2.823 0 1.737.957 2.906 2.379 2.906.8 0 1.415-.39 1.709-1.087h.11c.081.67.703 1.148 1.503 1.148 1.572 0 2.57-1.415 2.57-3.643zm-7.177.704c0-1.197.54-1.907 1.456-1.907.93 0 1.524.738 1.524 1.907S8.308 9.84 7.371 9.84c-.895 0-1.442-.725-1.442-1.914z"></path> | 
 |  |  |                 </svg> | 
 |  |  |                 <input placeholder="请输入用户名" id="username" name="username" class="inputField" type="text"> | 
 |  |  |             </div> | 
 |  |  |                   if (data.loginCopyrightImg1 == "") { | 
 |  |  |                      $(".copyright-img-url").hide() | 
 |  |  |                   } | 
 |  |  |                } | 
 |  |  |             }); | 
 |  |  |  | 
 |  |  |             <div class="inputContainer"> | 
 |  |  |                 <svg viewBox="0 0 16 16" fill="#2e2e2e" height="16" width="16" xmlns="http://www.w3.org/2000/svg" class="inputIcon"> | 
 |  |  |                     <path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"></path> | 
 |  |  |                 </svg> | 
 |  |  |                 <input placeholder="请输入密码" id="password" name="pass" class="inputField" type="password"> | 
 |  |  |             </div> | 
 |  |  |               var oldUserName = localStorage.getItem('oldUserName'); | 
 |  |  |               var oldPass = localStorage.getItem('oldPass'); | 
 |  |  |               if(oldUserName){ | 
 |  |  |                   $('#username').val(oldUserName); | 
 |  |  |               } | 
 |  |  |               if(oldPass){ | 
 |  |  |                   $('#password').val(oldPass); | 
 |  |  |               } | 
 |  |  |           }) | 
 |  |  | 		 | 
 |  |  |           window.onload = function(){document.getElementById("username").focus();} | 
 |  |  | 		 | 
 |  |  |           $(document).on('click','#login-button', function () { | 
 |  |  |               let username = $("#username").val(); | 
 |  |  |               if (username === "") { | 
 |  |  |                   layer.tips('请输入登录账号', '#username', {tips: [4, '#ff0000']}); | 
 |  |  |                   return; | 
 |  |  |               } | 
 |  |  |               let password = $("#password").val(); | 
 |  |  |               if (password === "") { | 
 |  |  |                   layer.tips('请输入密码', '#password', {tips: [4, '#ff0000']}); | 
 |  |  |                   return; | 
 |  |  |               } | 
 |  |  |               $.ajax({ | 
 |  |  |                   url: baseUrl+"/login.action", | 
 |  |  |                   data: { | 
 |  |  |                       mobile: username, | 
 |  |  |                       password: hex_md5(password) | 
 |  |  |                   }, | 
 |  |  |                   method: 'POST', | 
 |  |  |                   success: function (res) { | 
 |  |  |                       if (res.code === 200){ | 
 |  |  |                           localStorage.setItem("token", res.data.token); | 
 |  |  |                           localStorage.setItem("username", res.data.username); | 
 |  |  |                           window.location.href = "index.html"; | 
 |  |  |                       } else if (res.code === 10001) { | 
 |  |  |                           layer.tips(res.msg, '#username', {tips: [4, '#ff0000']}); | 
 |  |  |                       } else if (res.code === 10002) { | 
 |  |  |                           layer.tips(res.msg, '#username', {tips: [4, '#ff0000']}); | 
 |  |  |                       } else if (res.code === 10003) { | 
 |  |  |                           layer.tips(res.msg, '#password', {tips: [4, '#ff0000']}); | 
 |  |  |                       } else if (res.code === 20001) { | 
 |  |  |                      layer.tips(res.msg, '#login-button', {tips: [3, '#ff0000']}); | 
 |  |  |                      $("#updateLicense").show() | 
 |  |  |                   } else { | 
 |  |  |                      layer.tips(res.msg, '#login-button', {tips: [3, '#ff0000']}); | 
 |  |  |                   } | 
 |  |  |                   } | 
 |  |  |               }); | 
 |  |  |           }); | 
 |  |  | 		 | 
 |  |  |           $(document).keydown(function () { | 
 |  |  |               if (event.keyCode === 13) { | 
 |  |  |                   $("#login-button").click(); | 
 |  |  |               } | 
 |  |  |           }); | 
 |  |  | 			 | 
 |  |  |          $("#copyright-img1").on("mouseover", () => { | 
 |  |  |             $("#copyright-img-large1").show() | 
 |  |  |          }) | 
 |  |  | 			 | 
 |  |  |          $("#copyright-img1").on("mouseout", () => { | 
 |  |  |             $("#copyright-img-large1").hide() | 
 |  |  |          }) | 
 |  |  |  | 
 |  |  |             <button id="login-button">登录</button> | 
 |  |  |         </div> | 
 |  |  |          //更新许可证 | 
 |  |  |          $("#submitLicense").on("click",() => { | 
 |  |  |             $("#license").click() | 
 |  |  |          }) | 
 |  |  |  | 
 |  |  |     </div> | 
 |  |  | </div> | 
 |  |  |  | 
 |  |  | <script> | 
 |  |  |     class ShaderProgram { | 
 |  |  |  | 
 |  |  |         constructor( holder, options = {} ) { | 
 |  |  |  | 
 |  |  |             options = Object.assign( { | 
 |  |  |                 antialias: false, | 
 |  |  |                 depthTest: false, | 
 |  |  |                 mousemove: false, | 
 |  |  |                 autosize: true, | 
 |  |  |                 side: 'front', | 
 |  |  |                 vertex: ` | 
 |  |  |         precision highp float; | 
 |  |  |  | 
 |  |  |         attribute vec4 a_position; | 
 |  |  |         attribute vec4 a_color; | 
 |  |  |  | 
 |  |  |         uniform float u_time; | 
 |  |  |         uniform vec2 u_resolution; | 
 |  |  |         uniform vec2 u_mousemove; | 
 |  |  |         uniform mat4 u_projection; | 
 |  |  |  | 
 |  |  |         varying vec4 v_color; | 
 |  |  |  | 
 |  |  |         void main() { | 
 |  |  |  | 
 |  |  |           gl_Position = u_projection * a_position; | 
 |  |  |           gl_PointSize = (10.0 / gl_Position.w) * 100.0; | 
 |  |  |  | 
 |  |  |           v_color = a_color; | 
 |  |  |  | 
 |  |  |         }`, | 
 |  |  |                 fragment: ` | 
 |  |  |         precision highp float; | 
 |  |  |  | 
 |  |  |         uniform sampler2D u_texture; | 
 |  |  |         uniform int u_hasTexture; | 
 |  |  |  | 
 |  |  |         varying vec4 v_color; | 
 |  |  |  | 
 |  |  |         void main() { | 
 |  |  |  | 
 |  |  |           if ( u_hasTexture == 1 ) { | 
 |  |  |  | 
 |  |  |             gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord); | 
 |  |  |  | 
 |  |  |           } else { | 
 |  |  |  | 
 |  |  |             gl_FragColor = v_color; | 
 |  |  |  | 
 |  |  |           } | 
 |  |  |  | 
 |  |  |         }`, | 
 |  |  |                 uniforms: {}, | 
 |  |  |                 buffers: {}, | 
 |  |  |                 camera: {}, | 
 |  |  |                 texture: null, | 
 |  |  |                 onUpdate: ( () => {} ), | 
 |  |  |                 onResize: ( () => {} ), | 
 |  |  |             }, options ) | 
 |  |  |  | 
 |  |  |             const uniforms = Object.assign( { | 
 |  |  |                 time: { type: 'float', value: 0 }, | 
 |  |  |                 hasTexture: { type: 'int', value: 0 }, | 
 |  |  |                 resolution: { type: 'vec2', value: [ 0, 0 ] }, | 
 |  |  |                 mousemove: { type: 'vec2', value: [ 0, 0 ] }, | 
 |  |  |                 projection: { type: 'mat4', value: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] }, | 
 |  |  |             }, options.uniforms ) | 
 |  |  |  | 
 |  |  |             const buffers = Object.assign( { | 
 |  |  |                 position: { size: 3, data: [] }, | 
 |  |  |                 color: { size: 4, data: [] }, | 
 |  |  |             }, options.buffers ) | 
 |  |  |  | 
 |  |  |             const camera = Object.assign( { | 
 |  |  |                 fov: 60, | 
 |  |  |                 near: 1, | 
 |  |  |                 far: 10000, | 
 |  |  |                 aspect: 1, | 
 |  |  |                 z: 100, | 
 |  |  |                 perspective: true, | 
 |  |  |             }, options.camera ) | 
 |  |  |  | 
 |  |  |             const canvas = document.createElement( 'canvas' ) | 
 |  |  |             const gl = canvas.getContext( 'webgl', { antialias: options.antialias } ) | 
 |  |  |  | 
 |  |  |             if ( ! gl ) return false | 
 |  |  |  | 
 |  |  |             this.count = 0 | 
 |  |  |             this.gl = gl | 
 |  |  |             this.canvas = canvas | 
 |  |  |             this.camera = camera | 
 |  |  |             this.holder = holder | 
 |  |  |             this.onUpdate = options.onUpdate | 
 |  |  |             this.onResize = options.onResize | 
 |  |  |             this.data = {} | 
 |  |  |  | 
 |  |  |             holder.appendChild( canvas ) | 
 |  |  |  | 
 |  |  |             this.createProgram( options.vertex, options.fragment ) | 
 |  |  |  | 
 |  |  |             this.createBuffers( buffers ) | 
 |  |  |             this.createUniforms( uniforms ) | 
 |  |  |  | 
 |  |  |             this.updateBuffers() | 
 |  |  |             this.updateUniforms() | 
 |  |  |  | 
 |  |  |             this.createTexture( options.texture ) | 
 |  |  |  | 
 |  |  |             gl.enable( gl.BLEND ) | 
 |  |  |             gl.enable( gl.CULL_FACE ) | 
 |  |  |             gl.blendFunc( gl.SRC_ALPHA, gl.ONE ) | 
 |  |  |             gl[ options.depthTest ? 'enable' : 'disable' ]( gl.DEPTH_TEST ) | 
 |  |  |  | 
 |  |  |             if ( options.autosize ) | 
 |  |  |                 window.addEventListener( 'resize', e => this.resize( e ), false ) | 
 |  |  |             if ( options.mousemove ) | 
 |  |  |                 window.addEventListener( 'mousemove', e => this.mousemove( e ), false ) | 
 |  |  |  | 
 |  |  |             this.resize() | 
 |  |  |  | 
 |  |  |             this.update = this.update.bind( this ) | 
 |  |  |             this.time = { start: performance.now(), old: performance.now() } | 
 |  |  |             this.update() | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         mousemove( e ) { | 
 |  |  |  | 
 |  |  |             let x = e.pageX / this.width * 2 - 1 | 
 |  |  |             let y = e.pageY / this.height * 2 - 1 | 
 |  |  |  | 
 |  |  |             this.uniforms.mousemove = [ x, y ] | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         resize( e ) { | 
 |  |  |  | 
 |  |  |             const holder = this.holder | 
 |  |  |             const canvas = this.canvas | 
 |  |  |             const gl = this.gl | 
 |  |  |  | 
 |  |  |             const width = this.width = holder.offsetWidth | 
 |  |  |             const height = this.height = holder.offsetHeight | 
 |  |  |             const aspect = this.aspect = width / height | 
 |  |  |             const dpi = this.dpi = devicePixelRatio | 
 |  |  |  | 
 |  |  |             canvas.width = width * dpi | 
 |  |  |             canvas.height = height * dpi | 
 |  |  |             canvas.style.width = width + 'px' | 
 |  |  |             canvas.style.height = height + 'px' | 
 |  |  |  | 
 |  |  |             gl.viewport( 0, 0, width * dpi, height * dpi ) | 
 |  |  |             gl.clearColor( 0, 0, 0, 0 ) | 
 |  |  |  | 
 |  |  |             this.uniforms.resolution = [ width, height ] | 
 |  |  |             this.uniforms.projection = this.setProjection( aspect ) | 
 |  |  |  | 
 |  |  |             this.onResize( width, height, dpi ) | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         setProjection( aspect ) { | 
 |  |  |  | 
 |  |  |             const camera = this.camera | 
 |  |  |  | 
 |  |  |             if ( camera.perspective ) { | 
 |  |  |  | 
 |  |  |                 camera.aspect = aspect | 
 |  |  |  | 
 |  |  |                 const fovRad = camera.fov * ( Math.PI / 180 ) | 
 |  |  |                 const f = Math.tan( Math.PI * 0.5 - 0.5 * fovRad ) | 
 |  |  |                 const rangeInv = 1.0 / ( camera.near - camera.far ) | 
 |  |  |  | 
 |  |  |                 const matrix = [ | 
 |  |  |                     f / camera.aspect, 0, 0, 0, | 
 |  |  |                     0, f, 0, 0, | 
 |  |  |                     0, 0, (camera.near + camera.far) * rangeInv, -1, | 
 |  |  |                     0, 0, camera.near * camera.far * rangeInv * 2, 0 | 
 |  |  |                 ] | 
 |  |  |  | 
 |  |  |                 matrix[ 14 ] += camera.z | 
 |  |  |                 matrix[ 15 ] += camera.z | 
 |  |  |  | 
 |  |  |                 return matrix | 
 |  |  |  | 
 |  |  |             } else { | 
 |  |  |  | 
 |  |  |                 return [ | 
 |  |  |                     2 / this.width, 0, 0, 0, | 
 |  |  |                     0, -2 / this.height, 0, 0, | 
 |  |  |                     0, 0, 1, 0, | 
 |  |  |                     -1, 1, 0, 1, | 
 |  |  |                 ] | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         createShader( type, source ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const shader = gl.createShader( type ) | 
 |  |  |  | 
 |  |  |             gl.shaderSource( shader, source ) | 
 |  |  |             gl.compileShader( shader ) | 
 |  |  |  | 
 |  |  |             if ( gl.getShaderParameter (shader, gl.COMPILE_STATUS ) ) { | 
 |  |  |  | 
 |  |  |                 return shader | 
 |  |  |  | 
 |  |  |             } else { | 
 |  |  |  | 
 |  |  |                 console.log( gl.getShaderInfoLog( shader ) ) | 
 |  |  |                 gl.deleteShader( shader ) | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         createProgram( vertex, fragment ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |  | 
 |  |  |             const vertexShader = this.createShader( gl.VERTEX_SHADER, vertex ) | 
 |  |  |             const fragmentShader = this.createShader( gl.FRAGMENT_SHADER, fragment ) | 
 |  |  |  | 
 |  |  |             const program = gl.createProgram() | 
 |  |  |  | 
 |  |  |             gl.attachShader( program, vertexShader ) | 
 |  |  |             gl.attachShader( program, fragmentShader ) | 
 |  |  |             gl.linkProgram( program ) | 
 |  |  |  | 
 |  |  |             if ( gl.getProgramParameter( program, gl.LINK_STATUS ) ) { | 
 |  |  |  | 
 |  |  |                 gl.useProgram( program ) | 
 |  |  |                 this.program = program | 
 |  |  |  | 
 |  |  |             } else { | 
 |  |  |  | 
 |  |  |                 console.log( gl.getProgramInfoLog( program ) ) | 
 |  |  |                 gl.deleteProgram( program ) | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         createUniforms( data ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const uniforms = this.data.uniforms = data | 
 |  |  |             const values = this.uniforms = {} | 
 |  |  |  | 
 |  |  |             Object.keys( uniforms ).forEach( name => { | 
 |  |  |  | 
 |  |  |                 const uniform = uniforms[ name ] | 
 |  |  |  | 
 |  |  |                 uniform.location = gl.getUniformLocation( this.program, 'u_' + name ) | 
 |  |  |  | 
 |  |  |                 Object.defineProperty( values, name, { | 
 |  |  |                     set: value => { | 
 |  |  |  | 
 |  |  |                         uniforms[ name ].value = value | 
 |  |  |                         this.setUniform( name, value ) | 
 |  |  |  | 
 |  |  |                     }, | 
 |  |  |                     get: () => uniforms[ name ].value | 
 |  |  |                 } ) | 
 |  |  |  | 
 |  |  |             } ) | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         setUniform( name, value ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const uniform = this.data.uniforms[ name ] | 
 |  |  |  | 
 |  |  |             uniform.value = value | 
 |  |  |  | 
 |  |  |             switch ( uniform.type ) { | 
 |  |  |                 case 'int': { | 
 |  |  |                     gl.uniform1i( uniform.location, value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |                 case 'float': { | 
 |  |  |                     gl.uniform1f( uniform.location, value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |                 case 'vec2': { | 
 |  |  |                     gl.uniform2f( uniform.location, ...value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |                 case 'vec3': { | 
 |  |  |                     gl.uniform3f( uniform.location, ...value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |                 case 'vec4': { | 
 |  |  |                     gl.uniform4f( uniform.location, ...value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |                 case 'mat2': { | 
 |  |  |                     gl.uniformMatrix2fv( uniform.location, false, value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |                 case 'mat3': { | 
 |  |  |                     gl.uniformMatrix3fv( uniform.location, false, value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |                 case 'mat4': { | 
 |  |  |                     gl.uniformMatrix4fv( uniform.location, false, value ) | 
 |  |  |                     break | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // ivec2       : uniform2i, | 
 |  |  |             // ivec3       : uniform3i, | 
 |  |  |             // ivec4       : uniform4i, | 
 |  |  |             // sampler2D   : uniform1i, | 
 |  |  |             // samplerCube : uniform1i, | 
 |  |  |             // bool        : uniform1i, | 
 |  |  |             // bvec2       : uniform2i, | 
 |  |  |             // bvec3       : uniform3i, | 
 |  |  |             // bvec4       : uniform4i, | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         updateUniforms() { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const uniforms = this.data.uniforms | 
 |  |  |  | 
 |  |  |             Object.keys( uniforms ).forEach( name => { | 
 |  |  |  | 
 |  |  |                 const uniform = uniforms[ name ] | 
 |  |  |  | 
 |  |  |                 this.uniforms[ name ] = uniform.value | 
 |  |  |  | 
 |  |  |             } ) | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         createBuffers( data ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const buffers = this.data.buffers = data | 
 |  |  |             const values = this.buffers = {} | 
 |  |  |  | 
 |  |  |             Object.keys( buffers ).forEach( name => { | 
 |  |  |  | 
 |  |  |                 const buffer = buffers[ name ] | 
 |  |  |  | 
 |  |  |                 buffer.buffer = this.createBuffer( 'a_' + name, buffer.size ) | 
 |  |  |  | 
 |  |  |                 Object.defineProperty( values, name, { | 
 |  |  |                     set: data => { | 
 |  |  |  | 
 |  |  |                         buffers[ name ].data = data | 
 |  |  |                         this.setBuffer( name, data ) | 
 |  |  |  | 
 |  |  |                         if ( name == 'position' ) | 
 |  |  |                             this.count = buffers.position.data.length / 3 | 
 |  |  |  | 
 |  |  |                     }, | 
 |  |  |                     get: () => buffers[ name ].data | 
 |  |  |                 } ) | 
 |  |  |  | 
 |  |  |             } ) | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         createBuffer( name, size ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const program = this.program | 
 |  |  |  | 
 |  |  |             const index = gl.getAttribLocation( program, name ) | 
 |  |  |             const buffer = gl.createBuffer() | 
 |  |  |  | 
 |  |  |             gl.bindBuffer( gl.ARRAY_BUFFER, buffer ) | 
 |  |  |             gl.enableVertexAttribArray( index ) | 
 |  |  |             gl.vertexAttribPointer( index, size, gl.FLOAT, false, 0, 0 ) | 
 |  |  |  | 
 |  |  |             return buffer | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         setBuffer( name, data ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const buffers = this.data.buffers | 
 |  |  |  | 
 |  |  |             if ( name == null && ! gl.bindBuffer( gl.ARRAY_BUFFER, null ) ) return | 
 |  |  |  | 
 |  |  |             gl.bindBuffer( gl.ARRAY_BUFFER, buffers[ name ].buffer ) | 
 |  |  |             gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( data ), gl.STATIC_DRAW ) | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         updateBuffers() { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const buffers = this.buffers | 
 |  |  |  | 
 |  |  |             Object.keys( buffers ).forEach( name => | 
 |  |  |                 buffers[ name ] = buffer.data | 
 |  |  |             ) | 
 |  |  |  | 
 |  |  |             this.setBuffer( null ) | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         createTexture( src ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const texture = gl.createTexture() | 
 |  |  |  | 
 |  |  |             gl.bindTexture( gl.TEXTURE_2D, texture ) | 
 |  |  |             gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array( [ 0, 0, 0, 0 ] ) ) | 
 |  |  |  | 
 |  |  |             this.texture = texture | 
 |  |  |  | 
 |  |  |             if ( src ) { | 
 |  |  |  | 
 |  |  |                 this.uniforms.hasTexture = 1 | 
 |  |  |                 this.loadTexture( src ) | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         loadTexture( src ) { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |             const texture = this.texture | 
 |  |  |  | 
 |  |  |             const textureImage = new Image() | 
 |  |  |  | 
 |  |  |             textureImage.onload = () => { | 
 |  |  |  | 
 |  |  |                 gl.bindTexture( gl.TEXTURE_2D, texture ) | 
 |  |  |  | 
 |  |  |                 gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImage ) | 
 |  |  |  | 
 |  |  |                 gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR ) | 
 |  |  |                 gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR ) | 
 |  |  |  | 
 |  |  |                 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) | 
 |  |  |                 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) | 
 |  |  |  | 
 |  |  |                 // gl.generateMipmap( gl.TEXTURE_2D ) | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             textureImage.src = src | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         update() { | 
 |  |  |  | 
 |  |  |             const gl = this.gl | 
 |  |  |  | 
 |  |  |             const now = performance.now() | 
 |  |  |             const elapsed = ( now - this.time.start ) / 5000 | 
 |  |  |             const delta = now - this.time.old | 
 |  |  |             this.time.old = now | 
 |  |  |  | 
 |  |  |             this.uniforms.time = elapsed | 
 |  |  |  | 
 |  |  |             if ( this.count > 0 ) { | 
 |  |  |                 gl.clear( gl.COLORBUFFERBIT ) | 
 |  |  |                 gl.drawArrays( gl.POINTS, 0, this.count ) | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             this.onUpdate( delta ) | 
 |  |  |  | 
 |  |  |             requestAnimationFrame( this.update ) | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     const pointSize = 2.5 | 
 |  |  |  | 
 |  |  |     const waves = new ShaderProgram( document.querySelector( '.waves' ), { | 
 |  |  |         texture: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAb1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8v0wLRAAAAJHRSTlMAC/goGvDhmwcExrVjWzrm29TRqqSKenRXVklANSIUE8mRkGpv+HOfAAABCElEQVQ4y4VT13LDMAwLrUHteO+R9f/fWMfO6dLaPeKVEECRxOULWsEGpS9nULDwia2Y+ALqUNbAWeg775zv+sA4/FFRMxt8U2FZFCVWjR/YrH4/H9sarclSKdPMWKzb8VsEeHB3m0shkhVCyNzeXeAQ9Xl4opEieX2QCGnwGbj6GMyjw9t1K0fK9YZunPXeAGsfJtYjwzxaBnozGGorYz0ypK2HzQSYx1y8DgSRo2ewOiyh2QWOEk1Y9OrQV0a8TiBM1a8eMHWYnRMy7CZ4t1CmyRkhSUvP3gRXyHOCLBxNoC3IJv//ZrJ/kxxUHPUB+6jJZZHrpg6GOjnqaOmzp4NDR48OLxn/H27SRQ08S0ZJAAAAAElFTkSuQmCC', | 
 |  |  |         uniforms: { | 
 |  |  |             size: { type: 'float', value: pointSize }, | 
 |  |  |             field: { type: 'vec3', value: [ 0, 0, 0 ] }, | 
 |  |  |             speed: { type: 'float', value: 5 }, | 
 |  |  |         }, | 
 |  |  |         vertex: ` | 
 |  |  |     #define M_PI 3.1415926535897932384626433832795 | 
 |  |  |  | 
 |  |  |     precision highp float; | 
 |  |  |  | 
 |  |  |     attribute vec4 a_position; | 
 |  |  |     attribute vec4 a_color; | 
 |  |  |  | 
 |  |  |     uniform float u_time; | 
 |  |  |     uniform float u_size; | 
 |  |  |     uniform float u_speed; | 
 |  |  |     uniform vec3 u_field; | 
 |  |  |     uniform mat4 u_projection; | 
 |  |  |  | 
 |  |  |     varying vec4 v_color; | 
 |  |  |  | 
 |  |  |     void main() { | 
 |  |  |  | 
 |  |  |       vec3 pos = a_position.xyz; | 
 |  |  |  | 
 |  |  |       pos.y += ( | 
 |  |  |         cos(pos.x / u_field.x * M_PI * 8.0 + u_time * u_speed) + | 
 |  |  |         sin(pos.z / u_field.z * M_PI * 8.0 + u_time * u_speed) | 
 |  |  |       ) * u_field.y; | 
 |  |  |  | 
 |  |  |       gl_Position = u_projection * vec4( pos.xyz, a_position.w ); | 
 |  |  |       gl_PointSize = ( u_size / gl_Position.w ) * 100.0; | 
 |  |  |  | 
 |  |  |       v_color = a_color; | 
 |  |  |  | 
 |  |  |     }`, | 
 |  |  |         fragment: ` | 
 |  |  |     precision highp float; | 
 |  |  |  | 
 |  |  |     uniform sampler2D u_texture; | 
 |  |  |  | 
 |  |  |     varying vec4 v_color; | 
 |  |  |  | 
 |  |  |     void main() { | 
 |  |  |  | 
 |  |  |       gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord); | 
 |  |  |  | 
 |  |  |     }`, | 
 |  |  |         onResize( w, h, dpi ) { | 
 |  |  |  | 
 |  |  |             const position = [], color = [] | 
 |  |  |  | 
 |  |  |             const width = 400 * ( w / h ) | 
 |  |  |             const depth = 400 | 
 |  |  |             const height = 3 | 
 |  |  |             const distance = 5 | 
 |  |  |  | 
 |  |  |             for ( let x = 0; x < width; x += distance ) { | 
 |  |  |                 for ( let z = 0; z < depth; z+= distance ) { | 
 |  |  |  | 
 |  |  |                     position.push( - width / 2 + x, -30, -depth / 2 + z ) | 
 |  |  |                     color.push( 0, 1 - ( x / width ) * 1, 0.5 + x / width * 0.5, z / depth ) | 
 |  |  |  | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             this.uniforms.field = [ width, height, depth ] | 
 |  |  |  | 
 |  |  |             this.buffers.position = position | 
 |  |  |             this.buffers.color = color | 
 |  |  |  | 
 |  |  |             this.uniforms.size = ( h / 400) * pointSize * dpi | 
 |  |  |  | 
 |  |  |         }, | 
 |  |  |     } ) | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script> | 
 |  |  | <script type="text/javascript" src="../static/js/tools/md5.js"></script> | 
 |  |  | <script type="text/javascript" src="../static/layer/layer.js"></script> | 
 |  |  | <script type="text/javascript" src="../static/js/common.js"></script> | 
 |  |  | <script> | 
 |  |  |     // remember pwd | 
 |  |  |     $(function () { | 
 |  |  |         var oldUserName = localStorage.getItem('oldUserName'); | 
 |  |  |         var oldPass = localStorage.getItem('oldPass'); | 
 |  |  |         if(oldUserName){ | 
 |  |  |             $('#username').val(oldUserName); | 
 |  |  |         } | 
 |  |  |         if(oldPass){ | 
 |  |  |             $('#password').val(oldPass); | 
 |  |  |         } | 
 |  |  |     }) | 
 |  |  |  | 
 |  |  |     window.onload = function(){document.getElementById("username").focus();} | 
 |  |  |  | 
 |  |  |     $(document).on('click','#login-button', function () { | 
 |  |  |         let username = $("#username").val(); | 
 |  |  |         if (username === "") { | 
 |  |  |             layer.tips('请输入登录账号', '#username', {tips: [4, '#ff0000']}); | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |         let password = $("#password").val(); | 
 |  |  |         if (password === "") { | 
 |  |  |             layer.tips('请输入密码', '#password', {tips: [4, '#ff0000']}); | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |         $.ajax({ | 
 |  |  |             url: baseUrl+"/login.action", | 
 |  |  |             data: { | 
 |  |  |                 mobile: username, | 
 |  |  |                 password: hex_md5(password) | 
 |  |  |             }, | 
 |  |  |             method: 'POST', | 
 |  |  |             success: function (res) { | 
 |  |  |                 if (res.code === 200){ | 
 |  |  |                     localStorage.setItem("token", res.data.token); | 
 |  |  |                     localStorage.setItem("username", res.data.username); | 
 |  |  |                     window.location.href = "index.html"; | 
 |  |  |                 } else if (res.code === 10001) { | 
 |  |  |                     layer.tips(res.msg, '#username', {tips: [4, '#ff0000']}); | 
 |  |  |                 } else if (res.code === 10002) { | 
 |  |  |                     layer.tips(res.msg, '#username', {tips: [4, '#ff0000']}); | 
 |  |  |                 } else if (res.code === 10003) { | 
 |  |  |                     layer.tips(res.msg, '#password', {tips: [4, '#ff0000']}); | 
 |  |  |                 } else { | 
 |  |  |                     layer.tips(res.msg, '.login-btn', {tips: [3, '#ff0000']}); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |     }); | 
 |  |  |  | 
 |  |  |     $('body').keydown(function () { | 
 |  |  |         if (event.keyCode === 13) { | 
 |  |  |             $(".login-btn").click(); | 
 |  |  |         } | 
 |  |  |     }); | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | </body> | 
 |  |  | </html> | 
 |  |  |          //上传并更新许可证 | 
 |  |  |          $("#license").on("change",(evt) => { | 
 |  |  |             var files = evt.target.files; | 
 |  |  |             console.log(files) | 
 |  |  |             let formData = new FormData(); | 
 |  |  |             formData.append("file", files[0]) | 
 |  |  |             $.ajax({ | 
 |  |  |                url: baseUrl+"/license/updateLicense", | 
 |  |  |                data: formData, | 
 |  |  |                method: 'POST', | 
 |  |  |                cache: false, | 
 |  |  |                processData: false, | 
 |  |  |                contentType: false, | 
 |  |  |                success: function (res) { | 
 |  |  |                   if (res.code == 200) { | 
 |  |  |                      layer.msg('更新成功', {time: 1000}, () => { | 
 |  |  |                         parent.location.reload() | 
 |  |  |                      }); | 
 |  |  |                   }else{ | 
 |  |  |                      layer.msg(res.msg,{time:2000},() => { | 
 |  |  |                         parent.location.reload() | 
 |  |  |                      }) | 
 |  |  |                   } | 
 |  |  |                } | 
 |  |  |             }) | 
 |  |  |          }) | 
 |  |  |       </script> | 
 |  |  |    </body> | 
 |  |  | </html> |