html5 地理定位
html5 Geolocation API用于獲得用戶的地理位置
鑒于該特性可能侵犯用戶的隱私,除非用戶同意,否則用戶位置信息是不可用的
注意:Geolocation(地理定位)對于擁有GPS的設(shè)備,地理定位更加精確
Geolocation API的主要方法是gerCurrentPositon,它用來獲得用戶的位置
下面是一個(gè)簡答的地理定位實(shí)例,可返回用戶位置的經(jīng)度和緯度:
var x=document.getElementById("demo");
function getLocation(){
if(navigator.geolocation){
navigator.geolocation.getCurrentLocation(showPositon);}
else{
x.innerHTML="該瀏覽器不支持獲取地理位置."}
}
function showPosition(position){
x.innerHTML="緯度:"+position.coords.latitude+
"<br>經(jīng)度:"+position.coords.longitude;}
實(shí)例解析:
●檢測是否支持地理定位
●如果支持,則運(yùn)行g(shù)erCurrentPosition()方法.如果不支持,則向用戶顯示一段信息
●如果getCurrentPostion()運(yùn)行成功,則向參數(shù)showPosition中規(guī)定的函數(shù)返回一個(gè)coordinates對象
●showPosition()函數(shù)獲得并顯示經(jīng)度和緯度
上面的例子是一個(gè)非常基礎(chǔ)的地理定位腳本,不含錯(cuò)誤處理
你需要先熟悉JavaScript才能理解和使用API
如果gerCurrentPosition()運(yùn)行成功,則getCurrentPosition()方法返回對象.始終返回latitude,longtitude以及accuracy屬性.如果可用,則會返回其他下面的屬性:
●coords.latitude:十進(jìn)制數(shù)的緯度
●coords.longtitude:十進(jìn)制的經(jīng)度
●coords.accuracy:位置精度
●coords.altitude:海拔,海平面以上以米計(jì)
●coords.altitudeAccuracy:位置的海拔精度
●coords.heading:方向,從正北開始以度計(jì)
●coords.speed:速度,以米/每秒計(jì)
●timestamp:響應(yīng)的日期/時(shí)間
二 html5 拖放
拖放(Drag和drop)是html5標(biāo)準(zhǔn)的組成部分
拖放是一種常見的特性,即抓取對象以后拖到另一個(gè)位置
在html5中,拖放是標(biāo)準(zhǔn)的一部分,任何元素都能夠拖放
★設(shè)置元素為可拖放
首先,為了使元素可拖動(dòng),需要把draggable屬性設(shè)置為true:
<img draggable="true">
★拖動(dòng)什么-ondragstart和setData()
然后,規(guī)定當(dāng)元素拖動(dòng)時(shí),會發(fā)生什么
dataTransfer.setData()方法,設(shè)置被拖數(shù)據(jù)的數(shù)據(jù)類型和值:
function drag(ev){
ev.dataTransfer.setData("Text",ev.target.id);}
在這個(gè)例子中,數(shù)據(jù)類型是"Text",值是可拖動(dòng)元素的id("drag1")
★放到何處-ondragover
ondragover時(shí)間規(guī)定在何處放置被拖動(dòng)的數(shù)據(jù)
默認(rèn)地,無法將數(shù)據(jù)/元素放置到其他元素中,如果需要設(shè)置允許放置,我們必須阻止元素的默認(rèn)處理方式.
這要通過調(diào)用ondragover時(shí)間的event.preventDefault()方法:
event.preventDefault()
★進(jìn)行放置-ondrop
當(dāng)放置被拖數(shù)據(jù)時(shí),會發(fā)生drop事件
function drop(ev){
ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));}
三 html5 SVG
什么是SVG?
●SVG指可伸縮矢量圖形(Scalable Vector Graphics)
●SVG用于定義用于網(wǎng)絡(luò)的基于矢量的圖形
●SVG使用XML格式定義圖形
●SVG圖像在放大或改變尺寸的情況下其圖形質(zhì)量不會損失
●SVG是萬維聯(lián)盟的標(biāo)準(zhǔn)
在html5中,你能夠直接將SVG元素嵌入html頁面中
要使用SVG繪制圖形,你首先需要?jiǎng)?chuàng)建一個(gè)<svg>標(biāo)簽
<svg width="1000" height="1000"></svg>
要?jiǎng)?chuàng)建一個(gè)圓形,需要添加一個(gè)<circle>標(biāo)簽
下面是SVG代碼:
<svg width="1000" height="1000">
<circle cx="100" cy="50" r="40" fill="red" />
</svg>
●cx和cy屬性定義圓點(diǎn)的x和y坐標(biāo).如果省略cx和cy,圓的中心會被設(shè)置為(0,0)
●r屬性定義圓的半徑
運(yùn)行效果如下:
畫布坐標(biāo)、屏幕坐標(biāo)的概念
幾何變換:平移、縮放、旋轉(zhuǎn)
Canvas 中的所有幾何變換針對的不是繪制的圖形,而是針對畫布本身,也就是說,當(dāng)移動(dòng)、縮放、旋轉(zhuǎn)畫布之后,新的坐標(biāo)系只對新的操作生效
參考:
示例代碼
const canvas = document.getElementById("canvas");
const context = convas.getContext("2d");
context.fillRect(100, 100, 50, 50);
Canvas的繪制和html的繪制是不一樣的,html的繪制是增量的,當(dāng)變化時(shí),只會重新繪制變化的部分,沒有變化的部分是不會重新繪制的,但是canvas不一樣,每次都是全量繪制的,如果一個(gè)canvas里有很多圖形,當(dāng)改變一個(gè)圖形時(shí),需要重新繪制所有圖形才可以(當(dāng)然,可以用clearRect擦除部分區(qū)域,但一般很少這么用)。
了解canvas的繪制規(guī)則之后,就很容易發(fā)現(xiàn)性能問題,如果canvas上繪制了大量的圖形(成千上萬個(gè)),每次重繪就需要很長的時(shí)間,如果重繪的頻率很高,那么就會有性能問題
那么如何解決這個(gè)問題呢,目前有以下幾種方案
圖層的概念來自于PS,每一個(gè)圖層都是一個(gè)canvas,既然在一個(gè)canvas上繪制太多圖形會有性能問題,那么就分幾個(gè)圖層,每次僅重新繪制其中一個(gè)圖層,每個(gè)圖層的圖形都不會很多,那么即使重繪的頻率很高,也不會有性能問題。圖層的概念圖如下:
這里用背景顏色只是示意,實(shí)際上圖層都是透明
代碼實(shí)現(xiàn)
用一個(gè)父元素作為容器,把所有的元素設(shè)置成一樣的寬高并放在里面重疊。
<div class="container">
<canvas width="500" height="500"></canvas>
<canvas width="500" height="500"></canvas>
<canvas width="500" height="500"></canvas>
<canvas width="500" height="500"></canvas>
<canvas width="500" height="500"></canvas>
</div>
繪制是很耗性能的,如果每次都清空畫布然后重新畫一次,那么性能會消耗很大(即使分了幾個(gè)圖層),我們應(yīng)區(qū)分“變”與“不變”的部分,只對“變”的部分重新渲染,“不變”的部分不渲染,將經(jīng)常變化的部分抽離到臨時(shí)圖層,這樣僅需要渲染臨時(shí)圖層,臨時(shí)圖層有幾種實(shí)現(xiàn)思路,一種是使用操作圖層(俗稱高性能圖層),一種是使用隱藏圖層(不繪制到界面上的)
高性能圖層
一般高頻(實(shí)時(shí)響應(yīng)鼠標(biāo)、鍵盤等事件)的操作會放在高性能圖層,等操作完成之后,再將最終結(jié)果保存到其它圖層,比如繪制、拖拽、縮放一個(gè)(或一批)shape
隱藏圖層
有些圖層是不用給用戶看的,這些canvas僅存在于內(nèi)存中,不會插入html的dom中,用完就銷毀,比如常見的canvas to image。
還有一種實(shí)現(xiàn)方式是離屏渲染(OffscreenCanvas),先在一個(gè)offCanvas操作,然后再將結(jié)果渲染到界面上(有點(diǎn)像虛擬dom操作),一般會結(jié)合webworker或webassembly
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
// 繪制圖片,或其它操作
context.drawImage();
// 轉(zhuǎn)成base64圖片
convas.toDataUrl();
影響canvas性能的除了繪制頻率,還有一個(gè)重要的是像素點(diǎn)操作,一般圖像處理會涉及到大量的像素點(diǎn)操作,如果放在主線程計(jì)算,那么會卡住其它操作,造成頁面卡頓,特別影響用戶體驗(yàn),這些涉及大量計(jì)算的一般會單獨(dú)開個(gè)線程來操作,而在瀏覽器中有這個(gè)能力的就只有webworker了。
有了webworker可能還不夠,因?yàn)槭冀K是在js上執(zhí)行,js執(zhí)行效率天生就比其它語言慢,所以一般的會使用webassembly,執(zhí)行效率比js快很多,而且還能用到更豐富的圖像處理庫
如果還有更高的性能要求,那么普通的2d canvas可能就無法滿足了,這個(gè)時(shí)候可以使用webgl,性能更高(當(dāng)然學(xué)習(xí)成本也更高),再結(jié)合wasm,就可以有無限想象力了,鼎鼎大名的figma就是用webgl + wasm(rust)實(shí)現(xiàn)的,另外google doc在線文檔也使用了webgl,飛書文檔將來也會替換成wegbl,基于瀏覽器的渲染始終有諸多限制,一般有能力的都會實(shí)現(xiàn)自己的渲染引擎。
假設(shè)canvas大小為(867,350)
圖片的大小為(768,576)
將上面這張圖片放到canvas中,圖片貼邊處理,也即圖片太大就縮小,圖片太小就放大。那么我們?nèi)绾螌?shí)現(xiàn)這種效果呢?
總結(jié)一下,總共分為幾步:
canvas的執(zhí)行細(xì)節(jié)如下:
有時(shí)候,我們想閱讀頁面中某段精彩的內(nèi)容,但由于頁面太長,用戶需要自己滾動(dòng)頁面,查找起來非常麻煩 ,很容易讓人失去繼續(xù)往下閱讀的興趣。這樣體驗(yàn)非常不好,所以我們可以想辦法 實(shí)現(xiàn)點(diǎn)擊某段文字或者圖片跳轉(zhuǎn)到頁面指定位置,方便用戶的閱讀。
這里作為錨點(diǎn)的標(biāo)簽可以是任意元素。
<a href="#aa">跳轉(zhuǎn)到 id 為 aa 標(biāo)記的錨點(diǎn)</a>
<p>-------------分隔線-------------</p>
<div id="aa">a</div>
這里作為錨點(diǎn)的標(biāo)簽只能是 a 標(biāo)簽。
<a href="#bb" >跳轉(zhuǎn)到 name 為 bb 的 a 標(biāo)簽錨點(diǎn)</a>
<p>-------------分隔線-------------</p>
<a name="bb">name 為 bb 的 a 標(biāo)簽的錨點(diǎn)</a>
<div id="abb">bbb</div>
注意:當(dāng)以 ' a 標(biāo)簽 name 屬性作為錨點(diǎn) ' 和 ' 利用 id 為標(biāo)記的錨點(diǎn) ' 同時(shí)出現(xiàn)(即以 name 為錨點(diǎn)和以 id 為錨點(diǎn)名字相同時(shí)),會將后者作為錨點(diǎn)。
window.scrollTo 滾動(dòng)到文檔中的某個(gè)坐標(biāo)。可提供滑動(dòng)效果,想具體了解 scrollTo() 可以看看 MDN 中的介紹。
話不多說,看下面代碼
「html 部分」:
<a id="linkc">平滑滾動(dòng)到 c</a>
<p>-------------分隔線-------------</p>
<div id="cc">c</div>
「js 部分」:
var linkc = document.querySelector('#linkc')
var cc = document.querySelector('#cc')
function to(toEl) {
// toEl 為指定跳轉(zhuǎn)到該位置的DOM節(jié)點(diǎn)
let bridge = toEl;
let body = document.body;
let height = 0;
// 計(jì)算該 DOM 節(jié)點(diǎn)到 body 頂部距離
do {
height += bridge.offsetTop;
bridge = bridge.offsetParent;
} while (bridge !== body)
// 滾動(dòng)到指定位置
window.scrollTo({
top: height,
behavior: 'smooth'
})
}
linkc.addEventListener('click', function () {
to(cc)
});
Element.scrollIntoView() 方法讓當(dāng)前的元素滾動(dòng)到瀏覽器窗口的可視區(qū)域內(nèi)。想具體了解 scrollIntoView() 可以看看 MDN 中的介紹。
下面也直接上代碼
「html 部分」:
<a onclick="goTo()">利用 scrollIntoView 跳轉(zhuǎn)到 d</a>
<p>-------------分隔線-------------</p>
<div id="dd">ddd</div>
「js 部分」:
var dd = document.querySelector('#dd')
function goTo(){
dd.scrollIntoView()
}
注意:此功能某些瀏覽器尚在開發(fā)中,請參考瀏覽器兼容性表格以得到在不同瀏覽器中適合使用的前綴。由于該功能對應(yīng)的標(biāo)準(zhǔn)文檔可能被重新修訂,所以在未來版本的瀏覽器中該功能的語法和行為可能隨之改變。
下面為了方便看效果,把上面的代碼整理在一起。
<!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>
div {
width: 600px;
height: 300px;
background-color: pink;
}
</style>
</head>
<body>
<a href="#aa">跳轉(zhuǎn)到以 id 為 aa 標(biāo)記的錨點(diǎn) a</a>
<p>-------------分隔線-------------</p>
<a name="aa">hhh</a>
<div id="aa">aa</div>
<a href="#bb" >跳轉(zhuǎn)到 name 為 bb 的 a 標(biāo)簽錨點(diǎn)</a>
<p>-------------分隔線-------------</p>
<a name="bb">name 為 bb 的 a 標(biāo)簽的錨點(diǎn)</a>
<p>-------------分隔線-------------</p>
<div>bb</div>
<a id="linkc">平滑滾動(dòng)到 c</a>
<p>-------------分隔線-------------</p>
<div id="cc">cc</div>
<a onclick="goTo()">利用 scrollIntoView 跳轉(zhuǎn)到 d</a>
<p>-------------分隔線-------------</p>
<div id="dd">dd</div>
<p>-------------分隔線-------------</p>
<div></div>
</body>
<script>
var cc = document.querySelector('#cc')
var linkc = document.querySelector('#linkc')
function to(toEl) {
//ele為指定跳轉(zhuǎn)到該位置的DOM節(jié)點(diǎn)
let bridge = toEl;
let body = document.body;
let height = 0;
do {
height += bridge.offsetTop;
bridge = bridge.offsetParent;
} while (bridge !== body)
console.log(height)
window.scrollTo({
top: height,
behavior: 'smooth'
})
}
linkc.addEventListener('click', function () {
to(cc)
});
</script>
<script>
var dd = document.querySelector('#dd')
function goTo(){
dd.scrollIntoView()
}
</script>
</html>
效果圖:
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。