公司有一個新的需求 是需要懸浮球在一側上下滑動 其實是很簡單的 而且網上都有各種案例,但是 偏偏是橫屏狀態下 ,而且不是手機橫屏 是用css強制旋轉螢幕90度之後的橫屏,所以就會出現座標系的紊亂,然後我這個功能一開始做成的效果就是觸控上下滑動的時候 ,懸浮球是左右走(目前的這個圖片的上下左右),當時非常的苦惱,接下來貼上我的程式碼,大家可以參考,有問題可以評論指出,謝謝!我先把我的基本佈局拿過來,用的js是 flexible.js 寫的移動端的佈局;
因為程式碼是有一陣子了 我也是從網上找的相關的正常懸浮球的移動的案例 之後再研究的橫屏下的懸浮球移動;如涉及侵權,請諒解 或者指出 我會標明出處;感謝配合;
下面的是html
圖片那裡大家可以自行更換
1 <body> 2 <div id="example"> 3 <!-- 側邊的懸浮球 --> 4 <div class="sideDown"> 5 <ul class="smallDown"> 6 <img class="suspBall" src="./images/sideDownLogo.png" alt=""> 7 <li class="comeOut"> 8 <p class="Take_back"><img src="./images/putAway.png" alt=""></p> 9 <p class="save_game"> 10 <img src="./images/saveLogo.png" alt=""> 11 <i>儲存</i> 12 </p> 13 <p class="down_game"> 14 <img src="./images/downLogo.png" alt=""> 15 <i>下載</i> 16 </p> 17 </li> 18 </ul> 19 </div> 20 </div> 21 </body>
下面的是css 因為我當時寫這個的時候是依賴於一個雲專案中的SDK 自帶的樣式 它的樣式就是這麼強制橫屏的 所以我當時為了測試,就自己先寫在了自己的樣式裡面 僅供參考 如有更好的 大家可以儘可能的提出!
#example { width: 100%; height: 100%; position: relative; /* 這是分割線 以下是為了螢幕旋轉成橫屏 僅供參考 */ width: 667px; height: 375px; left: -146px; top: 146px; -moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); -moz-transform-origin: center center; -webkit-transform-origin: center center; -o-transform-origin: center center; -ms-transform-origin: center center; transform-origin: center center } /* 側邊的懸浮球 */ .sideDown { width: 1rem; height: 100%; position: absolute; z-index: 444; right: 0; display: block; } .sideDown ul { width: 1rem; height: 1rem; display: flex; align-items: center; position: absolute; top: 20px; right: 0; opacity: 1; } .sideDown ul img.suspBall { display: inline-block; width: 1rem; height: 1rem; z-index: 333; } .sideDown li { position: absolute; z-index: 222; right: 0.15rem; width: 3.3rem; height: 0.60rem; background: rgba(255, 230, 0, 1); border-radius: 0.35rem; opacity: 0.9; display: flex; align-items: center; } .sideDown li p { height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; margin-left: 0.5rem; } .sideDown li p img { display: inline-block; width: 0.29rem; height: 0.29rem; } .sideDown li p:first-child { width: 0.2rem; height: 0.2rem; margin-left: 0.16rem; } .sideDown li p:first-child img { display: inline-block; width: 0.2rem; height: 0.2rem; } .sideDown li p:first-child img { display: inline-block; width: 0.2rem; height: 0.2rem; } .sideDown li p i { display: inline-block; font-size: 0.17rem; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: rgba(51, 51, 51, 1); }
以下是重點 js程式碼
1 <script> 2 window.onload = function () { 3 var flag = 0; //標記是拖曳還是點選 4 var disX, disY; 5 var targetW = 0;//剛進來的時候懸浮球左邊的寬度是正常的; 6 // 獲取元素 7 var bigBox = document.querySelector(".sideDown"); 8 var sBox = document.querySelector(".smallDown"); 9 var sBoxImg = document.querySelector(".suspBall"); 10 // console.log('獲取元素', bigBox, sBox) 11 // 獲取大盒子的大小 12 var bigbox_w = bigBox.offsetHeight; 13 var bigbox_h = bigBox.offsetWidth; 14 // console.log('獲取大盒子的大小', bigbox_w, bigbox_h) 15 // 獲取小盒子的大小 16 var sbox_w = sBox.offsetHeight; 17 var sbox_h = sBox.offsetWidth ; 18 // console.log('獲取小盒子的大小', sbox_w, sbox_h) 19 // 獲取大盒子的間距 20 var bigBox_l = bigBox.offsetLeft; 21 var bigBox_t = bigBox.offsetTop ; 22 // console.log('獲取大盒子的間距', bigBox_l, bigBox_t) 23 24 // 小盒子滑鼠按下才觸發事件 25 sBoxImg.addEventListener('touchstart', function (ev) { 26 flag = 0; 27 ev = ev || window.event; 28 ev.preventDefault();//阻止觸控時頁面的滾動,縮放 29 30 // 獲取滑鼠在盒子中的位置 31 // 觸點位置減去小盒子的間距就是滑鼠在小盒子中的位置 32 disX = bigbox_w - ev.touches[0].pageX - sBox.offsetTop; 33 disY = ev.touches[0].pageY - bigBox_l; 34 35 console.log('獲取觸點位置', ev.touches[0].pageY, ev.touches[0].pageX) 36 console.log('小盒子的左和上間距', sBox.offsetLeft, sBox.offsetTop) 37 console.log('獲取滑鼠在盒子中的位置', disX, disY) 38 }) 39 sBoxImg.addEventListener('touchmove', function (e) { 40 flag = 1; 41 e = e || window.event; 42 // 用這次獲取到的滑鼠的位置減去上次滑鼠在小盒子的位置就是小盒子的左和上間距 43 var moveX = bigbox_w - e.touches[0].pageX - disX; 44 var moveY = e.touches[0].pageY - disY; 45 // console.log('移動的時候~~獲取觸點位置', e.touches[0].pageX, e.touches[0].pageY) 46 // console.log('獲取上次滑鼠在盒子中的位置', disX, disY) 47 // console.log('小盒子的左和上間距', moveX, moveY) 48 49 if (moveX < 0) { 50 moveX = 0; 51 } 52 if (moveY < 0) { 53 moveY = 0; 54 } 55 if (moveX > bigbox_w - sbox_w) { 56 moveX = bigbox_w - sbox_w; 57 } 58 if (moveY > bigbox_h - sbox_h) { 59 moveY = bigbox_h - sbox_h; 60 } 61 sBox.style.top = moveX + 'px'; 62 sBox.style.left = moveY + 'px'; 63 }) 64 sBoxImg.addEventListener('touchend', function (e) { 65 // console.log('結束') 66 //判斷滑動方向 67 if (flag === 0) {//點選 68 69 // console.log('點選了'); 70 71 if (targetW == 0) { 72 console.log('收回去了', targetW) 73 $(".comeOut").animate({ width: '0.3rem', opacity: '0.5', }, 'slow', function () { 74 targetW = 1; //改變懸浮球左邊大小的時候 改變這個值 以便於後面的判斷; 75 }) 76 } 77 if (targetW == 1) { 78 console.log('放出來了', targetW) 79 $(".comeOut").animate({ width: '3.3rem', opacity: '0.9', }, 'slow', function () { 80 targetW = 0; 81 }) 82 } 83 84 } 85 }); 86 87 $(".Take_back").click(function (event) { 88 console.log('點選箭頭', targetW) 89 $(".comeOut").animate({ width: '0.3rem', opacity: '0.5', }, 'slow', function () { 90 targetW = 1; //改變懸浮球左邊大小的時候 改變這個值 以便於後面的判斷; 91 }) 92 event.stopPropagation() 93 }); 94 } 95 96 </script>
下面進行詳細的解說:
var bigbox_w = bigBox.offsetHeight;
var bigbox_h = bigBox.offsetWidth;
這兩句 按正常的豎屏的話應該是
var bigbox_w = bigBox.offsetWidth;
var bigbox_h = bigBox.offsetHeight;
offsetWidth 顯示的是盒子正常的寬 (也就是你css裡面寫的寬)
offsetHeight 顯示的是盒子正常的高 (也就是你css裡面寫的高)
但是 由於橫屏 你的視覺中看到的就是一下左圖中 寬 高
這就是需要把 offsetWidth 和 offsetHeight 換一下 才是右圖中列印出來的寬高 才是視覺中的寬高;
同理 小盒子的大小(16,17行)也需要換一下,儘管小盒子是一個正方形的 ;
這個是大盒子的間距; offsetLeft 和 offsetTop 也不是視覺中的left和top
var bigBox_l = bigBox.offsetLeft; var bigBox_t = bigBox.offsetTop ;
此時的大盒子的 offsetTop 為0 我就不在圖中標出來了;大家應該明白 就是圖中的右邊距離;
手機按下事件 這裡就不多說了 基本上就是按下(touchstart) 移動(touchmove ) 抬起 (touchend)
整體的邏輯 就是按下的時候 記錄一下滑鼠在小盒子裡面的位置
以下就是關鍵,弄不好滑鼠的位置就記錄錯了,我也是反反覆覆的想 才想明白;
我會用圖向大家解說
disX = bigbox_w - ev.touches[0].pageX - smallBox.offsetTop;
disY = ev.touches[0].pageY - bigBox_l;
滑鼠按下的值已經記錄完畢 然後就是滑鼠移動的時候 小球也要跟著動
var moveX = bigbox_w - e.touches[0].pageX - disX;
var moveY = e.touches[0].pageY - disY;
最後就是賦值
當然了 臨界值的話 比較好判斷 這裡就不多說了;
smallBox.style.top = moveX + 'px';
smallBox.style.left = moveY + 'px';
這裡需要注意的是 小盒子的top值 其實是你最後算出來的moveX 值;
left值 就是moveY 值;
寫了好久了 自己的能力有限 如果有更好的或者可以改進的方式 隨時等待大家的評論來指點,謝謝大家;