Forráskód Böngészése

Merge branch 'iteration-roll-call' into online

lex 1 éve
szülő
commit
09c4bad4f7
39 módosított fájl, 3041 hozzáadás és 112 törlés
  1. 37 56
      dev-dist/sw.js
  2. 356 0
      public/roll-call/css/index.css
  3. BIN
      public/roll-call/img/1.webp
  4. BIN
      public/roll-call/img/10.webp
  5. BIN
      public/roll-call/img/2.webp
  6. BIN
      public/roll-call/img/3.webp
  7. BIN
      public/roll-call/img/4.webp
  8. BIN
      public/roll-call/img/5.webp
  9. BIN
      public/roll-call/img/6.webp
  10. BIN
      public/roll-call/img/7.webp
  11. BIN
      public/roll-call/img/8.webp
  12. BIN
      public/roll-call/img/9.webp
  13. BIN
      public/roll-call/img/icon-back.png
  14. BIN
      public/roll-call/img/icon-over-btn.png
  15. BIN
      public/roll-call/img/icon-start-btn-disabled.png
  16. BIN
      public/roll-call/img/icon-start-btn.png
  17. BIN
      public/roll-call/img/icon-title.png
  18. BIN
      public/roll-call/img/starBg.jpg
  19. BIN
      public/roll-call/img/startBg2.png
  20. 400 0
      public/roll-call/index.html
  21. 173 0
      public/roll-call/js/CSS2DRenderer.js
  22. 243 0
      public/roll-call/js/CSS3DRenderer.js
  23. 287 0
      public/roll-call/js/RaytracingRenderer.js
  24. 611 0
      public/roll-call/js/TrackballControls.js
  25. 11 0
      public/roll-call/js/data.js
  26. 128 0
      public/roll-call/js/star.js
  27. 5 0
      public/roll-call/js/stats.min.js
  28. 372 0
      public/roll-call/js/three.min.js
  29. 13 0
      public/roll-call/js/tween.min.js
  30. 5 0
      public/roll-call/js/vue.min.js
  31. BIN
      public/roll-call/music/04-抽奖音乐 猪突猛進.mp3
  32. BIN
      public/roll-call/music/9629.mp3
  33. 1 1
      public/version.json
  34. 120 0
      src/views/attend-class/component/roll-call/pen.module.less
  35. 131 0
      src/views/attend-class/component/roll-call/pen.tsx
  36. 50 32
      src/views/attend-class/component/tools/pen.tsx
  37. BIN
      src/views/attend-class/image/right_icon10.png
  38. 7 1
      src/views/attend-class/index.module.less
  39. 91 22
      src/views/attend-class/index.tsx

+ 37 - 56
dev-dist/sw.js

@@ -13,29 +13,31 @@
 
 // If the loader is already loaded, just stop.
 if (!self.define) {
-  const registry = {};
+  let registry = {};
 
   // Used for `eval` and `importScripts` where we can't get script URL by other means.
   // In both cases, it's safe to use a global var because those functions are synchronous.
   let nextDefineUri;
 
   const singleRequire = (uri, parentUri) => {
-    uri = new URL(uri + '.js', parentUri).href;
-    return (
-      registry[uri] ||
-      new Promise(resolve => {
-        if ('document' in self) {
-          const script = document.createElement('script');
-          script.src = uri;
-          script.onload = resolve;
-          document.head.appendChild(script);
-        } else {
-          nextDefineUri = uri;
-          importScripts(uri);
-          resolve();
-        }
-      }).then(() => {
-        const promise = registry[uri];
+    uri = new URL(uri + ".js", parentUri).href;
+    return registry[uri] || (
+      
+        new Promise(resolve => {
+          if ("document" in self) {
+            const script = document.createElement("script");
+            script.src = uri;
+            script.onload = resolve;
+            document.head.appendChild(script);
+          } else {
+            nextDefineUri = uri;
+            importScripts(uri);
+            resolve();
+          }
+        })
+      
+      .then(() => {
+        let promise = registry[uri];
         if (!promise) {
           throw new Error(`Module ${uri} didn’t register its module`);
         }
@@ -45,31 +47,27 @@ if (!self.define) {
   };
 
   self.define = (depsNames, factory) => {
-    const uri =
-      nextDefineUri ||
-      ('document' in self ? document.currentScript.src : '') ||
-      location.href;
+    const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href;
     if (registry[uri]) {
       // Module is already loading or loaded.
       return;
     }
-    const exports = {};
+    let exports = {};
     const require = depUri => singleRequire(depUri, uri);
     const specialDeps = {
       module: { uri },
       exports,
       require
     };
-    registry[uri] = Promise.all(
-      depsNames.map(depName => specialDeps[depName] || require(depName))
-    ).then(deps => {
+    registry[uri] = Promise.all(depsNames.map(
+      depName => specialDeps[depName] || require(depName)
+    )).then(deps => {
       factory(...deps);
       return exports;
     });
   };
 }
-define(['./workbox-5357ef54'], function (workbox) {
-  ('use strict');
+define(['./workbox-5357ef54'], (function (workbox) { 'use strict';
 
   self.skipWaiting();
   workbox.clientsClaim();
@@ -79,33 +77,16 @@ define(['./workbox-5357ef54'], function (workbox) {
    * requests for URLs in the manifest.
    * See https://goo.gl/S9QRab
    */
-  workbox.precacheAndRoute(
-    [
-      {
-        url: 'registerSW.js',
-        revision: '3ca0b8505b4bec776b69afdba2768812'
-      },
-      {
-        url: 'index.html',
-        revision: '0.03e7uq64dqg'
-      }
-    ],
-    {}
-  );
-
-  /**
-   * https://juejin.cn/post/6844903881189621767
-   * 缓存策略 有5种
-   */
+  workbox.precacheAndRoute([{
+    "url": "registerSW.js",
+    "revision": "3ca0b8505b4bec776b69afdba2768812"
+  }, {
+    "url": "index.html",
+    "revision": "0.3vo3lspd3m"
+  }], {});
   workbox.cleanupOutdatedCaches();
-  workbox.registerRoute(
-    new workbox.NavigationRoute(workbox.createHandlerBoundToURL('index.html'), {
-      allowlist: [/^\/$/]
-    }),
-    workbox.strategies.NetworkFirst()
-  );
-  workbox.routing.registerRoute(
-    new RegExp('.*.html|css|js'),
-    workbox.strategies.NetworkFirst()
-  );
-});
+  workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
+    allowlist: [/^\/$/]
+  }));
+
+}));

+ 356 - 0
public/roll-call/css/index.css

@@ -0,0 +1,356 @@
+html,
+body {
+  height: 100%;
+}
+* {
+  padding: 0;
+  margin: 0;
+  box-sizing: border-box;
+}
+body {
+  background-color: #000000;
+  margin: 0;
+  font-family: Helvetica, sans-serif;
+  overflow: hidden;
+  background: url('../img/startBg2.png') no-repeat center #000000;
+  background-size: cover;
+}
+
+.pageTitle {
+  width: 217px;
+  height: 103px;
+  background: url('../img/icon-title.png') no-repeat center;
+  background-size: contain;
+  position: fixed;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.iconBack {
+  width: 54px;
+  height: 54px;
+  background: url('../img/icon-back.png') no-repeat center;
+  background-size: contain;
+  position: fixed;
+  left: 36px;
+  top: 30px;
+  cursor: pointer;
+  transition: opacity 0.2s ease;
+}
+.iconBack:hover {
+  opacity: 0.9;
+  transition: opacity 0.2s ease;
+}
+
+a {
+  color: #ffffff;
+}
+
+#info {
+  position: absolute;
+  width: 100%;
+  color: #ffffff;
+  padding: 5px;
+  font-family: Monospace;
+  font-size: 13px;
+  font-weight: bold;
+  text-align: center;
+  z-index: 1;
+}
+
+#menu {
+  position: absolute;
+  bottom: 50px;
+  width: 100%;
+  text-align: center;
+}
+.bss {
+  height: 100vh;
+  width: 100%;
+}
+.element {
+  width: 152px;
+  height: 172px;
+  box-shadow: 0px 3px 7px 0px rgba(99, 171, 186, 0.53);
+  text-align: center;
+  cursor: default;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  transition: all 0.2s ease;
+}
+
+.element.hide {
+  visibility: hidden;
+  opacity: 0;
+  transition: all 0.2s ease;
+}
+
+.element .symbolBox {
+  display: block;
+  width: 98px;
+  height: 98px;
+  overflow: hidden;
+  border-radius: 50%;
+  border: 3px solid #4daaff;
+}
+.element .symbolBox img {
+  width: 100%;
+  height: 100%;
+}
+
+.element .details {
+  padding-top: 15px;
+  font-size: 22px;
+  color: #374693;
+  font-weight: 500;
+  max-width: 100px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+#table {
+  width: 171px;
+  height: 69px;
+  background: url('../img/icon-start-btn.png') no-repeat center;
+  background-size: contain;
+  border: none;
+  cursor: pointer;
+  transition: opacity 0.2s ease;
+}
+#table:hover {
+  opacity: 0.9;
+  transition: opacity 0.2s ease;
+}
+#table.disabled {
+  background: url('../img/icon-start-btn-disabled.png') no-repeat center;
+  background-size: contain;
+  cursor: not-allowed;
+}
+#table.disabled:hover {
+  opacity: 1;
+}
+#sphere {
+  width: 171px;
+  height: 69px;
+  background: url('../img/icon-over-btn.png') no-repeat center;
+  background-size: contain;
+  border: none;
+  cursor: pointer;
+  transition: opacity 0.2s ease;
+}
+#sphere:hover {
+  opacity: 0.9;
+  transition: opacity 0.2s ease;
+}
+
+.changeImgBoxs {
+  position: relative;
+  overflow: hidden;
+  width: 257px;
+  height: 292px;
+  background: #ffffff;
+  box-shadow: 0px 7px 16px 0px rgba(108, 200, 220, 0.53);
+  border-radius: 15px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+.changeImgBoxs .details {
+  padding-top: 22px;
+  font-weight: 500;
+  font-size: 35px;
+  color: #374693;
+  line-height: 49px;
+  text-align: center;
+  max-width: 200px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.symbolBox2 {
+  width: 166px;
+  height: 166px;
+  border: 6px solid #4daaff;
+  position: relative;
+  overflow: hidden;
+  border-radius: 50%;
+}
+.symbol2 {
+  position: absolute;
+  top: 0;
+  left: 50%;
+  height: 100%;
+  transform: translateX(-50%);
+}
+
+.priceLists {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.9);
+}
+.closeBtn {
+  position: absolute;
+  right: 30px;
+  top: 20px;
+  width: 40px;
+  height: 40px;
+  font-size: 38px;
+  line-height: 40px;
+  text-align: center;
+  border-radius: 50%;
+  border: 2px solid rgba(127, 255, 255, 0.75);
+  color: rgba(127, 255, 255, 0.75);
+  cursor: pointer;
+}
+
+.listBoxs {
+  width: 80%;
+  height: 80%;
+  border-radius: 20px;
+  border: 2px solid rgba(127, 255, 255, 0.75);
+  box-shadow: 0 0 20px rgba(127, 255, 255, 0.75);
+  margin: 0 auto;
+  margin-top: 80px;
+  display: flex;
+  flex-direction: column;
+  position: relative;
+}
+.listBoxs .tit {
+  height: 80px;
+  width: 100%;
+  font-size: 38px;
+  text-align: center;
+  line-height: 80px;
+  color: rgba(127, 255, 255, 0.75);
+}
+.listBoxs .listBox {
+  min-height: 80px;
+  padding: 20px;
+  display: flex;
+  align-content: center;
+  padding-left: 60px;
+}
+.listBox label {
+  font-size: 24px;
+  color: rgba(127, 255, 255, 0.75);
+  display: block;
+  width: 120px;
+  text-align: right;
+  padding-right: 20px;
+  line-height: 80px;
+}
+.listBox dl {
+  width: 110px;
+  height: 150px;
+  padding: 10px;
+  border: 2px solid rgba(127, 255, 255, 0.75);
+  border-radius: 5px;
+  box-shadow: 0 0 10px rgba(127, 255, 255, 0.75);
+  background: rgba(127, 255, 255, 0.25);
+  margin-right: 20px;
+}
+.listBox dl dt {
+  width: 100%;
+  height: 80%;
+  position: relative;
+  overflow: hidden;
+}
+.listBox dl dt img {
+  height: 100%;
+  position: relative;
+  left: 50%;
+  transform: translateX(-50%);
+}
+.listBox dl dd {
+  text-align: center;
+  font-size: 15px;
+  line-height: 40px;
+  color: rgba(127, 255, 255, 0.75);
+}
+.listBoxs .clear {
+  position: absolute;
+  left: 30px;
+  bottom: 30px;
+  width: 120px;
+  height: 50px;
+  font-size: 20px;
+  text-align: center;
+  line-height: 50px;
+  cursor: pointer;
+  color: rgba(127, 255, 255, 0.75);
+  border-radius: 5px;
+  border: 2px solid rgba(127, 255, 255, 0.75);
+  box-shadow: 0 0 10px rgba(127, 255, 255, 0.75);
+  background: rgba(127, 255, 255, 0.25);
+}
+.listBoxs .clear2 {
+  right: 30px;
+  left: auto;
+}
+.spic {
+  position: absolute;
+  right: 20px;
+  top: 70px;
+  width: 400px;
+  height: 80%;
+}
+/*特等奖*/
+.spic p {
+  color: rgba(127, 255, 255, 0.75);
+  font-size: 25px;
+  line-height: 3;
+}
+.spic dl {
+  width: 240px;
+  height: 320px;
+  padding: 20px;
+  border: 2px solid rgba(127, 255, 255, 0.75);
+  border-radius: 10px;
+  box-shadow: 0 0 20px rgba(127, 255, 255, 0.75);
+  background: rgba(127, 255, 255, 0.25);
+  margin-right: 20px;
+}
+.spic dl dt {
+  width: 100%;
+  height: 83%;
+  position: relative;
+  overflow: hidden;
+}
+.spic dl dt img {
+  height: 100%;
+  position: relative;
+  left: 50%;
+  transform: translateX(-50%);
+}
+.spic dl dd {
+  text-align: center;
+  font-size: 32px;
+  line-height: 70px;
+  color: rgba(127, 255, 255, 0.75);
+}
+
+/*礼包*/
+.imgBox {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 300px;
+  height: 400px;
+  background: rgba(0, 0, 0, 0.3);
+  margin-top: 100px;
+}
+.imgBox p {
+  height: 100px;
+  line-height: 140px;
+  color: rgba(127, 255, 255, 0.75);
+  font-size: 36px;
+  text-align: center;
+}
+.imgBox img {
+  width: 300px;
+  height: 300px;
+}

BIN
public/roll-call/img/1.webp


BIN
public/roll-call/img/10.webp


BIN
public/roll-call/img/2.webp


BIN
public/roll-call/img/3.webp


BIN
public/roll-call/img/4.webp


BIN
public/roll-call/img/5.webp


BIN
public/roll-call/img/6.webp


BIN
public/roll-call/img/7.webp


BIN
public/roll-call/img/8.webp


BIN
public/roll-call/img/9.webp


BIN
public/roll-call/img/icon-back.png


BIN
public/roll-call/img/icon-over-btn.png


BIN
public/roll-call/img/icon-start-btn-disabled.png


BIN
public/roll-call/img/icon-start-btn.png


BIN
public/roll-call/img/icon-title.png


BIN
public/roll-call/img/starBg.jpg


BIN
public/roll-call/img/startBg2.png


+ 400 - 0
public/roll-call/index.html

@@ -0,0 +1,400 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8">
+  <link rel="icon" href="/favicon.ico" />
+  <meta name="viewport"
+    content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
+  <meta http-equiv="Cache-control" content="no-cache">
+  <meta http-equiv="Cache" content="no-cache">
+  <meta name="apple-mobile-web-app-capable" content="yes" />
+  <title>点名</title>
+  <link rel="stylesheet" href="./css/index.css">
+  <script src="js/three.min.js"></script>
+  <script src="js/tween.min.js"></script>
+  <!-- <script src="js/stats.min.js"></script> -->
+  <script src="js/TrackballControls.js"></script>
+  <script src="js/CSS3DRenderer.js"></script>
+  <script src="js/vue.min.js"></script>
+  <!-- 创建星星 -->
+  <!-- <script src="js/star.js"></script> -->
+  <!-- 数据位置 -->
+  <script src="js/data.js"></script>
+</head>
+
+<body>
+
+  <div id="container" style="pointer-events: none;"></div>
+  <div id="vueBoxs">
+    <div class="bss">
+      <div class="pageTitle"></div>
+      <div class="iconBack" @click="onBack()"></div>
+      <div id="menu">
+        <button id="table" :class="tableIndex <= 1 ? 'disabled' : ''" v-show="!animationStatus"
+          @click="start()"></button>
+        <button id="sphere" v-show="animationStatus" @click="closes()"></button>
+        <!-- <button id="reset" style="margin-left:40px;" @click="resets()">照片墙</button> -->
+        <!-- <button id="lists" @click="listShow = true">中奖名单</button> -->
+      </div>
+    </div>
+  </div>
+</body>
+
+</html>
+<script>
+  var table = getData();
+  var tableLens = table.length;
+  var camera, scene, renderer;
+  var controls;
+  var objects = [];
+  var targets = { chaos: [], table: [], sphere: [], helix: [], grid: [] };
+  var ang = 0, moving = false, objectsss, starBG, isMoving = false;  //objectsss 为切换的图片的
+  var cpx = 0, cpy = 0, cpz = 0, crx = 0, cry = 0, crz = 0;
+
+  function init() {
+    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
+    camera.position.z = 1500;
+    scene = new THREE.Scene();
+    // table
+    for (var i = 0; i < table.length; i++) {
+      // 每个图标的盒子
+      var element = document.createElement('div');
+      element.className = 'element';
+      element.style.backgroundColor = 'rgba(255,255,255)';
+      element.style.borderRadius = '12px'
+      if (i >= 32) {
+        element.className = 'element hide'
+      }
+      // 图片
+      var symbolBox = document.createElement('div');
+      var symbol = document.createElement('img');
+      symbolBox.className = 'symbolBox';
+      symbol.className = 'symbol';
+      symbol.src = table[i].img;
+      symbolBox.appendChild(symbol);
+      element.appendChild(symbolBox);
+      // 姓名
+      var details = document.createElement('div');
+      details.className = 'details';
+      details.innerHTML = table[i].name;
+      element.appendChild(details);
+      // 图标变成3d内的对象,放入场景中
+      var object = new THREE.CSS3DObject(element);
+      object.position.x = Math.random() * 3400 - 1700;
+      object.position.y = Math.random() * 3400 - 1700;
+      object.position.z = Math.random() * 3400 - 1700;
+      object.name = table[i].name;
+      scene.add(object);
+      objects.push(object);
+      // 根据索引,定制位置
+      var object = new THREE.Object3D();
+      var ix = (i) % 8;
+      object.position.y = 300;
+      if (table.length === 1) {
+        object.position.x = 0;
+      } else if (table.length === 2) {
+        object.position.x = (ix * 172) - (172 * 1 / 2);
+      } else if (table.length === 3) {
+        object.position.x = (ix * 172) - (172 * 2 / 2);
+      } else if (table.length === 4) {
+        object.position.x = (ix * 172) - (172 * 3 / 2);
+      } else if (table.length === 5) {
+        object.position.x = (ix * 172) - (172 * 4 / 2);
+      } else if (table.length === 6) {
+        object.position.x = (ix * 172) - (172 * 5 / 2);
+      } else if (table.length === 7) {
+        object.position.x = (ix * 172) - (172 * 6 / 2);
+      } else {
+        var iy = Math.floor((i) / 8);
+        object.position.x = (ix * 172) - 600;
+        object.position.y = - (iy * 192) + 300;
+      }
+
+      targets.table.push(object);
+    }
+
+    // 创建切换图片
+    var elements = document.createElement('div');
+    elements.className = 'changeImgBoxs';
+    // element.style.backgroundImage = "url(./img/pic.png)";
+    elements.style.backgroundColor = 'rgba(255,255,255)';
+
+    var symbolBox = document.createElement('div');
+    var symbol = document.createElement('img');
+    symbol.setAttribute("id", "changeImg");
+    symbolBox.className = 'symbolBox2';
+    symbol.className = 'symbol2';
+    symbol.src = table[0].img;
+    symbolBox.appendChild(symbol);
+    elements.appendChild(symbolBox);
+
+    var details = document.createElement('div');
+    details.setAttribute("id", "detailss");
+    details.className = 'details';
+    details.innerHTML = table[0].name;
+    elements.appendChild(details);
+
+    objectsss = new THREE.CSS3DObject(elements);
+    objectsss.position.x = 0;
+    objectsss.position.y = 20000;
+    objectsss.position.z = 0;
+    scene.add(objectsss);
+    // 散乱随机位置
+    var vector = new THREE.Vector3();
+    for (var i = 0, l = objects.length; i < l; i++) {
+      var phi = Math.acos(-1 + (2 * i) / l);
+      var theta = Math.sqrt(l * Math.PI) * phi;
+      var object = new THREE.Object3D();
+      var py = Math.random() * 3400 - 1700;
+      if (py < 400 && py > -400) {    //防止停止时,图片位置不好挡住中央的图片
+        if (py < 0) {
+          py -= 400;
+        } else {
+          py += 400;
+        }
+      }
+      object.position.x = Math.random() * 3400 - 1700;
+      object.position.y = py;
+      object.position.z = Math.random() * 3400 - 1700;
+      object.lookAt(vector);
+      targets.chaos.push(object);
+    }
+    // 球
+    var vector = new THREE.Vector3();
+    for (var i = 0, l = objects.length; i < l; i++) {
+      var phi = Math.acos(-1 + (2 * i) / l);
+      var theta = Math.sqrt(l * Math.PI) * phi;
+      var object = new THREE.Object3D();
+      object.position.x = 750 * Math.cos(theta) * Math.sin(phi);
+      object.position.y = 750 * Math.sin(theta) * Math.sin(phi);
+      object.position.z = 750 * Math.cos(phi);
+      vector.copy(object.position).multiplyScalar(2);
+      object.lookAt(vector);
+      targets.sphere.push(object);
+    }
+    //渲染
+    renderer = new THREE.CSS3DRenderer();
+    renderer.setSize(window.innerWidth, window.innerHeight);
+    renderer.domElement.style.position = 'absolute';
+    document.getElementById('container').appendChild(renderer.domElement);
+    //控制器
+    controls = new THREE.TrackballControls(camera, renderer.domElement);
+    controls.rotateSpeed = 0.5;
+    controls.minDistance = 500;
+    controls.maxDistance = 6000;
+    controls.addEventListener('change', render);
+    // 初始化
+    transform(targets.table, 500);
+    window.addEventListener('resize', onWindowResize, false);
+    cpx = camera.position.x;
+    cpy = camera.position.y;
+    cpz = camera.position.z;
+
+    crx = camera.rotation.x;
+    cry = camera.rotation.y;
+    crz = camera.rotation.z;
+  }
+  // 切换状态时动画
+  function transform(targets, duration, type) {
+    var scale = 1;
+    if (type == undefined) {
+      type = 0;
+    }
+    TWEEN.removeAll();
+    for (var i = 0; i < objects.length; i++) {
+      var object = objects[i];
+      var target = targets[i];
+
+      new TWEEN.Tween(object.position)
+        .to({ x: target.position.x, y: target.position.y, z: target.position.z }, Math.random() * duration + duration)
+        .easing(TWEEN.Easing.Exponential.InOut)
+        .start();
+      new TWEEN.Tween(object.rotation)
+        .to({ x: target.rotation.x, y: target.rotation.y, z: target.rotation.z }, Math.random() * duration + duration)
+        .easing(TWEEN.Easing.Exponential.InOut)
+        .start();
+    }
+    new TWEEN.Tween(this)
+      .to({}, duration * 2)
+      .onUpdate(render)
+      .start()
+
+    // console.log(document.querySelectorAll('.element'), '1212')
+    setTimeout(() => {
+      if (moving || type === 2) {
+        const elements = document.querySelectorAll('.element')
+        if (elements.length > 0) {
+          elements.forEach((e, index) => {
+            if (type === 2) {
+              if (index >= 32) {
+                e.classList.add('hide')
+              }
+            } else {
+              e.classList.remove('hide')
+            }
+          })
+        }
+      }
+    }, 400);
+
+  }
+  // 屏幕大小适配
+  function onWindowResize() {
+    camera.aspect = window.innerWidth / window.innerHeight;
+    camera.updateProjectionMatrix();
+    renderer.setSize(window.innerWidth, window.innerHeight);
+    render();
+  }
+  function animate() {
+    requestAnimationFrame(animate);
+    TWEEN.update();
+    // 旋转
+    if (moving) {
+      movings();
+    }
+    controls.update();
+    // 星空位置与相机位置相对
+    cpx = camera.position.x;
+    cpy = camera.position.y;
+    cpz = camera.position.z;
+
+    crx = camera.rotation.x;
+    cry = camera.rotation.y;
+    crz = camera.rotation.z;
+
+  }
+  function render() {
+    renderer.render(scene, camera);
+  }
+  var numsss = 0, srcss = '', txtsss = '';
+  function movings() {
+    // 相机旋转
+    ang += Math.PI / 50;
+    camera.position.x = Math.cos(ang) * 2000;
+    camera.position.z = Math.sin(ang) * 2000;
+    camera.position.y = 0;
+    // 相机方向重置
+    camera.up.x = 0;
+    camera.up.y = 1;
+    camera.up.z = 0;
+    // 图片方向固定
+    objectsss.rotation.y = -ang + Math.PI / 2;
+    //中间图片切换
+    numsss = Math.floor(Math.random() * tableLens);
+    if (numsss == tableLens) {
+      numsss = tableLens - 1;
+    }
+    srcss = table[numsss].img;
+    txtsss = table[numsss].name;
+    changeImg.src = srcss;
+    detailss.innerHTML = txtsss;
+  }
+  // 停止时,图片放大动画
+  function objDeal(obj, nums) {
+    var option = {
+      x: obj.scale.x,
+      y: obj.scale.y,
+      z: obj.scale.z,
+    };
+    var tween = new TWEEN.Tween(option).to({
+      x: nums,
+      y: nums,
+      z: nums,
+    }, 300).delay(100).onUpdate(function () {
+      obj.scale.x = this.x;
+      obj.scale.y = this.y;
+      obj.scale.z = this.z;
+      isMoving = true;
+    }).onComplete(function () {
+      isMoving = false;
+    }).start();
+  }
+
+  // 初始化数据
+  function renderData(data) {
+    table = data
+    tableLens = data.length
+    vm.tableIndex = tableLens
+    init();
+    animate();
+
+    console.log(vm.tableIndex, 'renderData')
+  }
+
+  //点击事件及部分判断
+  var vm = new Vue({
+    el: '#vueBoxs',
+    data: {
+      animationStatus: false,
+      tableIndex: 0,
+      listShow: false
+    },
+    methods: {
+      keyDowns: function () {
+        this.closes();
+      },
+      //开始
+      start: function () {
+        if (this.tableIndex <= 1) {
+          return
+        }
+        moving = true;
+        this.animationStatus = true;
+        objectsss.position.y = 0;
+        transform(targets.sphere, 1000);
+        objDeal(objectsss, 1);
+        // music.play();
+        // this.ckPrice();
+      },
+      //结束
+      closes: function () {
+        // music.pause();
+        if (!moving) {
+          return;
+        }
+        // music2.play();
+        moving = false;
+        this.animationStatus = false;
+        // this.choosePerson();
+        transform(targets.chaos, 250, 1);
+        objDeal(objectsss, 1.8);
+      },
+      //回到照片墙的状态
+      resets: function () {
+        moving = false;
+        camera.position.z = 1500;
+        camera.position.x = 0;
+        camera.position.y = 0;
+        camera.up.x = 0;//相机以哪个方向为上方
+        camera.up.y = 1;
+        camera.up.z = 0;
+
+        //图片重置方向
+        objectsss.rotation.y = 0;
+        objectsss.position.y = 20000;
+        objectsss.scale.set(1, 1, 1);
+        // 星空背景图重置
+        transform(targets.table, 400, 2);
+        // music.pause();
+        // this.ckPrice();
+      },
+      onBack() {
+        // 返回时先结束
+        this.closes()
+        this.resets()
+        window.parent.postMessage({
+          api: 'callBack',
+          loading: false,
+        }, '*');
+      }
+    },
+    created: function () {
+      // init();
+      // animate();
+
+      // getStar();
+      // this.ckPrice();
+    }
+  })
+</script>

+ 173 - 0
public/roll-call/js/CSS2DRenderer.js

@@ -0,0 +1,173 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.CSS2DObject = function ( element ) {
+
+	THREE.Object3D.call( this );
+
+	this.element = element;
+	this.element.style.position = 'absolute';
+
+	this.addEventListener( 'removed', function ( event ) {
+
+		if ( this.element.parentNode !== null ) {
+
+			this.element.parentNode.removeChild( this.element );
+
+		}
+
+	} );
+
+};
+
+THREE.CSS2DObject.prototype = Object.create( THREE.Object3D.prototype );
+THREE.CSS2DObject.prototype.constructor = THREE.CSS2DObject;
+
+//
+
+THREE.CSS2DRenderer = function () {
+
+	console.log( 'THREE.CSS2DRenderer', THREE.REVISION );
+
+	var _width, _height;
+	var _widthHalf, _heightHalf;
+
+	var vector = new THREE.Vector3();
+	var viewMatrix = new THREE.Matrix4();
+	var viewProjectionMatrix = new THREE.Matrix4();
+
+	var cache = {
+		objects: new WeakMap()
+	};
+
+	var domElement = document.createElement( 'div' );
+	domElement.style.overflow = 'hidden';
+
+	this.domElement = domElement;
+
+	this.getSize = function () {
+
+		return {
+			width: _width,
+			height: _height
+		};
+
+	};
+
+	this.setSize = function ( width, height ) {
+
+		_width = width;
+		_height = height;
+
+		_widthHalf = _width / 2;
+		_heightHalf = _height / 2;
+
+		domElement.style.width = width + 'px';
+		domElement.style.height = height + 'px';
+
+	};
+
+	var renderObject = function ( object, camera ) {
+
+		if ( object instanceof THREE.CSS2DObject ) {
+
+			vector.setFromMatrixPosition( object.matrixWorld );
+			vector.applyMatrix4( viewProjectionMatrix );
+
+			var element = object.element;
+			var style = 'translate(-50%,-50%) translate(' + ( vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - vector.y * _heightHalf + _heightHalf ) + 'px)';
+
+			element.style.WebkitTransform = style;
+			element.style.MozTransform = style;
+			element.style.oTransform = style;
+			element.style.transform = style;
+
+			var objectData = {
+				distanceToCameraSquared: getDistanceToSquared( camera, object )
+			};
+
+			cache.objects.set( object, objectData );
+
+			if ( element.parentNode !== domElement ) {
+
+				domElement.appendChild( element );
+
+			}
+
+		}
+
+		for ( var i = 0, l = object.children.length; i < l; i ++ ) {
+
+			renderObject( object.children[ i ], camera );
+
+		}
+
+	};
+
+	var getDistanceToSquared = function () {
+
+		var a = new THREE.Vector3();
+		var b = new THREE.Vector3();
+
+		return function ( object1, object2 ) {
+
+			a.setFromMatrixPosition( object1.matrixWorld );
+			b.setFromMatrixPosition( object2.matrixWorld );
+
+			return a.distanceToSquared( b );
+
+		};
+
+	}();
+
+	var filterAndFlatten = function ( scene ) {
+
+		var result = [];
+
+		scene.traverse( function ( object ) {
+
+			if ( object instanceof THREE.CSS2DObject ) result.push( object );
+
+		} );
+
+		return result;
+
+	};
+
+	var zOrder = function ( scene ) {
+
+		var sorted = filterAndFlatten( scene ).sort( function ( a, b ) {
+
+			var distanceA = cache.objects.get( a ).distanceToCameraSquared;
+			var distanceB = cache.objects.get( b ).distanceToCameraSquared;
+
+			return distanceA - distanceB;
+
+		} );
+
+		var zMax = sorted.length;
+
+		for ( var i = 0, l = sorted.length; i < l; i ++ ) {
+
+			sorted[ i ].element.style.zIndex = zMax - i;
+
+		}
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
+		viewMatrix.copy( camera.matrixWorldInverse );
+		viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, viewMatrix );
+
+		renderObject( scene, camera );
+		zOrder( scene );
+
+	};
+
+};

+ 243 - 0
public/roll-call/js/CSS3DRenderer.js

@@ -0,0 +1,243 @@
+/**
+ * Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.CSS3DObject = function ( element ) {
+
+	THREE.Object3D.call( this );
+
+	this.element = element;
+	this.element.style.position = 'absolute';
+
+	this.addEventListener( 'removed', function ( event ) {
+
+		if ( this.element.parentNode !== null ) {
+
+			this.element.parentNode.removeChild( this.element );
+
+		}
+
+	} );
+
+};
+
+THREE.CSS3DObject.prototype = Object.create( THREE.Object3D.prototype );
+
+THREE.CSS3DSprite = function ( element ) {
+
+	THREE.CSS3DObject.call( this, element );
+
+};
+
+THREE.CSS3DSprite.prototype = Object.create( THREE.CSS3DObject.prototype );
+
+//
+
+THREE.CSS3DRenderer = function () {
+
+	console.log( 'THREE.CSS3DRenderer', THREE.REVISION );
+
+	var _width, _height;
+	var _widthHalf, _heightHalf;
+
+	var matrix = new THREE.Matrix4();
+	
+	var cache = {
+		camera: { fov: 0, style: '' },
+		objects: {}
+	};
+
+	var domElement = document.createElement( 'div' );
+	domElement.style.overflow = 'hidden';
+
+	domElement.style.WebkitTransformStyle = 'preserve-3d';
+	domElement.style.MozTransformStyle = 'preserve-3d';
+	domElement.style.oTransformStyle = 'preserve-3d';
+	domElement.style.transformStyle = 'preserve-3d';
+
+	this.domElement = domElement;
+
+	var cameraElement = document.createElement( 'div' );
+
+	cameraElement.style.WebkitTransformStyle = 'preserve-3d';
+	cameraElement.style.MozTransformStyle = 'preserve-3d';
+	cameraElement.style.oTransformStyle = 'preserve-3d';
+	cameraElement.style.transformStyle = 'preserve-3d';
+
+	domElement.appendChild( cameraElement );
+
+	this.setClearColor = function () {
+
+	};
+
+	this.setSize = function ( width, height ) {
+
+		_width = width;
+		_height = height;
+
+		_widthHalf = _width / 2;
+		_heightHalf = _height / 2;
+
+		domElement.style.width = width + 'px';
+		domElement.style.height = height + 'px';
+
+		cameraElement.style.width = width + 'px';
+		cameraElement.style.height = height + 'px';
+
+	};
+
+	var epsilon = function ( value ) {
+
+		return Math.abs( value ) < 0.000001 ? 0 : value;
+
+	};
+
+	var getCameraCSSMatrix = function ( matrix ) {
+
+		var elements = matrix.elements;
+
+		return 'matrix3d(' +
+			epsilon( elements[ 0 ] ) + ',' +
+			epsilon( - elements[ 1 ] ) + ',' +
+			epsilon( elements[ 2 ] ) + ',' +
+			epsilon( elements[ 3 ] ) + ',' +
+			epsilon( elements[ 4 ] ) + ',' +
+			epsilon( - elements[ 5 ] ) + ',' +
+			epsilon( elements[ 6 ] ) + ',' +
+			epsilon( elements[ 7 ] ) + ',' +
+			epsilon( elements[ 8 ] ) + ',' +
+			epsilon( - elements[ 9 ] ) + ',' +
+			epsilon( elements[ 10 ] ) + ',' +
+			epsilon( elements[ 11 ] ) + ',' +
+			epsilon( elements[ 12 ] ) + ',' +
+			epsilon( - elements[ 13 ] ) + ',' +
+			epsilon( elements[ 14 ] ) + ',' +
+			epsilon( elements[ 15 ] ) +
+		')';
+
+	};
+
+	var getObjectCSSMatrix = function ( matrix ) {
+
+		var elements = matrix.elements;
+
+		return 'translate3d(-50%,-50%,0) matrix3d(' +
+			epsilon( elements[ 0 ] ) + ',' +
+			epsilon( elements[ 1 ] ) + ',' +
+			epsilon( elements[ 2 ] ) + ',' +
+			epsilon( elements[ 3 ] ) + ',' +
+			epsilon( - elements[ 4 ] ) + ',' +
+			epsilon( - elements[ 5 ] ) + ',' +
+			epsilon( - elements[ 6 ] ) + ',' +
+			epsilon( - elements[ 7 ] ) + ',' +
+			epsilon( elements[ 8 ] ) + ',' +
+			epsilon( elements[ 9 ] ) + ',' +
+			epsilon( elements[ 10 ] ) + ',' +
+			epsilon( elements[ 11 ] ) + ',' +
+			epsilon( elements[ 12 ] ) + ',' +
+			epsilon( elements[ 13 ] ) + ',' +
+			epsilon( elements[ 14 ] ) + ',' +
+			epsilon( elements[ 15 ] ) +
+		')';
+
+	};
+
+	var renderObject = function ( object, camera ) {
+
+		if ( object instanceof THREE.CSS3DObject ) {
+
+			var style;
+
+			if ( object instanceof THREE.CSS3DSprite ) {
+
+				// http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/
+
+				matrix.copy( camera.matrixWorldInverse );
+				matrix.transpose();
+				matrix.copyPosition( object.matrixWorld );
+				matrix.scale( object.scale );
+
+				matrix.elements[ 3 ] = 0;
+				matrix.elements[ 7 ] = 0;
+				matrix.elements[ 11 ] = 0;
+				matrix.elements[ 15 ] = 1;
+
+				style = getObjectCSSMatrix( matrix );
+
+			} else {
+
+				style = getObjectCSSMatrix( object.matrixWorld );
+
+			}
+
+			var element = object.element;
+			var cachedStyle = cache.objects[ object.id ];
+
+			if ( cachedStyle === undefined || cachedStyle !== style ) {
+
+				element.style.WebkitTransform = style;
+				element.style.MozTransform = style;
+				element.style.oTransform = style;
+				element.style.transform = style;
+
+				cache.objects[ object.id ] = style;
+
+			}
+
+			if ( element.parentNode !== cameraElement ) {
+
+				cameraElement.appendChild( element );
+
+			}
+
+		}
+
+		for ( var i = 0, l = object.children.length; i < l; i ++ ) {
+
+			renderObject( object.children[ i ], camera );
+
+		}
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		var fov = 0.5 / Math.tan( THREE.Math.degToRad( camera.fov * 0.5 ) ) * _height;
+
+		if ( cache.camera.fov !== fov ) {
+
+			domElement.style.WebkitPerspective = fov + "px";
+			domElement.style.MozPerspective = fov + "px";
+			domElement.style.oPerspective = fov + "px";
+			domElement.style.perspective = fov + "px";
+
+			cache.camera.fov = fov;
+
+		}
+
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+
+		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+
+		var style = "translate3d(0,0," + fov + "px)" + getCameraCSSMatrix( camera.matrixWorldInverse ) +
+			" translate3d(" + _widthHalf + "px," + _heightHalf + "px, 0)";
+
+		if ( cache.camera.style !== style ) {
+
+			cameraElement.style.WebkitTransform = style;
+			cameraElement.style.MozTransform = style;
+			cameraElement.style.oTransform = style;
+			cameraElement.style.transform = style;
+			
+			cache.camera.style = style;
+
+		}
+
+		renderObject( scene, camera );
+
+	};
+
+};

+ 287 - 0
public/roll-call/js/RaytracingRenderer.js

@@ -0,0 +1,287 @@
+/**
+ * RaytracingRenderer renders by raytracing it's scene. However, it does not
+ * compute the pixels itself but it hands off and coordinates the tasks for workers.
+ * The workers compute the pixel values and this renderer simply paints it to the Canvas.
+ *
+ * @author zz85 / http://github.com/zz85
+ */
+
+THREE.RaytracingRenderer = function ( parameters ) {
+
+	console.log( 'THREE.RaytracingRenderer', THREE.REVISION );
+
+	parameters = parameters || {};
+
+	var scope = this;
+	var pool = [];
+	var renderering = false;
+
+	var canvas = document.createElement( 'canvas' );
+	var context = canvas.getContext( '2d', {
+		alpha: parameters.alpha === true
+	} );
+
+	var canvasWidth, canvasHeight;
+
+	var clearColor = new THREE.Color( 0x000000 );
+
+	this.domElement = canvas;
+
+	this.autoClear = true;
+
+	var workers = parameters.workers;
+	var blockSize = parameters.blockSize || 64;
+	this.randomize = parameters.randomize;
+
+	var toRender = [], workerId = 0, sceneId = 0;
+
+	console.log( '%cSpinning off ' + workers + ' Workers ', 'font-size: 20px; background: black; color: white; font-family: monospace;' );
+
+	this.setWorkers = function ( w ) {
+
+		workers = w || navigator.hardwareConcurrency || 4;
+
+		while ( pool.length < workers ) {
+
+			var worker = new Worker( parameters.workerPath );
+			worker.id = workerId ++;
+
+			worker.onmessage = function ( e ) {
+
+				var data = e.data;
+
+				if ( ! data ) return;
+
+				if ( data.blockSize && sceneId == data.sceneId ) { // we match sceneId here to be sure
+
+					var imagedata = new ImageData( new Uint8ClampedArray( data.data ), data.blockSize, data.blockSize );
+					context.putImageData( imagedata, data.blockX, data.blockY );
+
+					// completed
+
+					console.log( 'Worker ' + this.id, data.time / 1000, ( Date.now() - reallyThen ) / 1000 + ' s' );
+
+					if ( pool.length > workers ) {
+
+						pool.splice( pool.indexOf( this ), 1 );
+						return this.terminate();
+
+					}
+
+					renderNext( this );
+
+				}
+
+			};
+
+			worker.color = new THREE.Color().setHSL( Math.random(), 0.8, 0.8 ).getHexString();
+			pool.push( worker );
+
+			updateSettings( worker );
+
+			if ( renderering ) {
+
+				worker.postMessage( {
+					scene: sceneJSON,
+					camera: cameraJSON,
+					annex: materials,
+					sceneId: sceneId
+				} );
+
+				renderNext( worker );
+
+			}
+
+		}
+
+		if ( ! renderering ) {
+
+			while ( pool.length > workers ) {
+
+				pool.pop().terminate();
+
+			}
+
+		}
+
+	};
+
+	this.setWorkers( workers );
+
+	this.setClearColor = function ( color /*, alpha */ ) {
+
+		clearColor.set( color );
+
+	};
+
+	this.setPixelRatio = function () {};
+
+	this.setSize = function ( width, height ) {
+
+		canvas.width = width;
+		canvas.height = height;
+
+		canvasWidth = canvas.width;
+		canvasHeight = canvas.height;
+
+		context.fillStyle = 'white';
+
+		pool.forEach( updateSettings );
+
+	};
+
+	this.setSize( canvas.width, canvas.height );
+
+	this.clear = function () {
+
+	};
+
+	//
+
+	var totalBlocks, xblocks, yblocks;
+
+	function updateSettings( worker ) {
+
+		worker.postMessage( {
+
+			init: [ canvasWidth, canvasHeight ],
+			worker: worker.id,
+			// workers: pool.length,
+			blockSize: blockSize
+
+		} );
+
+	}
+
+	function renderNext( worker ) {
+
+		if ( ! toRender.length ) {
+
+			renderering = false;
+			return scope.dispatchEvent( { type: "complete" } );
+
+		}
+
+		var current = toRender.pop();
+
+		var blockX = ( current % xblocks ) * blockSize;
+		var blockY = ( current / xblocks | 0 ) * blockSize;
+
+		worker.postMessage( {
+			render: true,
+			x: blockX,
+			y: blockY,
+			sceneId: sceneId
+		} );
+
+		context.fillStyle = '#' + worker.color;
+
+		context.fillRect( blockX, blockY, blockSize, blockSize );
+
+	}
+
+	var materials = {};
+
+	var sceneJSON, cameraJSON, reallyThen;
+
+	// additional properties that were not serialize automatically
+
+	var _annex = {
+
+		mirror: 1,
+		reflectivity: 1,
+		refractionRatio: 1,
+		glass: 1
+
+	};
+
+	function serializeObject( o ) {
+
+		var mat = o.material;
+
+		if ( ! mat || mat.uuid in materials ) return;
+
+		var props = {};
+		for ( var m in _annex ) {
+
+			if ( mat[ m ] !== undefined ) {
+
+				props[ m ] = mat[ m ];
+
+			}
+
+		}
+
+		materials[ mat.uuid ] = props;
+
+	}
+
+	this.render = function ( scene, camera ) {
+
+		renderering = true;
+
+		// update scene graph
+
+		if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
+
+		// update camera matrices
+
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
+
+		sceneJSON = scene.toJSON();
+		cameraJSON = camera.toJSON();
+		++ sceneId;
+
+		scene.traverse( serializeObject );
+
+		pool.forEach( function ( worker ) {
+
+			worker.postMessage( {
+				scene: sceneJSON,
+				camera: cameraJSON,
+				annex: materials,
+				sceneId: sceneId
+			} );
+
+		} );
+
+		context.clearRect( 0, 0, canvasWidth, canvasHeight );
+		reallyThen = Date.now();
+
+		xblocks = Math.ceil( canvasWidth / blockSize );
+		yblocks = Math.ceil( canvasHeight / blockSize );
+		totalBlocks = xblocks * yblocks;
+
+		toRender = [];
+
+		for ( var i = 0; i < totalBlocks; i ++ ) {
+
+			toRender.push( i );
+
+		}
+
+
+		// Randomize painting :)
+
+		if ( scope.randomize ) {
+
+			for ( var i = 0; i < totalBlocks; i ++ ) {
+
+				var swap = Math.random() * totalBlocks | 0;
+				var tmp = toRender[ swap ];
+				toRender[ swap ] = toRender[ i ];
+				toRender[ i ] = tmp;
+
+			}
+
+		}
+
+
+		pool.forEach( renderNext );
+
+	};
+
+};
+
+Object.assign( THREE.RaytracingRenderer.prototype, THREE.EventDispatcher.prototype );

+ 611 - 0
public/roll-call/js/TrackballControls.js

@@ -0,0 +1,611 @@
+/**
+ * @author Eberhard Graether / http://egraether.com/
+ * @author Mark Lundin 	/ http://mark-lundin.com
+ */
+
+THREE.TrackballControls = function ( object, domElement ) {
+
+	var _this = this;
+	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
+
+	this.object = object;
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+	// API
+
+	this.enabled = true;
+
+	this.screen = { left: 0, top: 0, width: 0, height: 0 };
+
+	this.rotateSpeed = 1.0;
+	this.zoomSpeed = 1.2;
+	this.panSpeed = 0.3;
+
+	this.noRotate = false;
+	this.noZoom = false;
+	this.noPan = false;
+	this.noRoll = false;
+
+	this.staticMoving = false;
+	this.dynamicDampingFactor = 0.2;
+
+	this.minDistance = 0;
+	this.maxDistance = Infinity;
+
+	this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
+
+	// internals
+
+	this.target = new THREE.Vector3();
+
+	var EPS = 0.000001;
+
+	var lastPosition = new THREE.Vector3();
+
+	var _state = STATE.NONE,
+	_prevState = STATE.NONE,
+
+	_eye = new THREE.Vector3(),
+
+	_rotateStart = new THREE.Vector3(),
+	_rotateEnd = new THREE.Vector3(),
+
+	_zoomStart = new THREE.Vector2(),
+	_zoomEnd = new THREE.Vector2(),
+
+	_touchZoomDistanceStart = 0,
+	_touchZoomDistanceEnd = 0,
+
+	_panStart = new THREE.Vector2(),
+	_panEnd = new THREE.Vector2();
+
+	// for reset
+
+	this.target0 = this.target.clone();
+	this.position0 = this.object.position.clone();
+	this.up0 = this.object.up.clone();
+
+	// events
+
+	var changeEvent = { type: 'change' };
+	var startEvent = { type: 'start'};
+	var endEvent = { type: 'end'};
+
+
+	// methods
+
+	this.handleResize = function () {
+
+		if ( this.domElement === document ) {
+
+			this.screen.left = 0;
+			this.screen.top = 0;
+			this.screen.width = window.innerWidth;
+			this.screen.height = window.innerHeight;
+
+		} else {
+
+			var box = this.domElement.getBoundingClientRect();
+			// adjustments come from similar code in the jquery offset() function
+			var d = this.domElement.ownerDocument.documentElement;
+			this.screen.left = box.left + window.pageXOffset - d.clientLeft;
+			this.screen.top = box.top + window.pageYOffset - d.clientTop;
+			this.screen.width = box.width;
+			this.screen.height = box.height;
+
+		}
+
+	};
+
+	this.handleEvent = function ( event ) {
+
+		if ( typeof this[ event.type ] == 'function' ) {
+
+			this[ event.type ]( event );
+
+		}
+
+	};
+
+	var getMouseOnScreen = ( function () {
+
+		var vector = new THREE.Vector2();
+
+		return function ( pageX, pageY ) {
+
+			vector.set(
+				( pageX - _this.screen.left ) / _this.screen.width,
+				( pageY - _this.screen.top ) / _this.screen.height
+			);
+
+			return vector;
+
+		};
+
+	}() );
+
+	var getMouseProjectionOnBall = ( function () {
+
+		var vector = new THREE.Vector3();
+		var objectUp = new THREE.Vector3();
+		var mouseOnBall = new THREE.Vector3();
+
+		return function ( pageX, pageY ) {
+
+			mouseOnBall.set(
+				( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
+				( _this.screen.height * 0.5 + _this.screen.top - pageY ) / (_this.screen.height*.5),
+				0.0
+			);
+
+			var length = mouseOnBall.length();
+
+			if ( _this.noRoll ) {
+
+				if ( length < Math.SQRT1_2 ) {
+
+					mouseOnBall.z = Math.sqrt( 1.0 - length*length );
+
+				} else {
+
+					mouseOnBall.z = .5 / length;
+					
+				}
+
+			} else if ( length > 1.0 ) {
+
+				mouseOnBall.normalize();
+
+			} else {
+
+				mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+
+			}
+
+			_eye.copy( _this.object.position ).sub( _this.target );
+
+			vector.copy( _this.object.up ).setLength( mouseOnBall.y )
+			vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
+			vector.add( _eye.setLength( mouseOnBall.z ) );
+
+			return vector;
+
+		};
+
+	}() );
+
+	this.rotateCamera = (function(){
+
+		var axis = new THREE.Vector3(),
+			quaternion = new THREE.Quaternion();
+
+
+		return function () {
+
+			var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
+
+			if ( angle ) {
+
+				axis.crossVectors( _rotateStart, _rotateEnd ).normalize();
+
+				angle *= _this.rotateSpeed;
+
+				quaternion.setFromAxisAngle( axis, -angle );
+
+				_eye.applyQuaternion( quaternion );
+				_this.object.up.applyQuaternion( quaternion );
+
+				_rotateEnd.applyQuaternion( quaternion );
+
+				if ( _this.staticMoving ) {
+
+					_rotateStart.copy( _rotateEnd );
+
+				} else {
+
+					quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
+					_rotateStart.applyQuaternion( quaternion );
+
+				}
+
+			}
+		}
+
+	}());
+
+	this.zoomCamera = function () {
+
+		if ( _state === STATE.TOUCH_ZOOM_PAN ) {
+
+			var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
+			_touchZoomDistanceStart = _touchZoomDistanceEnd;
+			_eye.multiplyScalar( factor );
+
+		} else {
+
+			var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
+
+			if ( factor !== 1.0 && factor > 0.0 ) {
+
+				_eye.multiplyScalar( factor );
+
+				if ( _this.staticMoving ) {
+
+					_zoomStart.copy( _zoomEnd );
+
+				} else {
+
+					_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
+
+				}
+
+			}
+
+		}
+
+	};
+
+	this.panCamera = (function(){
+
+		var mouseChange = new THREE.Vector2(),
+			objectUp = new THREE.Vector3(),
+			pan = new THREE.Vector3();
+
+		return function () {
+
+			mouseChange.copy( _panEnd ).sub( _panStart );
+
+			if ( mouseChange.lengthSq() ) {
+
+				mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
+
+				pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
+				pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
+
+				_this.object.position.add( pan );
+				_this.target.add( pan );
+
+				if ( _this.staticMoving ) {
+
+					_panStart.copy( _panEnd );
+
+				} else {
+
+					_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
+
+				}
+
+			}
+		}
+
+	}());
+
+	this.checkDistances = function () {
+
+		if ( !_this.noZoom || !_this.noPan ) {
+
+			if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
+
+				_this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );
+
+			}
+
+			if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
+
+				_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );
+
+			}
+
+		}
+
+	};
+
+	this.update = function () {
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		if ( !_this.noRotate ) {
+
+			_this.rotateCamera();
+
+		}
+
+		if ( !_this.noZoom ) {
+
+			_this.zoomCamera();
+
+		}
+
+		if ( !_this.noPan ) {
+
+			_this.panCamera();
+
+		}
+
+		_this.object.position.addVectors( _this.target, _eye );
+
+		_this.checkDistances();
+
+		_this.object.lookAt( _this.target );
+
+		if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {
+
+			_this.dispatchEvent( changeEvent );
+
+			lastPosition.copy( _this.object.position );
+
+		}
+
+	};
+
+	this.reset = function () {
+
+		_state = STATE.NONE;
+		_prevState = STATE.NONE;
+
+		_this.target.copy( _this.target0 );
+		_this.object.position.copy( _this.position0 );
+		_this.object.up.copy( _this.up0 );
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		_this.object.lookAt( _this.target );
+
+		_this.dispatchEvent( changeEvent );
+
+		lastPosition.copy( _this.object.position );
+
+	};
+
+	// listeners
+
+	function keydown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		window.removeEventListener( 'keydown', keydown );
+
+		_prevState = _state;
+
+		if ( _state !== STATE.NONE ) {
+
+			return;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
+
+			_state = STATE.ROTATE;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
+
+			_state = STATE.ZOOM;
+
+		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
+
+			_state = STATE.PAN;
+
+		}
+
+	}
+
+	function keyup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		_state = _prevState;
+
+		window.addEventListener( 'keydown', keydown, false );
+
+	}
+
+	function mousedown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.NONE ) {
+
+			_state = event.button;
+
+		}
+
+		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+
+			_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
+			_rotateEnd.copy( _rotateStart );
+
+		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+
+			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_zoomEnd.copy(_zoomStart);
+
+		} else if ( _state === STATE.PAN && !_this.noPan ) {
+
+			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_panEnd.copy(_panStart)
+
+		}
+		// bai
+//		document.addEventListener( 'mousemove', mousemove, false );
+//		document.addEventListener( 'mouseup', mouseup, false );
+
+		_this.dispatchEvent( startEvent );
+
+	}
+
+	function mousemove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+
+			_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
+
+		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+			
+			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+
+		} else if ( _state === STATE.PAN && !_this.noPan ) {
+			//把右键位移关掉了
+//			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+
+		}
+
+	}
+
+	function mouseup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		_state = STATE.NONE;
+
+		document.removeEventListener( 'mousemove', mousemove );
+		document.removeEventListener( 'mouseup', mouseup );
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function mousewheel( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		var delta = 0;
+
+		if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
+
+			delta = event.wheelDelta / 40;
+
+		} else if ( event.detail ) { // Firefox
+
+			delta = - event.detail / 3;
+
+		}
+
+		_zoomStart.y += delta * 0.01;
+		_this.dispatchEvent( startEvent );
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function touchstart( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_state = STATE.TOUCH_ROTATE;
+				_rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateEnd.copy( _rotateStart );
+				break;
+
+			case 2:
+				_state = STATE.TOUCH_ZOOM_PAN;
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panStart.copy( getMouseOnScreen( x, y ) );
+				_panEnd.copy( _panStart );
+				break;
+
+			default:
+				_state = STATE.NONE;
+
+		}
+		_this.dispatchEvent( startEvent );
+
+
+	}
+
+	function touchmove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				break;
+
+			case 2:
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
+				break;
+
+			default:
+				_state = STATE.NONE;
+
+		}
+
+	}
+
+	function touchend( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateStart.copy( _rotateEnd );
+				break;
+
+			case 2:
+				_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
+				_panStart.copy( _panEnd );
+				break;
+
+		}
+
+		_state = STATE.NONE;
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
+	// bai
+	// this.domElement.addEventListener( 'mousewheel', mousewheel, false );
+	// this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
+
+	this.domElement.addEventListener( 'touchstart', touchstart, false );
+	this.domElement.addEventListener( 'touchend', touchend, false );
+	this.domElement.addEventListener( 'touchmove', touchmove, false );
+
+//	window.addEventListener( 'keydown', keydown, false );
+//	window.addEventListener( 'keyup', keyup, false );
+
+	this.handleResize();
+
+	// force an update at start
+	this.update();
+
+};
+
+THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );

+ 11 - 0
public/roll-call/js/data.js

@@ -0,0 +1,11 @@
+function getData() {
+  return (data = [
+    { name: '小白', img: './img/1.webp' },
+    { img: './img/2.webp', name: '小黑' },
+    { img: './img/2.webp', name: '小黑' },
+    { img: './img/3.webp', name: '小明' },
+    { img: './img/4.webp', name: '晓得' },
+    { img: './img/4.webp', name: '晓得' },
+    { img: './img/5.webp', name: '小李' }
+  ]);
+}

+ 128 - 0
public/roll-call/js/star.js

@@ -0,0 +1,128 @@
+function getStar() {
+  var canvas = document.createElement('canvas'),
+    ctx = canvas.getContext('2d'),
+    w = (canvas.width = window.innerWidth * 2),
+    h = (canvas.height = window.innerHeight * 2),
+    hue = 217,
+    stars = [],
+    count = 0,
+    maxStars = 350; //星星数量
+
+  //放背景图
+
+  var canvas2 = document.createElement('canvas'),
+    ctx2 = canvas2.getContext('2d');
+  canvas2.width = 100;
+  canvas2.height = 100;
+  var half = canvas2.width / 2,
+    gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half);
+  gradient2.addColorStop(0.025, '#CCC');
+  gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
+  gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');
+  gradient2.addColorStop(1, 'transparent');
+
+  ctx2.fillStyle = gradient2;
+  ctx2.beginPath();
+  ctx2.arc(half, half, half, 0, Math.PI * 2);
+  ctx2.fill();
+
+  // End cache
+
+  function random(min, max) {
+    if (arguments.length < 2) {
+      max = min;
+      min = 0;
+    }
+
+    if (min > max) {
+      var hold = max;
+      max = min;
+      min = hold;
+    }
+
+    return Math.floor(Math.random() * (max - min + 1)) + min;
+  }
+
+  function maxOrbit(x, y) {
+    var max = Math.max(x, y),
+      diameter = Math.round(Math.sqrt(max * max + max * max));
+    return diameter / 2;
+    //星星移动范围,值越大范围越小,
+  }
+
+  var Star = function () {
+    this.orbitRadius = random(maxOrbit(w, h));
+    this.radius = random(60, this.orbitRadius) / 8;
+    //星星大小
+    this.orbitX = w / 2;
+    this.orbitY = h / 2;
+    this.timePassed = random(0, maxStars);
+    this.speed = random(this.orbitRadius) / 150000;
+    //星星移动速度
+    this.alpha = random(2, 10) / 10;
+
+    count++;
+    stars[count] = this;
+  };
+
+  Star.prototype.draw = function () {
+    var x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
+      y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
+      twinkle = random(10);
+
+    if (twinkle === 1 && this.alpha > 0) {
+      this.alpha -= 0.05;
+    } else if (twinkle === 2 && this.alpha < 1) {
+      this.alpha += 0.05;
+    }
+
+    ctx.globalAlpha = this.alpha;
+    ctx.drawImage(
+      canvas2,
+      x - this.radius / 2,
+      y - this.radius / 2,
+      this.radius,
+      this.radius
+    );
+    this.timePassed += this.speed;
+  };
+
+  for (var i = 0; i < maxStars; i++) {
+    new Star();
+  }
+
+  function animation() {
+    ctx.globalCompositeOperation = 'source-over';
+    ctx.globalAlpha = 0.5; //尾巴
+    ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)';
+    ctx.fillRect(0, 0, w, h);
+
+    ctx.globalCompositeOperation = 'lighter';
+    for (var i = 1, l = stars.length; i < l; i++) {
+      stars[i].draw();
+    }
+
+    window.requestAnimationFrame(animation);
+  }
+
+  var canvasBoxs = document.createElement('div');
+  var images = document.createElement('img');
+  images.src = './img/starBg.jpg';
+  images.style.opacity = '0.4';
+  images.style.width = '100%';
+  images.style.height = '1280px';
+  images.style.zIndex = '22';
+  images.style.position = 'absolute';
+  images.style.background = '#000';
+  canvasBoxs.appendChild(images);
+  canvas.style.zIndex = '23';
+  canvasBoxs.appendChild(canvas);
+  starBG = new THREE.CSS3DObject(canvasBoxs);
+  starBG.position.x = 0;
+  starBG.position.y = 0;
+  starBG.position.z = -5000;
+  var scal = (window.innerWidth + 10000) / window.innerWidth / 2;
+  starBG.scale.set(scal, scal, scal);
+  scene.add(starBG);
+  animation();
+}

+ 5 - 0
public/roll-call/js/stats.min.js

@@ -0,0 +1,5 @@
+// stats.js - http://github.com/mrdoob/stats.js
+var Stats=function(){function h(a){c.appendChild(a.dom);return a}function k(a){for(var d=0;d<c.children.length;d++)c.children[d].style.display=d===a?"block":"none";l=a}var l=0,c=document.createElement("div");c.style.cssText="position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";c.addEventListener("click",function(a){a.preventDefault();k(++l%c.children.length)},!1);var g=(performance||Date).now(),e=g,a=0,r=h(new Stats.Panel("FPS","#0ff","#002")),f=h(new Stats.Panel("MS","#0f0","#020"));
+if(self.performance&&self.performance.memory)var t=h(new Stats.Panel("MB","#f08","#201"));k(0);return{REVISION:16,dom:c,addPanel:h,showPanel:k,begin:function(){g=(performance||Date).now()},end:function(){a++;var c=(performance||Date).now();f.update(c-g,200);if(c>e+1E3&&(r.update(1E3*a/(c-e),100),e=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){g=this.end()},domElement:c,setMode:k}};
+Stats.Panel=function(h,k,l){var c=Infinity,g=0,e=Math.round,a=e(window.devicePixelRatio||1),r=80*a,f=48*a,t=3*a,u=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=f;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,f);b.fillStyle=k;b.fillText(h,t,u);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(f,
+v){c=Math.min(c,f);g=Math.max(g,f);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=k;b.fillText(e(f)+" "+h+" ("+e(c)+"-"+e(g)+")",t,u);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,e((1-f/v)*p))}}};"object"===typeof module&&(module.exports=Stats);

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 372 - 0
public/roll-call/js/three.min.js


+ 13 - 0
public/roll-call/js/tween.min.js

@@ -0,0 +1,13 @@
+// tween.js - http://github.com/sole/tween.js
+'use strict';var TWEEN=TWEEN||function(){var a=[];return{REVISION:"7",getAll:function(){return a},removeAll:function(){a=[]},add:function(c){a.push(c)},remove:function(c){c=a.indexOf(c);-1!==c&&a.splice(c,1)},update:function(c){if(0===a.length)return!1;for(var b=0,d=a.length,c=void 0!==c?c:Date.now();b<d;)a[b].update(c)?b++:(a.splice(b,1),d--);return!0}}}();
+TWEEN.Tween=function(a){var c={},b={},d=1E3,e=0,f=null,h=TWEEN.Easing.Linear.None,r=TWEEN.Interpolation.Linear,k=[],l=null,m=!1,n=null,p=null;this.to=function(a,c){null!==c&&(d=c);b=a;return this};this.start=function(d){TWEEN.add(this);m=!1;f=void 0!==d?d:Date.now();f+=e;for(var g in b)if(null!==a[g]){if(b[g]instanceof Array){if(0===b[g].length)continue;b[g]=[a[g]].concat(b[g])}c[g]=a[g]}return this};this.stop=function(){TWEEN.remove(this);return this};this.delay=function(a){e=a;return this};this.easing=
+function(a){h=a;return this};this.interpolation=function(a){r=a;return this};this.chain=function(){k=arguments;return this};this.onStart=function(a){l=a;return this};this.onUpdate=function(a){n=a;return this};this.onComplete=function(a){p=a;return this};this.update=function(e){if(e<f)return!0;!1===m&&(null!==l&&l.call(a),m=!0);var g=(e-f)/d,g=1<g?1:g,i=h(g),j;for(j in c){var s=c[j],q=b[j];a[j]=q instanceof Array?r(q,i):s+(q-s)*i}null!==n&&n.call(a,i);if(1==g){null!==p&&p.call(a);g=0;for(i=k.length;g<
+i;g++)k[g].start(e);return!1}return!0}};
+TWEEN.Easing={Linear:{None:function(a){return a}},Quadratic:{In:function(a){return a*a},Out:function(a){return a*(2-a)},InOut:function(a){return 1>(a*=2)?0.5*a*a:-0.5*(--a*(a-2)-1)}},Cubic:{In:function(a){return a*a*a},Out:function(a){return--a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a:0.5*((a-=2)*a*a+2)}},Quartic:{In:function(a){return a*a*a*a},Out:function(a){return 1- --a*a*a*a},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a:-0.5*((a-=2)*a*a*a-2)}},Quintic:{In:function(a){return a*a*a*
+a*a},Out:function(a){return--a*a*a*a*a+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*a*a*a:0.5*((a-=2)*a*a*a*a+2)}},Sinusoidal:{In:function(a){return 1-Math.cos(a*Math.PI/2)},Out:function(a){return Math.sin(a*Math.PI/2)},InOut:function(a){return 0.5*(1-Math.cos(Math.PI*a))}},Exponential:{In:function(a){return 0===a?0:Math.pow(1024,a-1)},Out:function(a){return 1===a?1:1-Math.pow(2,-10*a)},InOut:function(a){return 0===a?0:1===a?1:1>(a*=2)?0.5*Math.pow(1024,a-1):0.5*(-Math.pow(2,-10*(a-1))+2)}},Circular:{In:function(a){return 1-
+Math.sqrt(1-a*a)},Out:function(a){return Math.sqrt(1- --a*a)},InOut:function(a){return 1>(a*=2)?-0.5*(Math.sqrt(1-a*a)-1):0.5*(Math.sqrt(1-(a-=2)*a)+1)}},Elastic:{In:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return-(b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4))},Out:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return b*Math.pow(2,-10*a)*Math.sin((a-c)*
+2*Math.PI/0.4)+1},InOut:function(a){var c,b=0.1;if(0===a)return 0;if(1===a)return 1;!b||1>b?(b=1,c=0.1):c=0.4*Math.asin(1/b)/(2*Math.PI);return 1>(a*=2)?-0.5*b*Math.pow(2,10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4):0.5*b*Math.pow(2,-10*(a-=1))*Math.sin((a-c)*2*Math.PI/0.4)+1}},Back:{In:function(a){return a*a*(2.70158*a-1.70158)},Out:function(a){return--a*a*(2.70158*a+1.70158)+1},InOut:function(a){return 1>(a*=2)?0.5*a*a*(3.5949095*a-2.5949095):0.5*((a-=2)*a*(3.5949095*a+2.5949095)+2)}},Bounce:{In:function(a){return 1-
+TWEEN.Easing.Bounce.Out(1-a)},Out:function(a){return a<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+0.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+0.9375:7.5625*(a-=2.625/2.75)*a+0.984375},InOut:function(a){return 0.5>a?0.5*TWEEN.Easing.Bounce.In(2*a):0.5*TWEEN.Easing.Bounce.Out(2*a-1)+0.5}}};
+TWEEN.Interpolation={Linear:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.Linear;return 0>c?f(a[0],a[1],d):1<c?f(a[b],a[b-1],b-d):f(a[e],a[e+1>b?b:e+1],d-e)},Bezier:function(a,c){var b=0,d=a.length-1,e=Math.pow,f=TWEEN.Interpolation.Utils.Bernstein,h;for(h=0;h<=d;h++)b+=e(1-c,d-h)*e(c,h)*a[h]*f(d,h);return b},CatmullRom:function(a,c){var b=a.length-1,d=b*c,e=Math.floor(d),f=TWEEN.Interpolation.Utils.CatmullRom;return a[0]===a[b]?(0>c&&(e=Math.floor(d=b*(1+c))),f(a[(e-
+1+b)%b],a[e],a[(e+1)%b],a[(e+2)%b],d-e)):0>c?a[0]-(f(a[0],a[0],a[1],a[1],-d)-a[0]):1<c?a[b]-(f(a[b],a[b],a[b-1],a[b-1],d-b)-a[b]):f(a[e?e-1:0],a[e],a[b<e+1?b:e+1],a[b<e+2?b:e+2],d-e)},Utils:{Linear:function(a,c,b){return(c-a)*b+a},Bernstein:function(a,c){var b=TWEEN.Interpolation.Utils.Factorial;return b(a)/b(c)/b(a-c)},Factorial:function(){var a=[1];return function(c){var b=1,d;if(a[c])return a[c];for(d=c;1<d;d--)b*=d;return a[c]=b}}(),CatmullRom:function(a,c,b,d,e){var a=0.5*(b-a),d=0.5*(d-c),f=
+e*e;return(2*c-2*b+a+d)*e*f+(-3*c+3*b-2*a-d)*f+a*e+c}}};

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 5 - 0
public/roll-call/js/vue.min.js


BIN
public/roll-call/music/04-抽奖音乐 猪突猛進.mp3


BIN
public/roll-call/music/9629.mp3


+ 1 - 1
public/version.json

@@ -1 +1 @@
-{"version":1709737052944}
+{ "version": 1709737052944 }

+ 120 - 0
src/views/attend-class/component/roll-call/pen.module.less

@@ -0,0 +1,120 @@
+.pen {
+  position: fixed;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  top: 0;
+  z-index: 501;
+}
+
+.open {
+  display: block;
+}
+
+.whiteboard {
+  background: #fff !important;
+}
+
+.hide {
+  display: none;
+}
+
+.iframe {
+  display: block;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+.dely {
+  opacity: 0;
+}
+
+.rightItem {
+  position: absolute;
+  right: 30px;
+  bottom: 0;
+  bottom: constant(safe-area-inset-bottom);
+  bottom: env(safe-area-inset-bottom);
+  height: 78Px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  svg {
+    width: 28Px;
+    height: 28Px;
+  }
+
+  // position: absolute;
+  // top: 40px;
+  // left: 40px;
+  // width: 187px;
+  // height: 65px;
+  // cursor: pointer;
+  // transition: all 0.5s;
+
+  // img {
+  //   width: 100%;
+  //   height: 100%;
+  //   -moz-user-select: none;
+  //   /* 火狐浏览器 */
+  //   -webkit-user-drag: none;
+  //   /* 谷歌、Safari和Opera浏览器 */
+  //   -webkit-user-select: none;
+  //   /* 谷歌、Safari和Opera浏览器 */
+  //   -ms-user-select: none;
+  //   /* IE10+浏览器 */
+  //   user-select: none;
+  //   /* 通用 */
+  //   -webkit-touch-callout: none;
+  //   /* iOS Safari */
+  // }
+
+}
+
+.img {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  display: block;
+}
+
+
+.removeVisiable {
+  width: 432px;
+
+  :global {
+    .n-card-header {
+      font-size: max(22px, 16Px);
+    }
+  }
+
+  .studentRemove {
+    padding: 20px 40px 0;
+
+    p {
+      font-size: max(18px, 14Px);
+      color: #777777;
+      line-height: 30px;
+      text-align: center;
+
+      span {
+        color: #EA4132;
+      }
+    }
+  }
+
+  .btnGroupModal {
+    padding: 32px 0;
+
+    :global {
+      .n-button {
+        height: 47px;
+        min-width: 156px;
+      }
+    }
+  }
+}

+ 131 - 0
src/views/attend-class/component/roll-call/pen.tsx

@@ -0,0 +1,131 @@
+import { defineComponent, toRefs, ref, PropType, reactive } from 'vue';
+import styles from './pen.module.less';
+import { ToolType } from '../../index';
+import { NButton, NModal, NSpace } from 'naive-ui';
+
+export default defineComponent({
+  name: 'pen-page',
+  props: {
+    show: {
+      type: Boolean,
+      default: false
+    },
+    type: {
+      type: String as PropType<ToolType>,
+      default: 'pen'
+    },
+    close: {
+      type: Function,
+      default: () => ({})
+    }
+  },
+  setup(props) {
+    const { show, type } = toRefs(props);
+    // const modelAttendStatus = ref(false);
+    const modal = reactive({
+      status: false,
+      title: type.value === 'pen' ? '退出批注' : '退出白板',
+      content:
+        type.value === 'pen' ? '确认是否退出批注?' : '确认是否退出白板?'
+    });
+    const firstRender = ref(true);
+    const origin = /(localhost|192)/.test(location.host)
+      ? // ? 'https://test.lexiaoya.cn/'
+        'http://localhost:5002/'
+      : location.origin;
+    let src = `${origin}/classroom-whiteboard?t=${+new Date()}`;
+
+    console.log(props.type, '121212');
+    if (props.type === 'call') {
+      src = `${origin}/roll-call/index.html?t=${+new Date()}`;
+    }
+    return () => (
+      <div
+        class={[
+          styles.pen,
+          type.value === 'whiteboard' ? styles.whiteboard : '',
+          firstRender.value ? styles.dely : '',
+          show.value ? styles.open : styles.hide
+        ]}>
+        <iframe
+          class={styles.iframe}
+          frameborder="0"
+          width="100vw"
+          height="100vh"
+          src={src}
+          onLoad={() => {
+            firstRender.value = false;
+          }}></iframe>
+        <div class={styles.rightItem} onClick={() => (modal.status = true)}>
+          <svg
+            width="28px"
+            height="28px"
+            viewBox="0 0 34 34"
+            version="1.1"
+            xmlns="http://www.w3.org/2000/svg">
+            <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+              <g
+                transform="translate(-1842.000000, -1016.000000)"
+                stroke="#FFFFFF">
+                <g transform="translate(980.000000, 1006.000000)">
+                  <g transform="translate(862.000000, 10.000000)">
+                    <g transform="translate(4.000000, 5.000000)">
+                      <g
+                        transform="translate(8.058241, 5.009812)"
+                        fill="#FFFFFF"
+                        fill-rule="nonzero"
+                        stroke-width="0.3">
+                        <path d="M11.6084252,-0.15 C11.9880433,-0.15 12.3676614,-0.00518057514 12.6573002,0.284458275 L12.6573002,0.284458275 L18.3141545,5.94131252 C18.6037933,6.23095137 18.7486128,6.61056948 18.7486128,6.99018758 C18.7486128,7.36980569 18.6037933,7.74942379 18.3141545,8.03906264 L18.3141545,8.03906264 L12.6573002,13.6959169 C12.3676614,13.9855557 11.9880433,14.1303752 11.6084252,14.1303752 C11.2288071,14.1303752 10.849189,13.9855557 10.5595501,13.6959169 C10.2699113,13.406278 10.1250918,13.0266599 10.1250918,12.6470418 C10.1250918,12.2674237 10.2699113,11.8878056 10.5595368,11.5981801 L10.5595368,11.5981801 L13.6839174,8.47301484 L1.33333333,8.47352092 C0.923722144,8.47352092 0.552888811,8.30749318 0.284458275,8.03906264 C0.0160277386,7.77063211 -0.15,7.39979877 -0.15,6.99018758 C-0.15,6.61194961 -0.00841906355,6.26678575 0.224608408,6.00476938 C0.462154637,5.73767211 0.794779811,5.55707713 1.16932931,5.51583101 L1.16932931,5.51583101 L13.6841044,5.50627626 L10.5595501,2.38220839 C10.2699113,2.09256954 10.1250918,1.71295144 10.1250918,1.33333333 C10.1250918,0.953715229 10.2699113,0.574097124 10.5595501,0.284458275 C10.849189,-0.00518057514 11.2288071,-0.15 11.6084252,-0.15 Z"></path>
+                      </g>
+                      <path
+                        d="M15,24 L3,24 C1.34314575,24 -1.1293615e-15,22.6568542 0,21 L0,3 C-2.02906125e-16,1.34314575 1.34314575,3.04359188e-16 3,0 L15,0 L15,0"
+                        stroke-width="3.5"
+                        stroke-linecap="round"
+                        stroke-linejoin="round"></path>
+                    </g>
+                  </g>
+                </g>
+              </g>
+            </g>
+          </svg>
+        </div>
+
+        {/* 布置作业 */}
+        <NModal
+          transformOrigin="center"
+          v-model:show={modal.status}
+          preset="card"
+          // class={styles.attendClassModal}
+          title={modal.title}
+          class={['modalTitle', styles.removeVisiable]}>
+          <div class={styles.studentRemove}>
+            <p>{modal.content}</p>
+            {/* <div class={styles.modelAttendContent}>
+              {data.modalAttendMessage}
+            </div> */}
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton
+                type="default"
+                round
+                onClick={() => {
+                  modal.status = false;
+                }}>
+                取消
+              </NButton>
+              <NButton
+                type="primary"
+                round
+                onClick={() => {
+                  // data.modelTrainStatus = true;
+                  modal.status = false;
+                  props.close();
+                }}>
+                确认
+              </NButton>
+            </NSpace>
+          </div>
+        </NModal>
+      </div>
+    );
+  }
+});

+ 50 - 32
src/views/attend-class/component/tools/pen.tsx

@@ -17,6 +17,10 @@ export default defineComponent({
     close: {
       type: Function,
       default: () => ({})
+    },
+    callStudents: {
+      type: Array,
+      default: () => []
     }
   },
   setup(props) {
@@ -30,10 +34,14 @@ export default defineComponent({
     });
     const firstRender = ref(true);
     const origin = /(localhost|192)/.test(location.host)
-      ? 'https://test.lexiaoya.cn/'
-      : // 'http://localhost:3000/'
-        location.origin;
-    const src = `${origin}/classroom-whiteboard?t=${+new Date()}`;
+      ? // ? 'https://test.lexiaoya.cn/'
+        'http://localhost:5002/'
+      : location.origin;
+    let src = `${origin}/classroom-whiteboard?t=${+new Date()}`;
+
+    if (props.type === 'call') {
+      src = `${origin}/roll-call/index.html?t=${+new Date()}`;
+    }
 
     return () => (
       <div
@@ -45,46 +53,56 @@ export default defineComponent({
         ]}>
         <iframe
           class={styles.iframe}
+          id="penIframeRef"
           frameborder="0"
           width="100vw"
           height="100vh"
           src={src}
           onLoad={() => {
             firstRender.value = false;
+
+            if (props.type === 'call') {
+              const iframeRef: any = document.getElementById('penIframeRef');
+              if (iframeRef && iframeRef.contentWindow.renderData) {
+                iframeRef.contentWindow.renderData(props.callStudents);
+              }
+            }
           }}></iframe>
-        <div class={styles.rightItem} onClick={() => (modal.status = true)}>
-          <svg
-            width="28px"
-            height="28px"
-            viewBox="0 0 34 34"
-            version="1.1"
-            xmlns="http://www.w3.org/2000/svg">
-            <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-              <g
-                transform="translate(-1842.000000, -1016.000000)"
-                stroke="#FFFFFF">
-                <g transform="translate(980.000000, 1006.000000)">
-                  <g transform="translate(862.000000, 10.000000)">
-                    <g transform="translate(4.000000, 5.000000)">
-                      <g
-                        transform="translate(8.058241, 5.009812)"
-                        fill="#FFFFFF"
-                        fill-rule="nonzero"
-                        stroke-width="0.3">
-                        <path d="M11.6084252,-0.15 C11.9880433,-0.15 12.3676614,-0.00518057514 12.6573002,0.284458275 L12.6573002,0.284458275 L18.3141545,5.94131252 C18.6037933,6.23095137 18.7486128,6.61056948 18.7486128,6.99018758 C18.7486128,7.36980569 18.6037933,7.74942379 18.3141545,8.03906264 L18.3141545,8.03906264 L12.6573002,13.6959169 C12.3676614,13.9855557 11.9880433,14.1303752 11.6084252,14.1303752 C11.2288071,14.1303752 10.849189,13.9855557 10.5595501,13.6959169 C10.2699113,13.406278 10.1250918,13.0266599 10.1250918,12.6470418 C10.1250918,12.2674237 10.2699113,11.8878056 10.5595368,11.5981801 L10.5595368,11.5981801 L13.6839174,8.47301484 L1.33333333,8.47352092 C0.923722144,8.47352092 0.552888811,8.30749318 0.284458275,8.03906264 C0.0160277386,7.77063211 -0.15,7.39979877 -0.15,6.99018758 C-0.15,6.61194961 -0.00841906355,6.26678575 0.224608408,6.00476938 C0.462154637,5.73767211 0.794779811,5.55707713 1.16932931,5.51583101 L1.16932931,5.51583101 L13.6841044,5.50627626 L10.5595501,2.38220839 C10.2699113,2.09256954 10.1250918,1.71295144 10.1250918,1.33333333 C10.1250918,0.953715229 10.2699113,0.574097124 10.5595501,0.284458275 C10.849189,-0.00518057514 11.2288071,-0.15 11.6084252,-0.15 Z"></path>
+        {props.type !== 'call' && (
+          <div class={styles.rightItem} onClick={() => (modal.status = true)}>
+            <svg
+              width="28px"
+              height="28px"
+              viewBox="0 0 34 34"
+              version="1.1"
+              xmlns="http://www.w3.org/2000/svg">
+              <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+                <g
+                  transform="translate(-1842.000000, -1016.000000)"
+                  stroke="#FFFFFF">
+                  <g transform="translate(980.000000, 1006.000000)">
+                    <g transform="translate(862.000000, 10.000000)">
+                      <g transform="translate(4.000000, 5.000000)">
+                        <g
+                          transform="translate(8.058241, 5.009812)"
+                          fill="#FFFFFF"
+                          fill-rule="nonzero"
+                          stroke-width="0.3">
+                          <path d="M11.6084252,-0.15 C11.9880433,-0.15 12.3676614,-0.00518057514 12.6573002,0.284458275 L12.6573002,0.284458275 L18.3141545,5.94131252 C18.6037933,6.23095137 18.7486128,6.61056948 18.7486128,6.99018758 C18.7486128,7.36980569 18.6037933,7.74942379 18.3141545,8.03906264 L18.3141545,8.03906264 L12.6573002,13.6959169 C12.3676614,13.9855557 11.9880433,14.1303752 11.6084252,14.1303752 C11.2288071,14.1303752 10.849189,13.9855557 10.5595501,13.6959169 C10.2699113,13.406278 10.1250918,13.0266599 10.1250918,12.6470418 C10.1250918,12.2674237 10.2699113,11.8878056 10.5595368,11.5981801 L10.5595368,11.5981801 L13.6839174,8.47301484 L1.33333333,8.47352092 C0.923722144,8.47352092 0.552888811,8.30749318 0.284458275,8.03906264 C0.0160277386,7.77063211 -0.15,7.39979877 -0.15,6.99018758 C-0.15,6.61194961 -0.00841906355,6.26678575 0.224608408,6.00476938 C0.462154637,5.73767211 0.794779811,5.55707713 1.16932931,5.51583101 L1.16932931,5.51583101 L13.6841044,5.50627626 L10.5595501,2.38220839 C10.2699113,2.09256954 10.1250918,1.71295144 10.1250918,1.33333333 C10.1250918,0.953715229 10.2699113,0.574097124 10.5595501,0.284458275 C10.849189,-0.00518057514 11.2288071,-0.15 11.6084252,-0.15 Z"></path>
+                        </g>
+                        <path
+                          d="M15,24 L3,24 C1.34314575,24 -1.1293615e-15,22.6568542 0,21 L0,3 C-2.02906125e-16,1.34314575 1.34314575,3.04359188e-16 3,0 L15,0 L15,0"
+                          stroke-width="3.5"
+                          stroke-linecap="round"
+                          stroke-linejoin="round"></path>
                       </g>
-                      <path
-                        d="M15,24 L3,24 C1.34314575,24 -1.1293615e-15,22.6568542 0,21 L0,3 C-2.02906125e-16,1.34314575 1.34314575,3.04359188e-16 3,0 L15,0 L15,0"
-                        stroke-width="3.5"
-                        stroke-linecap="round"
-                        stroke-linejoin="round"></path>
                     </g>
                   </g>
                 </g>
               </g>
-            </g>
-          </svg>
-        </div>
+            </svg>
+          </div>
+        )}
 
         {/* 布置作业 */}
         <NModal

BIN
src/views/attend-class/image/right_icon10.png


+ 7 - 1
src/views/attend-class/index.module.less

@@ -724,6 +724,10 @@
     opacity: 0.7;
     cursor: not-allowed;
   }
+
+  .itemHide {
+    display: none;
+  }
 }
 
 .rightColumnZ {
@@ -825,6 +829,8 @@
     opacity: 0.7;
     cursor: not-allowed;
   }
+
+
 }
 
 .selectMusicModal {
@@ -843,4 +849,4 @@
       }
     }
   }
-}
+}

+ 91 - 22
src/views/attend-class/index.tsx

@@ -81,6 +81,7 @@ import rightIconWhiteboard from './image/right_icon4.png';
 import rightIconMetronome from './image/right_icon5.png';
 import rightIconTuner from './image/right_icon6.png';
 import rightIconTimer from './image/right_icon7.png';
+import rightIconCall from './image/right_icon10.png';
 import rightIconPackUp from './image/right_icon8.png';
 import rightIconMusic from './image/right_icon9.png';
 import bottomIconSwitch from './image/bottom_icon1.png';
@@ -89,11 +90,11 @@ import bottomIconPre from './image/bottom_icon3.png';
 import bottomIconNext from './image/bottom_icon4.png';
 import rightHideIcon from './image/right_hide_icon.png';
 import SelectResources from '../prepare-lessons/model/select-resources';
-import { getStudentAfterWork } from '../studentList/api';
+import { getStudentAfterWork, getStudentList } from '../studentList/api';
 import TheNoticeBar from '/src/components/TheNoticeBar';
 import ClassWork from './model/class-work';
 
-export type ToolType = 'init' | 'pen' | 'whiteboard';
+export type ToolType = 'init' | 'pen' | 'whiteboard' | 'call';
 export type ToolItem = {
   type: ToolType;
   name: string;
@@ -291,6 +292,11 @@ export default defineComponent({
         }
       }
 
+      // 点名返回
+      if (ev.data?.api === 'callBack') {
+        closeStudyTool();
+      }
+
       if (ev.data?.api === 'onLogin') {
         const documentDom: any = document;
         documentDom.exitFullscreen
@@ -323,6 +329,8 @@ export default defineComponent({
       if (data.type === 'preview') {
         rightList.splice(1, 1);
       }
+
+      rollCallStudentList();
     });
 
     // const onFullScreen = () => {
@@ -853,7 +861,6 @@ export default defineComponent({
       }
     };
     document.body.addEventListener('keyup', (e: KeyboardEvent) => {
-      console.log(e, 'e');
       if (e.code === 'ArrowLeft') {
         // if (popupData.activeIndex === 0) return;
         setModalOpen();
@@ -928,7 +935,9 @@ export default defineComponent({
     const studyData = reactive({
       type: '' as ToolType,
       penShow: false,
-      whiteboardShow: false
+      whiteboardShow: false,
+      callShow: false,
+      callStudentList: [] as any // 学生列表
     });
 
     /** 打开教学工具 */
@@ -944,6 +953,10 @@ export default defineComponent({
           break;
         case 'whiteboard':
           studyData.whiteboardShow = true;
+          break;
+        case 'call':
+          studyData.callShow = true;
+          break;
       }
     };
 
@@ -1111,17 +1124,6 @@ export default defineComponent({
     // 右侧菜单栏
     const rightList = reactive([
       {
-        name: '结束课程',
-        name2: '结束预览',
-        icon: rightIconEnd,
-        id: 1
-      },
-      {
-        name: '布置作业',
-        icon: rightIconArrange,
-        id: 2
-      },
-      {
         name: '曲目资源',
         name2: '曲目资源',
         icon: rightIconMusic,
@@ -1143,15 +1145,31 @@ export default defineComponent({
         id: 5
       },
       {
-        name: '调音器',
-        icon: rightIconTuner,
-        id: 6
-      },
-      {
         name: '计时器',
         icon: rightIconTimer,
         id: 7
       },
+      // {
+      //   name: '调音器',
+      //   icon: rightIconTuner,
+      //   id: 6
+      // },
+      {
+        name: '点名',
+        icon: rightIconCall,
+        id: 10
+      },
+      {
+        name: '布置作业',
+        icon: rightIconArrange,
+        id: 2
+      },
+      {
+        name: '结束课程',
+        name2: '结束预览',
+        icon: rightIconEnd,
+        id: 1
+      },
       {
         name: '收起',
         icon: rightIconPackUp,
@@ -1268,11 +1286,49 @@ export default defineComponent({
           handleStop(false);
           data.selectResourceStatus = true;
           break;
+        case 10:
+          //  点名
+          // await rollCallStudentList();
+          if (studyData.callStudentList.length > 0) {
+            openStudyTool({
+              type: 'call',
+              icon: iconWhite,
+              name: '点名'
+            });
+            return;
+          }
+          break;
         default:
           break;
       }
     };
 
+    // 点名学生列表
+    const rollCallStudentList = async () => {
+      //
+      if (!data.classId) return;
+      try {
+        const res = await getStudentList({
+          classGroupId: data.classGroupId,
+          page: 1,
+          rows: 999
+        });
+        const result = res.data || {};
+        if (Array.isArray(result.rows) && result.rows.length > 0) {
+          const tempStudents: any = [];
+          result.rows.forEach((row: any) => {
+            tempStudents.push({
+              name: row.nickname,
+              img: row.avatar
+            });
+          });
+          studyData.callStudentList = [...tempStudents];
+        }
+      } catch {
+        //
+      }
+    };
+
     // 底部悬浮按钮操作
     const operateBottomBtn = (id: number) => {
       switch (id) {
@@ -1536,9 +1592,11 @@ export default defineComponent({
             <div
               class={[
                 styles.rightItem,
-                item.id === 2 && data.preStudentNum <= 0
+                (item.id === 2 && data.preStudentNum <= 0) ||
+                (item.id === 10 && studyData.callStudentList.length <= 0)
                   ? styles.itemDisabled
-                  : ''
+                  : '',
+                item.id === 10 && !data.classId ? styles.itemHide : ''
               ]}
               onClick={() => operateRightBtn(item.id)}>
               <img src={item.icon} />
@@ -1667,6 +1725,15 @@ export default defineComponent({
           />
         )}
 
+        {studyData.callShow && (
+          <Pen
+            callStudents={studyData.callStudentList}
+            show={studyData.type === 'call'}
+            type={studyData.type}
+            close={() => closeStudyTool()}
+          />
+        )}
+
         {/* 布置作业 */}
         <NModal
           transformOrigin="center"
@@ -1842,3 +1909,5 @@ export default defineComponent({
     );
   }
 });
+
+// roll-call/index.html

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott