當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
原生JS仿写手机指南针(带水平仪)
生活随笔
收集整理的這篇文章主要介紹了
原生JS仿写手机指南针(带水平仪)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
歷時半年整理出了十多萬字的學習筆記,目前依舊在更新
歡迎點贊和支持~🥳🥳🥳
博客
主要運用技術: css3旋轉和H5定位配合js實現
因為PC端沒有陀螺儀,H5的GetCurrentPosition定位自己玩還要翻墻,所以我只得用移動端過下癮。我用的是Android機,所以沒有兼容IO。
寫在前面
- 首先要開發這種頁面需要你手機與你的電腦在一個局域網內,你還要一個服務器。我用WampServer64位騰訊管家里下的,現在不需要改服務器里的文件,直接可以用,其余的請自行百度,但一定不要在你需要用服務器打開的文件出現中文文件夾,答應我!
- 開發的這個指南針(實際上是指北的,姑且這么叫吧)其實并不準,是非常的不準,常常是與手機自帶的指南針對準后,沒過一會就偏了個40多度,定位就別想了。其實準的就是IOS的定位了,它有專門監聽與正北方向的角度偏差,并實時調整。
- 定位自己經緯度的方法目前最方便的只有API了;建議用騰訊地圖的,響應快,可以定位到市,但一天請求不了多少次,好像是5次吧;所以當你請求到了位置,就復制下來,答應我!
- 仿寫的是華為手機自帶的指南針
廢話講完,慣例先來個圖(手機瀏覽器上打開的)
html部分
<div class="show"><div class="wrapper"><div class="box"><div class="text"><div class="direction-angle">西北 123°</div><div class="latitude">北緯 <span>123°5'23"</span></div><div class="longitude">東經 <span> 123°5'23"</span></div></div><!-- 指針 --><div class="point"></div><!-- 表盤 --><div class="dial"><!-- 刻度 --><div class="scale"><ul><!-- 自己生成--><li>*100<li>*80</ul></div><!-- 數字 --><div class="num"><ul><li>0</li><li>20</li><li>40</li><li>60</li><li>80</li><li>100</li><li>120</li><li>140</li><li>160</li><li>180</li><li>200</li><li>220</li><li>240</li><li>260</li><li>280</li><li>300</li><li>320</li><li>340</li></ul><div class="sign"></div><div class=" direction north"><span>北</span></div><div class=" direction east"><span>東</span></div><div class=" direction south"><span>南</span></div><div class=" direction western"><span>西</span></div></div></div><!-- 中心水平儀 --><div class="gradienter-in"></div></div><!-- 第二頁水平儀 --><div class="gradienter-out"><span><div>12°</div></span></div></div></div>css部分
* {padding: 0px;margin: 0px;list-style: none;}:root,body {height: 100%;}body {height: 100%;display: flex;justify-content: center;}.show {height: 95%;width: 350px;transform: translate3D(0px, 20px, 0px);}.wrapper {position: relative;width: 700px;height: 100%;display: flex;}/* 第二頁水平儀 */.wrapper .gradienter-out {position: relative;height: 100%;width: 350px;}.wrapper .gradienter-out span {position: absolute;left: calc(50% - 50px);top: calc(50% - 50px);height: 100px;width: 100px;border-radius: 50%;}.wrapper .gradienter-out span div {position: absolute;height: 50px;width: 100px;top: calc(50% - 25px);text-align: center;line-height: 50px;font-size: 30px;font-weight: bold;transform-origin: center center;}/* 第一頁 */.box {position: relative;width: 350px;height: 100%;}/* 方向文字、經緯度 */.box .text {position: absolute;width: 350px;height: 120px;left: calc(50% - 175px);top: 20px;font-size: 13px;font-weight: bold;}.box .text .direction-angle {height: 50px;line-height: 50px;text-align: center;font-size: 30px;margin-bottom: 10px;}.box .text .latitude {float: left;margin-left: 50px;color: rgba(0, 0, 0, .5)}.box .text .longitude {float: right;margin-right: 50px;color: rgba(0, 0, 0, .5)}/* 指針 */.box .point {position: absolute;height: 25px;width: 2px;left: 50%;top: 165px;background-color: black;z-index: 10;}/* 表盤 */.box .dial {position: relative;height: 300px;width: 300px;top: 170px;left: calc(50% - 155px);transform-origin: 158px 111px;}/* 外圈表盤刻度 */.box .dial .scale {position: absolute;height: 300px;width: 300px;border-radius: 50%;transform-origin: 150px 150px;transform: translatez(0px) rotate(11deg);}/* 小刻度 */.box .dial .scale ul li {position: absolute;left: calc(50% - 1px);width: 2px;height: 10px;background-color: #ddd;transform-origin: center 110px;}/* 中刻度 */.box .dial .scale ul li:nth-of-type(5n) {height: 12px;}/* 大刻度 */.box .dial .scale ul li:nth-of-type(10n) {height: 15px;background-color: rgba(0, 0, 0, .5);}/* 數字和方向 */.box .dial .num ul li,.box .dial .num .direction {position: absolute;height: 25px;width: 34px;left: calc(50% - 10px);top: 20px;text-align: center;line-height: 25px;font-family: '宋體';font-weight: 500;font-size: 10px;transform-origin: center 90px;}.box .dial .num .direction {top: 55px;transform-origin: center 55px;}/* 紅色小標記 */.dial .num .sign {position: absolute;left: calc(50% - 4px);top: 30px;border-top: 10px solid transparent;border-left: 10px solid transparent;border-right: 10px solid transparent;border-bottom: 10px solid red;}.dial .num .direction span {position: absolute;display: block;height: 100%;width: 100%;text-align: center;transform-origin: center;}.north {color: red;}.box .gradienter-in {position: relative;left: calc(50% - 10px);top: -6%;height: 30px;width: 30px;border-radius: 50%;box-sizing: border-box;transform-origin: center;}騰訊地圖API組件
<iframe id="geoPage" width=0 height=0 frameborder=0 style="display:none" scrolling="no" src="https://apis.map.qq.com/tools/geolocation?key=你的秘鑰&referer=myapp" frameborder="0">javaScript部分
// 獲取經緯度// 這是騰訊地圖API定義好的事件// window.addEventListener("message", function(e) {// var loc = e.data; 第一次獲取到了保存好var loc = {module: 'geolocation',nation: '中國',province: '廣東省',city: '深圳市',lat: '22.532332',lng: '113.936553',}//將得到的經緯度轉換后渲染到頁面oLatitudeSpan.innerHTML = parseInt(loc.lat) + '°' + parseInt((loc.lat - parseInt(loc.lat)) * 60) + "′" + parseInt(((loc.lat - parseInt(loc.lat)) * 60 - parseInt((loc.lat - parseInt(loc.lat)) * 60)) * 60) + "″";oLongitudeSpan.innerHTML = parseInt(loc.lng) + '°' + parseInt((loc.lng - parseInt(loc.lng)) * 60) + "′" + parseInt(((loc.lng - parseInt(loc.lng)) * 60 - parseInt((loc.lng - parseInt(loc.lng)) * 60)) * 60) + "″";//},false)封裝一個讓元素繞著表盤中心旋轉的函數
// 讓元素圍成一圈function rotateDom(domArr, deg) {Array.prototype.slice.call(domArr, 0).forEach(function (ele, index) {ele.style.transform = 'translatez(0px) rotate(' + deg * index + 'deg)';})}綁定獲取設備方位信息事件
window.addEventListener("deviceorientation", function (e) {if (e.alpha) {// 初始化表盤rotateDom(oScaleLiArr, 2)rotateDom(oNumLiArr, 20)rotateDom(oDirectionLiArr, 90)// 指北針oDial.style.transform = "translatez(0px) rotate(" + Math.round(e.alpha) + "deg)";var str = '';var dic = (Math.round((e.alpha) / 45) + 8) % 8;switch (dic) {case 0:str = "北 ";break;case 1:str = "西北 ";break;case 2:str = "西 ";break;case 3:str = "西南 ";break;case 4:str = "南 ";break;case 5:str = "東南 ";break;case 6:str = "東 ";break;case 7:str = "東北 ";break;};// 方向角度 oDirecrionAngle.innerHTML = str + Math.abs(Math.round(360 - e.alpha)) + '°';// 第一頁的水平儀和方位文字歸正oGradienterIn.style.transform = 'translate3D(0px, 0px, 0px) rotate(' + -Math.round(e.alpha) + 'deg)';oNorthSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha) + 'deg)';oEastSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha + 90) + 'deg)';oSouthSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha + 180) + 'deg)';oWesternSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha - 90) + 'deg)';// 水平儀 必須這么寫,否則不識別,注意每個值都要空格隔開 (得出的角度較大,為了美觀除以一個數)oGradienterOutSpan.style.cssText = "box-shadow: rgb(136, 135, 135) " + -Math.round(e.gamma) / 2 + "px " + -Math.round(e.beta) / 2 + "px 0px 0px, rgb(0, 0, 0) " + -Math.round(e.gamma) / 2 + "px " + -Math.round(e.beta) / 2 + "px 0px 0px inset;";oGradienterIn.style.cssText = "box-shadow: rgb(136, 135, 135) " + -Math.round(e.gamma) / 5 + "px " + -Math.round(e.beta) / 5 + "px 0px 0px, rgb(0, 0, 0) " + -Math.round(e.gamma) / 5 + "px " + -Math.round(e.beta) / 5 + "px 0px 0px inset;";// 指針指到正北時,指針變紅;if ((e.alpha) % 360 < 1 || (e.alpha) % 360 > 359) {oPoint.style.backgroundColor = "#f00";} else {oPoint.style.backgroundColor = "#000"}// 第二頁// 設備哪個軸偏轉量大就讓圓圈里顯示誰的值if (e.beta > e.gamma) {oGradienterOutSpan.style.transform = 'translate3D(0px, 0px, 0px) rotate(' - Math.round(e.beta) + 'deg)'oGradienterOutDiv.innerHTML = Math.abs(Math.round(e.beta)) + '°';} else {oGradienterOutDiv.innerHTML = Math.abs(Math.round(e.gamma)) + '°';}} else {alert("您的設備不支持Deviceorientation功能,請用Android設備打開!")}}, false)關于指南針判斷方位部分畫了張圖便于理解
以上,寫的還是有些匆忙,切頁的功能實現的還沒有擴大寬度來的美觀一點,老是一卡一卡的,還有就是第二屏的角度會隨著重力的方向排布。完整代碼
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {padding: 0px;margin: 0px;list-style: none;}:root,body {height: 100%;}body {height: 100%;display: flex;justify-content: center;}.show {height: 95%;width: 350px;transform: translate3D(0px, 20px, 0px);}.wrapper {position: relative;width: 700px;height: 100%;display: flex;}/* 第二頁水平儀 */.wrapper .gradienter-out {position: relative;height: 100%;width: 350px;}.wrapper .gradienter-out span {position: absolute;left: calc(50% - 50px);top: calc(50% - 50px);height: 100px;width: 100px;border-radius: 50%;}.wrapper .gradienter-out span div {position: absolute;height: 50px;width: 100px;top: calc(50% - 25px);text-align: center;line-height: 50px;font-size: 30px;font-weight: bold;transform-origin: center center;}/* 第一頁 */.box {position: relative;width: 350px;height: 100%;}/* 方向文字、經緯度 */.box .text {position: absolute;width: 350px;height: 120px;left: calc(50% - 175px);top: 20px;font-size: 13px;font-weight: bold;}.box .text .direction-angle {height: 50px;line-height: 50px;text-align: center;font-size: 30px;margin-bottom: 10px;}.box .text .latitude {float: left;margin-left: 50px;color: rgba(0, 0, 0, .5)}.box .text .longitude {float: right;margin-right: 50px;color: rgba(0, 0, 0, .5)}/* 指針 */.box .point {position: absolute;height: 25px;width: 2px;left: 50%;top: 165px;background-color: black;z-index: 10;}/* 表盤 */.box .dial {position: relative;height: 300px;width: 300px;top: 170px;left: calc(50% - 155px);transform-origin: 158px 111px;}/* 外圈表盤刻度 */.box .dial .scale {position: absolute;height: 300px;width: 300px;border-radius: 50%;transform-origin: 150px 150px;transform: translatez(0px) rotate(11deg);}/* 小刻度 */.box .dial .scale ul li {position: absolute;left: calc(50% - 1px);width: 2px;height: 10px;background-color: #ddd;transform-origin: center 110px;}/* 中刻度 */.box .dial .scale ul li:nth-of-type(5n) {height: 12px;}/* 大刻度 */.box .dial .scale ul li:nth-of-type(10n) {height: 15px;background-color: rgba(0, 0, 0, .5);}/* 數字和方向 */.box .dial .num ul li,.box .dial .num .direction {position: absolute;height: 25px;width: 34px;left: calc(50% - 10px);top: 20px;text-align: center;line-height: 25px;font-family: '宋體';font-weight: 500;font-size: 10px;transform-origin: center 90px;}.box .dial .num .direction {top: 55px;transform-origin: center 55px;}/* 紅色小標記 */.dial .num .sign {position: absolute;left: calc(50% - 4px);top: 30px;border-top: 10px solid transparent;border-left: 10px solid transparent;border-right: 10px solid transparent;border-bottom: 10px solid red;}.dial .num .direction span {position: absolute;display: block;height: 100%;width: 100%;text-align: center;transform-origin: center;}.north {color: red;}.box .gradienter-in {position: relative;left: calc(50% - 10px);top: -6%;height: 30px;width: 30px;border-radius: 50%;box-sizing: border-box;transform-origin: center;}</style> </head><body><div class="show"><div class="wrapper"><div class="box"><div class="text"><div class="direction-angle">西北 123°</div><div class="latitude">北緯 <span>123°5'23"</span></div><div class="longitude">東經 <span> 123°5'23"</span></div></div><!-- 指針 --><div class="point"></div><!-- 表盤 --><div class="dial"><!-- 刻度 --><div class="scale"><ul><li>*180</ul></div><!-- 數字 --><div class="num"><ul><li>0</li><li>20</li><li>40</li><li>60</li><li>80</li><li>100</li><li>120</li><li>140</li><li>160</li><li>180</li><li>200</li><li>220</li><li>240</li><li>260</li><li>280</li><li>300</li><li>320</li><li>340</li></ul><div class="sign"></div><div class=" direction north"><span>北</span></div><div class=" direction east"><span>東</span></div><div class=" direction south"><span>南</span></div><div class=" direction western"><span>西</span></div></div></div><!-- 中心水平儀 --><div class="gradienter-in"></div></div><!-- 第二頁水平儀 --><div class="gradienter-out"><span><div>12°</div></span></div></div></div><!-- <iframe id="geoPage" width=0 height=0 frameborder=0 style="display:none" scrolling="no" src="https://apis.map.qq.com/tools/geolocation?key=TMBBZ-5GYCP-AFQDK-L2QCS-K3323-HFBAX&referer=myapp" frameborder="0"></iframe> --><script>var oScaleLiArr = document.getElementsByClassName('scale')[0].getElementsByTagName('li');var oNumLiArr = document.getElementsByClassName('num')[0].getElementsByTagName('li');var oDirectionLiArr = document.getElementsByClassName('direction');var oLatitudeSpan = document.getElementsByClassName('latitude')[0].getElementsByTagName('span')[0]var oLongitudeSpan = document.getElementsByClassName('longitude')[0].getElementsByTagName('span')[0];var oGradienterOutSpan = document.getElementsByClassName('gradienter-out')[0].getElementsByTagName('span')[0];var oGradienterOutDiv = document.getElementsByClassName('gradienter-out')[0].getElementsByTagName('div')[0];var oGradienterIn = document.getElementsByClassName('gradienter-in')[0];var oDial = document.getElementsByClassName('dial')[0];var oPoint = document.getElementsByClassName('point')[0];var oNorthSpan = document.getElementsByClassName('north')[0].getElementsByTagName('span')[0];var oEastSpan = document.getElementsByClassName('east')[0].getElementsByTagName('span')[0];var oSouthSpan = document.getElementsByClassName('south')[0].getElementsByTagName('span')[0];var oWesternSpan = document.getElementsByClassName('western')[0].getElementsByTagName('span')[0];var oDirecrionAngle = document.getElementsByClassName('direction-angle')[0];// 讓元素圍成一圈function rotateDom(domArr, deg) {Array.prototype.slice.call(domArr, 0).forEach(function (ele, index) {ele.style.transform = 'translatez(0px) rotate(' + deg * index + 'deg)';})}// 獲取經緯度// 這是騰訊地圖API定義好的事件// window.addEventListener("message", function(e) {// var loc = e.data; 瞎寫的定位var loc = {module: 'geolocation',nation: '中國',province: '廣東省',city: '深圳市',lat: '22.532332',lng: '113.936553',}oLatitudeSpan.innerHTML = parseInt(loc.lat) + '°' + parseInt((loc.lat - parseInt(loc.lat)) * 60) + "′" + parseInt(((loc.lat - parseInt(loc.lat)) * 60 - parseInt((loc.lat - parseInt(loc.lat)) * 60)) * 60) + "″";oLongitudeSpan.innerHTML = parseInt(loc.lng) + '°' + parseInt((loc.lng - parseInt(loc.lng)) * 60) + "′" + parseInt(((loc.lng - parseInt(loc.lng)) * 60 - parseInt((loc.lng - parseInt(loc.lng)) * 60)) * 60) + "″";// }, false);// 綁定獲取設備方位信息事件window.addEventListener("deviceorientation", function (e) {if (e.alpha) {// 初始化表盤rotateDom(oScaleLiArr, 2)rotateDom(oNumLiArr, 20)rotateDom(oDirectionLiArr, 90)// 指北針oDial.style.transform = "translatez(0px) rotate(" + Math.round(e.alpha) + "deg)";var str = '';// 判斷方位var dic = (Math.round((e.alpha) / 45) + 8) % 8;switch (dic) {case 0:str = "北 ";break;case 1:str = "西北 ";break;case 2:str = "西 ";break;case 3:str = "西南 ";break;case 4:str = "南 ";break;case 5:str = "東南 ";break;case 6:str = "東 ";break;case 7:str = "東北 ";break;};// 方向角度 oDirecrionAngle.innerHTML = str + Math.abs(Math.round(360 - e.alpha)) + '°';// 第一頁的水平儀和方位文字歸正oGradienterIn.style.transform = 'translate3D(0px, 0px, 0px) rotate(' + -Math.round(e.alpha) + 'deg)';oNorthSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha) + 'deg)';oEastSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha + 90) + 'deg)';oSouthSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha + 180) + 'deg)';oWesternSpan.style.transform = 'translatez(0px) rotate(' + -Math.round(e.alpha - 90) + 'deg)';// 水平儀 必須這么寫,否則不識別,注意每個值都要空格隔開 (得出的角度較大,為了美觀除以一個數)oGradienterOutSpan.style.cssText = "box-shadow: rgb(136, 135, 135) " + -Math.round(e.gamma) / 2 + "px " + -Math.round(e.beta) / 2 + "px 0px 0px, rgb(0, 0, 0) " + -Math.round(e.gamma) / 2 + "px " + -Math.round(e.beta) / 2 + "px 0px 0px inset;";oGradienterIn.style.cssText = "box-shadow: rgb(136, 135, 135) " + -Math.round(e.gamma) / 5 + "px " + -Math.round(e.beta) / 5 + "px 0px 0px, rgb(0, 0, 0) " + -Math.round(e.gamma) / 5 + "px " + -Math.round(e.beta) / 5 + "px 0px 0px inset;";// 指針指到正北時,指針變紅;if ((e.alpha) % 360 < 1 || (e.alpha) % 360 > 359) {oPoint.style.backgroundColor = "#f00";} else {oPoint.style.backgroundColor = "#000"}// 第二頁// 設備哪個軸偏轉量大就讓圓圈里顯示誰的值if (e.beta > e.gamma) {oGradienterOutSpan.style.transform = 'translate3D(0px, 0px, 0px) rotate(' - Math.round(e.beta) + 'deg)'oGradienterOutDiv.innerHTML = Math.abs(Math.round(e.beta)) + '°';} else {oGradienterOutDiv.innerHTML = Math.abs(Math.round(e.gamma)) + '°';}} else {alert("您的設備不支持Deviceorientation功能,請用Android設備打開!")}}, false)</script></body></html>總結
以上是生活随笔為你收集整理的原生JS仿写手机指南针(带水平仪)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么叫死区时间_死区时间控制
- 下一篇: Full Transportable E