<!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" @dblclick="()=>{animationStatus?closes():start()}"> <div class="pageTitle"></div> <div v-if="platform!=='modal'" class="iconBack" @click.stop="onBack()"></div> <div id="menu" :class="[platform==='modal'?(imagePos==='right'?'menuRight':'menuLeft'):'']"> <div id="table" :class="tableIndex <= 1 ? 'disabled' : ''" v-show="!animationStatus" @click.stop="start()"></div> <div id="sphere" v-show="animationStatus" @click.stop="closes()"></div> <div v-if="platform==='modal'" id="backBtn" @click.stop="onBack()"></div> <!-- <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, platform: "", imagePos: "" }, 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, }, '*'); }, handleUrlParmas(){ const params=getUrlParams(location.href) params?.platform&&(this.platform = params?.platform) params?.imagePos&&(this.imagePos = params?.imagePos) } }, created: function () { // init(); // animate(); // getStar(); // this.ckPrice(); this.handleUrlParmas() } }) function getUrlParams(url) { let urlStr = url.split('?')[1] const urlSearchParams = new URLSearchParams(urlStr) const result = Object.fromEntries(urlSearchParams.entries()) return result } </script>