vue實現氣泡運動撞擊效果
本文實例為大傢分享瞭vue實現氣泡運動撞擊效果的具體代碼,供大傢參考,具體內容如下
封裝組件
<template> <ul id="main"> <li v-for="(item, index) in circleData" :key="index" :class="{'active': item.is_latest_sign_user}"> <div> <span>{{ item.nick_name }}</span> <span>簽到</span> </div> </li> </ul> </template> <script> export default { data() { return { circleData: [], circleDom: [], circleArr: [], //初始化運動的最大寬和高,初始定義0 maxW: 0, maxH: 0, timer: null, timerArr: [], count: 0, }; }, mounted() { this.getLatest_sign_users('init') this.timer = setInterval((i) => { this.count++ this.getLatest_sign_users() }, 5000) }, methods: { getLatest_sign_users(type = '') { let data = [] // nick_name: 用戶名 // is_latest_sign_user: 是否是新簽到用戶 // gender: 0-女 1-男 if (this.count === 0) { data = [ { id: '1', nick_name: '蕭一', is_latest_sign_user: true, gender: 0 }, { nick_name: '楊二', is_latest_sign_user: true, gender: 0 }, { nick_name: '張三', is_latest_sign_user: true, gender: 0 } ] } else if (this.count === 1) { data = [ { nick_name: '蕭一', is_latest_sign_user: false, gender: 0 }, { nick_name: '楊二', is_latest_sign_user: false, gender: 0 }, { nick_name: '張三', is_latest_sign_user: false, gender: 0 }, { nick_name: '李四', is_latest_sign_user: true, gender: 1 }, { nick_name: '王五', is_latest_sign_user: true, gender: 0 }, { nick_name: '徐六', is_latest_sign_user: true, gender: 1 }, { nick_name: '劉七', is_latest_sign_user: true, gender: 1 } ] } else if (this.count === 2) { data = [ { nick_name: '蕭一', is_latest_sign_user: false, gender: 0 }, { nick_name: '楊二', is_latest_sign_user: false, gender: 0 }, { nick_name: '張三', is_latest_sign_user: false, gender: 0 }, { nick_name: '李四', is_latest_sign_user: false, gender: 1 }, { nick_name: '王五', is_latest_sign_user: false, gender: 0 }, { nick_name: '徐六', is_latest_sign_user: false, gender: 1 }, { nick_name: '劉七', is_latest_sign_user: false, gender: 1 }, { nick_name: '何八', is_latest_sign_user: true, gender: 0 }, { nick_name: '柳九', is_latest_sign_user: true, gender: 0 }, { nick_name: '甄十', is_latest_sign_user: true, gender: 1 }, { nick_name: '十一', is_latest_sign_user: true, gender: 1 }, { nick_name: '十二', is_latest_sign_user: true, gender: 1 } ] } else { data = [ { nick_name: '蕭一', is_latest_sign_user: false, gender: 0 }, { nick_name: '楊二', is_latest_sign_user: false, gender: 0 }, { nick_name: '張三', is_latest_sign_user: false, gender: 0 }, { nick_name: '李四', is_latest_sign_user: false, gender: 1 }, { nick_name: '王五', is_latest_sign_user: false, gender: 0 }, { nick_name: '徐六', is_latest_sign_user: false, gender: 1 }, { nick_name: '劉七', is_latest_sign_user: false, gender: 1 }, { nick_name: '何八', is_latest_sign_user: false, gender: 0 }, { nick_name: '柳九', is_latest_sign_user: false, gender: 0 }, { nick_name: '甄十', is_latest_sign_user: false, gender: 1 }, { nick_name: '十一', is_latest_sign_user: false, gender: 1 }, { nick_name: '十二', is_latest_sign_user: false, gender: 1 } ] } this.circleData = [...data] if (type === 'init') {//初次加載時默認全是新增簽到用戶 data.forEach(item => item.is_latest_sign_user = true) } this.$nextTick(() => { if (data.length) { this.initBubble() } }) }, initBubble() { let main = document.getElementById("main"); let divDom = main.getElementsByClassName("active"); //獲取新增加的dom if (!divDom.length) return; //清理每個球得定時器 this.timerArr.forEach(item => { clearInterval(item) }) this.timerArr = [] //給新增加的dom設置寬高 for (let i = 0; i < divDom.length; i++) { let colors = [ "#EF250A", "#830AF6" ]; divDom[i].style.boxShadow = "0 0 20px" + " " + colors[this.circleData[i].gender] + " " + "inset"; // 10個以上尺寸變小 divDom[i].style.width = "46px"; divDom[i].style.height = "46px"; divDom[i].style.fontSize = "12px"; divDom[i].style.lineHeight = "16px"; this.circleDom.push(divDom[i]) } //根據瀏覽器窗口的大小自動調節小球的運動空間 window.onresize = () => { this.maxW = main.clientWidth - divDom[0].clientWidth; //為瞭讓小球不卡在瀏覽器邊緣 this.maxH = main.clientHeight - divDom[0].clientHeight; // 所以要減去自身的寬高 }; onresize(); //數組對象的初始化 for (let i = 0; i < this.circleDom.length; i++) { let obj = {}; console.log(this.circleDom[i]); if (this.circleDom[i].getAttribute("class") === 'active') { obj.x = Math.floor(Math.random() * (this.maxW + 1)); //初始x坐標 obj.y = Math.floor(Math.random() * (this.maxH + 1)); //初始y坐標 obj.cx = obj.x + this.circleDom[0].offsetWidth / 2;//圓心x坐標 obj.cy = obj.y + this.circleDom[0].offsetHeight / 2;//圓心y坐標 obj.movex = Math.floor(Math.random() * 2); //x軸移動方向 obj.movey = Math.floor(Math.random() * 2); //y軸移動方向 obj.speed = 0.2; //隨機速度 obj.timer = null; //計時器 obj.index = i; //索引值 this.circleArr.push(obj) //小球位置初始化 this.circleDom[i].style.left = obj.x + 'px'; this.circleDom[i].style.top = obj.y + 'px'; } else { //保留之前數據得位置信息,不刷新位置 obj = this.circleArr[i] } this.move(obj); } }, //移動函數 move(balls) { //每個球單獨有定時器 balls.timer = setInterval(() => { if (balls.movex === 1) { //如果往右跑,則一直加速度,碰到邊界,改為反方向運動 balls.x += balls.speed; if (balls.x + balls.speed >= this.maxW) { //防止小球出界 balls.x = this.maxW; balls.movex = 0; //小球運動方向發生改變 } } else { balls.x -= balls.speed; // 1和0表示正反方向 if (balls.x - balls.speed <= 0) { balls.x = 0; balls.movex = 1; } } if (balls.movey === 1) { balls.y += balls.speed; if (balls.y + balls.speed >= this.maxH) { balls.y = this.maxH; balls.movey = 0; } } else { balls.y -= balls.speed; if (balls.y - balls.speed <= 0) { balls.y = 0; balls.movey = 1; } } if (this.circleDom[balls.index]) { balls.cx = balls.x + this.circleDom[0].offsetWidth / 2;//小球圓心等於:運動中x的值加上自身的半徑 balls.cy = balls.y + this.circleDom[0].offsetHeight / 2; this.circleDom[balls.index].style.left = balls.x + "px"; //小球相對於屏幕的位置 this.circleDom[balls.index].style.top = balls.y + "px"; this.crash(balls.index); //每個小球進行碰撞檢測 } }, 25); this.timerArr.push(balls.timer) }, //碰撞函數 crash(a) { let container = [...this.circleArr] let ball1x = container[a].cx; //在數組中任意球的圓心坐標 let ball1y = container[a].cy;//思路:先隨便拿一個球,然後遍歷所有球,拿這個球和所有球的圓心距離比較 for (let i = 0; i < container.length; i++) { if (i !== a) { //判斷取出來的球不是本身,才能和其他球進行距離判斷 let ball2x = container[i].cx; //將其他球的圓心坐標賦值給球2 let ball2y = container[i].cy; //圓心距 求兩個點之間的距離,開平方 let distence = Math.sqrt((ball1x - ball2x) * (ball1x - ball2x) + (ball1y - ball2y) * (ball1y - ball2y)); if (distence <= this.circleDom[0].offsetWidth) { //球心距離和求直徑比較 if (ball1x > ball2x) { //當前位於未知求的右方 if (ball1y > ball2y) {//預設未知球撞當前球,然後當前球改變運動 container[a].movex = 1; //1表示為正值,對應的右和下 container[a].movey = 1;//0表示為負值,對應的左和上 } else if (ball1y < ball2y) { container[a].movex = 1; container[a].movey = 0; } else { container[a].movex = 1; } } else if (ball1x < ball2x) { if (ball1y > ball2y) { container[a].movex = 0; container[a].movey = 0; } else if (ball1y < ball2y) { container[a].movex = 0; container[a].movey = 1; } else { container[a].movex = 0; } } else { if (ball1y > ball2y) { container[a].movey = 1; } else if (ball1y < ball2y) { container[a].movey = 0; } } } } } } }, beforeDestroy() { //清理每個球得定時器 this.timerArr.forEach(item => { clearInterval(item) }) //清理簽到數據 clearInterval(this.timer) } }; </script> <style lang='less' scoped> #main { position: relative; width: 100%; height: 100%; overflow: hidden; padding: 0; li { position: absolute; overflow: hidden; -moz-border-radius: 50%; -webkit-border-radius: 50%; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-wrap: wrap; &.active { animation: scaleBox 1s 1; } @keyframes scaleBox { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } div { span { display: block; width: 100%; color: #fff; text-align: center; } } } } </style>
實現效果
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- JavaScript實現div的鼠標拖拽效果
- Android之小球自由碰撞動畫示例
- vue+ts實現元素鼠標拖動效果
- vue實現左右滑動效果實例代碼
- JavaScript canvas實現俄羅斯方塊遊戲