index.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="icon" href="/favicon.ico" />
  6. <meta name="viewport"
  7. content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
  8. <meta http-equiv="Cache-control" content="no-cache">
  9. <meta http-equiv="Cache" content="no-cache">
  10. <meta name="apple-mobile-web-app-capable" content="yes" />
  11. <title>点名</title>
  12. <link rel="stylesheet" href="./css/index.css">
  13. <script src="js/three.min.js"></script>
  14. <script src="js/tween.min.js"></script>
  15. <!-- <script src="js/stats.min.js"></script> -->
  16. <script src="js/TrackballControls.js"></script>
  17. <script src="js/CSS3DRenderer.js"></script>
  18. <script src="js/vue.min.js"></script>
  19. <!-- 创建星星 -->
  20. <!-- <script src="js/star.js"></script> -->
  21. <!-- 数据位置 -->
  22. <script src="js/data.js"></script>
  23. </head>
  24. <body>
  25. <div id="container" style="pointer-events: none;"></div>
  26. <div id="vueBoxs">
  27. <div class="bss">
  28. <div class="pageTitle"></div>
  29. <div class="iconBack" @click="onBack()"></div>
  30. <div id="menu">
  31. <button id="table" :class="tableIndex <= 1 ? 'disabled' : ''" v-show="!animationStatus"
  32. @click="start()"></button>
  33. <button id="sphere" v-show="animationStatus" @click="closes()"></button>
  34. <!-- <button id="reset" style="margin-left:40px;" @click="resets()">照片墙</button> -->
  35. <!-- <button id="lists" @click="listShow = true">中奖名单</button> -->
  36. </div>
  37. </div>
  38. </div>
  39. </body>
  40. </html>
  41. <script>
  42. var table = getData()
  43. var tableLens = table.length;
  44. var camera, scene, renderer;
  45. var controls;
  46. var objects = [];
  47. var targets = { chaos: [], table: [], sphere: [], helix: [], grid: [] };
  48. var ang = 0, moving = false, objectsss, starBG, isMoving = false; //objectsss 为切换的图片的
  49. var cpx = 0, cpy = 0, cpz = 0, crx = 0, cry = 0, crz = 0;
  50. function init() {
  51. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
  52. camera.position.z = 1500;
  53. scene = new THREE.Scene();
  54. // table
  55. for (var i = 0; i < table.length; i++) {
  56. // 每个图标的盒子
  57. var element = document.createElement('div');
  58. element.className = 'element';
  59. element.style.backgroundColor = 'rgba(255,255,255)';
  60. element.style.borderRadius = '12px'
  61. if (i >= 32) {
  62. element.className = 'element hide'
  63. }
  64. // 图片
  65. var symbolBox = document.createElement('div');
  66. var symbol = document.createElement('img');
  67. symbolBox.className = 'symbolBox';
  68. symbol.className = 'symbol';
  69. symbol.src = table[i].img + '?imageMogr2/strip/format/png/size-limit/50k!';
  70. symbolBox.appendChild(symbol);
  71. element.appendChild(symbolBox);
  72. // 姓名
  73. var details = document.createElement('div');
  74. details.className = 'details';
  75. details.innerHTML = table[i].name;
  76. element.appendChild(details);
  77. // 图标变成3d内的对象,放入场景中
  78. var object = new THREE.CSS3DObject(element);
  79. object.position.x = Math.random() * 3400 - 1700;
  80. object.position.y = Math.random() * 3400 - 1700;
  81. object.position.z = Math.random() * 3400 - 1700;
  82. object.name = table[i].name;
  83. scene.add(object);
  84. objects.push(object);
  85. // 根据索引,定制位置
  86. var object = new THREE.Object3D();
  87. var ix = (i) % 8;
  88. object.position.y = 300;
  89. switch (table.length) {
  90. case 1:
  91. object.position.x = 0;
  92. break;
  93. case 2:
  94. object.position.x = (ix * 172) - (172 * 1 / 2);
  95. break;
  96. case 3:
  97. object.position.x = (ix * 172) - (172 * 2 / 2);
  98. break;
  99. case 4:
  100. object.position.x = (ix * 172) - (172 * 3 / 2);
  101. break;
  102. case 5:
  103. object.position.x = (ix * 172) - (172 * 4 / 2);
  104. break;
  105. case 6:
  106. object.position.x = (ix * 172) - (172 * 5 / 2);
  107. break;
  108. case 7:
  109. object.position.x = (ix * 172) - (172 * 6 / 2);
  110. break;
  111. default:
  112. var iy = Math.floor((i) / 8);
  113. object.position.x = (ix * 172) - 600;
  114. object.position.y = - (iy * 192) + 300;
  115. break;
  116. }
  117. targets.table.push(object);
  118. }
  119. // 创建切换图片
  120. var elements = document.createElement('div');
  121. elements.className = 'changeImgBoxs';
  122. // element.style.backgroundImage = "url(./img/pic.png)";
  123. elements.style.backgroundColor = 'rgba(255,255,255)';
  124. var symbolBox = document.createElement('div');
  125. var symbol = document.createElement('img');
  126. symbol.setAttribute("id", "changeImg");
  127. symbolBox.className = 'symbolBox2';
  128. symbol.className = 'symbol2';
  129. symbol.src = table[0].img + '?imageMogr2/strip/format/png/size-limit/50k!';
  130. symbolBox.appendChild(symbol);
  131. elements.appendChild(symbolBox);
  132. var details = document.createElement('div');
  133. details.setAttribute("id", "detailss");
  134. details.className = 'details';
  135. details.innerHTML = table[0].name;
  136. elements.appendChild(details);
  137. objectsss = new THREE.CSS3DObject(elements);
  138. objectsss.position.x = 0;
  139. objectsss.position.y = 20000;
  140. objectsss.position.z = 0;
  141. scene.add(objectsss);
  142. // 散乱随机位置
  143. var vector = new THREE.Vector3();
  144. for (var i = 0, l = objects.length; i < l; i++) {
  145. var phi = Math.acos(-1 + (2 * i) / l);
  146. var theta = Math.sqrt(l * Math.PI) * phi;
  147. var object = new THREE.Object3D();
  148. var py = Math.random() * 3400 - 1700;
  149. if (py < 400 && py > -400) { //防止停止时,图片位置不好挡住中央的图片
  150. if (py < 0) {
  151. py -= 400;
  152. } else {
  153. py += 400;
  154. }
  155. }
  156. object.position.x = Math.random() * 3400 - 1700;
  157. object.position.y = py;
  158. object.position.z = Math.random() * 3400 - 1700;
  159. object.lookAt(vector);
  160. targets.chaos.push(object);
  161. }
  162. // 球
  163. var vector = new THREE.Vector3();
  164. for (var i = 0, l = objects.length; i < l; i++) {
  165. var phi = Math.acos(-1 + (2 * i) / l);
  166. var theta = Math.sqrt(l * Math.PI) * phi;
  167. var object = new THREE.Object3D();
  168. object.position.x = 750 * Math.cos(theta) * Math.sin(phi);
  169. object.position.y = 750 * Math.sin(theta) * Math.sin(phi);
  170. object.position.z = 750 * Math.cos(phi);
  171. vector.copy(object.position).multiplyScalar(2);
  172. object.lookAt(vector);
  173. targets.sphere.push(object);
  174. }
  175. //渲染
  176. renderer = new THREE.CSS3DRenderer();
  177. renderer.setSize(window.innerWidth, window.innerHeight);
  178. renderer.domElement.style.position = 'absolute';
  179. document.getElementById('container').appendChild(renderer.domElement);
  180. //控制器
  181. controls = new THREE.TrackballControls(camera, renderer.domElement);
  182. controls.rotateSpeed = 0.5;
  183. controls.minDistance = 500;
  184. controls.maxDistance = 6000;
  185. controls.addEventListener('change', render);
  186. // 初始化
  187. transform(targets.table, 800);
  188. window.addEventListener('resize', onWindowResize, false);
  189. cpx = camera.position.x;
  190. cpy = camera.position.y;
  191. cpz = camera.position.z;
  192. crx = camera.rotation.x;
  193. cry = camera.rotation.y;
  194. crz = camera.rotation.z;
  195. }
  196. // 切换状态时动画
  197. function transform(targets, duration, type) {
  198. var scale = 1;
  199. if (type == undefined) {
  200. type = 0;
  201. }
  202. TWEEN.removeAll();
  203. for (var i = 0; i < objects.length; i++) {
  204. var object = objects[i];
  205. var target = targets[i];
  206. new TWEEN.Tween(object.position)
  207. .to({ x: target.position.x, y: target.position.y, z: target.position.z }, Math.random() * duration + duration)
  208. .easing(TWEEN.Easing.Exponential.InOut)
  209. .start();
  210. new TWEEN.Tween(object.rotation)
  211. .to({ x: target.rotation.x, y: target.rotation.y, z: target.rotation.z }, Math.random() * duration + duration)
  212. .easing(TWEEN.Easing.Exponential.InOut)
  213. .start();
  214. }
  215. new TWEEN.Tween(this)
  216. .to({}, duration * 2)
  217. .onUpdate(render)
  218. .start()
  219. // console.log(document.querySelectorAll('.element'), '1212')
  220. setTimeout(() => {
  221. console.log(moving, type)
  222. if (moving || type === 2) {
  223. const elements = document.querySelectorAll('.element')
  224. console.log(elements, 'eee')
  225. if (elements.length > 0) {
  226. elements.forEach((e, index) => {
  227. if (type === 2) {
  228. if (index >= 32) {
  229. e.classList.add('hide')
  230. }
  231. } else {
  232. e.classList.remove('hide')
  233. }
  234. })
  235. }
  236. }
  237. }, 400);
  238. }
  239. // 屏幕大小适配
  240. function onWindowResize() {
  241. camera.aspect = window.innerWidth / window.innerHeight;
  242. camera.updateProjectionMatrix();
  243. renderer.setSize(window.innerWidth, window.innerHeight);
  244. render();
  245. }
  246. function animate() {
  247. requestAnimationFrame(animate);
  248. TWEEN.update();
  249. // 旋转
  250. if (moving) {
  251. movings();
  252. }
  253. controls.update();
  254. // 星空位置与相机位置相对
  255. cpx = camera.position.x;
  256. cpy = camera.position.y;
  257. cpz = camera.position.z;
  258. crx = camera.rotation.x;
  259. cry = camera.rotation.y;
  260. crz = camera.rotation.z;
  261. }
  262. function render() {
  263. renderer.render(scene, camera);
  264. }
  265. var numsss = 0, srcss = '', txtsss = '';
  266. function movings() {
  267. // 相机旋转
  268. ang += Math.PI / 50;
  269. camera.position.x = Math.cos(ang) * 2000;
  270. camera.position.z = Math.sin(ang) * 2000;
  271. camera.position.y = 0;
  272. // 相机方向重置
  273. camera.up.x = 0;
  274. camera.up.y = 1;
  275. camera.up.z = 0;
  276. // 图片方向固定
  277. objectsss.rotation.y = -ang + Math.PI / 2;
  278. //中间图片切换
  279. numsss = Math.floor(Math.random() * tableLens);
  280. if (numsss == tableLens) {
  281. numsss = tableLens - 1;
  282. }
  283. srcss = table[numsss].img + '?imageMogr2/strip/format/png/size-limit/50k!';
  284. txtsss = table[numsss].name;
  285. changeImg.src = srcss;
  286. detailss.innerHTML = txtsss;
  287. }
  288. // 停止时,图片放大动画
  289. function objDeal(obj, nums) {
  290. var option = {
  291. x: obj.scale.x,
  292. y: obj.scale.y,
  293. z: obj.scale.z,
  294. };
  295. var tween = new TWEEN.Tween(option).to({
  296. x: nums,
  297. y: nums,
  298. z: nums,
  299. }, 300).delay(100).onUpdate(function () {
  300. obj.scale.x = this.x;
  301. obj.scale.y = this.y;
  302. obj.scale.z = this.z;
  303. isMoving = true;
  304. }).onComplete(function () {
  305. isMoving = false;
  306. }).start();
  307. }
  308. // 初始化数据
  309. function renderData(data) {
  310. table = data
  311. tableLens = data.length
  312. vm.tableIndex = tableLens
  313. init();
  314. animate();
  315. }
  316. function preloadImages(imageUrls, callback) {
  317. let images = {};
  318. let loadedImages = 0;
  319. let numImages = imageUrls.length;
  320. // 创建一个Image对象,并设置src属性来开始加载图片
  321. imageUrls.forEach((url) => {
  322. images[url] = new Image();
  323. images[url].onload = function () {
  324. // 当图片加载完成时,更新计数器
  325. loadedImages++;
  326. if (loadedImages === numImages && callback) {
  327. callback(images); // 所有图片都加载完毕,调用回调函数
  328. }
  329. };
  330. images[url].onerror = function () {
  331. console.error('Could not load image at ' + url);
  332. loadedImages++;
  333. };
  334. images[url].src = url;
  335. });
  336. }
  337. //点击事件及部分判断
  338. var vm = new Vue({
  339. el: '#vueBoxs',
  340. data: {
  341. animationStatus: false,
  342. tableIndex: 0,
  343. listShow: false
  344. },
  345. methods: {
  346. keyDowns: function () {
  347. this.closes();
  348. },
  349. //开始
  350. start: function () {
  351. if (this.tableIndex <= 1) {
  352. return
  353. }
  354. moving = true;
  355. this.animationStatus = true;
  356. objectsss.position.y = 0;
  357. transform(targets.sphere, 1000);
  358. objDeal(objectsss, 1);
  359. // music.play();
  360. // this.ckPrice();
  361. },
  362. //结束
  363. closes: function () {
  364. // music.pause();
  365. if (!moving) {
  366. return;
  367. }
  368. // music2.play();
  369. moving = false;
  370. this.animationStatus = false;
  371. // this.choosePerson();
  372. transform(targets.chaos, 250, 1);
  373. objDeal(objectsss, 1.8);
  374. },
  375. //回到照片墙的状态
  376. resets: function () {
  377. moving = false;
  378. camera.position.z = 1500;
  379. camera.position.x = 0;
  380. camera.position.y = 0;
  381. camera.up.x = 0;//相机以哪个方向为上方
  382. camera.up.y = 1;
  383. camera.up.z = 0;
  384. //图片重置方向
  385. objectsss.rotation.y = 0;
  386. objectsss.position.y = 20000;
  387. objectsss.scale.set(1, 1, 1);
  388. // 星空背景图重置
  389. transform(targets.table, 400, 2);
  390. },
  391. onBack() {
  392. // 返回时先结束
  393. this.closes()
  394. this.resets()
  395. window.parent.postMessage({
  396. api: 'callBack',
  397. loading: false,
  398. }, '*');
  399. }
  400. },
  401. created: function () {
  402. // init();
  403. // animate();
  404. // const imageUrls = table.map(value => value.img + '?imageMogr2/strip/format/png/size-limit/50k!')
  405. // console.log(imageUrls.length, 'length')
  406. // console.log(imageUrls, 'imageUrls')
  407. // preloadImages(imageUrls, function (images) {
  408. // // console.log('All images loaded.');
  409. // // // 这里可以访问images对象,它是一个包含预加载图片的对象,
  410. // // // 其中键是图片的URL,值是Image对象。
  411. // init();
  412. // animate();
  413. // setTimeout(() => {
  414. // animate();
  415. // }, 100);
  416. // });
  417. // getStar();
  418. // this.ckPrice();
  419. }
  420. })
  421. </script>