目录
第二步:设置元素拖拽事件--ondragstart 和 setData()
1.Html--地理定位
HTML 地理位置 API
定位用户位置
HTML 地理位置 API 用于获取用户的地理位置。
鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的。
用于定位用户的位置。
注释: 地理定位是最准确的设备与全球定位系统,如智能手机。
注释: 从 Chrome50 开始,地理位置 API 只在诸如 HTTPS 这样的安全上下文上工作。如果站点托管在非安全源(例如 HTTP)上,则获取用户位置的请求将不再起作用。
1.1.地理位置
getCurrentPosition()
方法用于返回用户的位置。
这里测试全部使用Edge浏览器,谷歌或者qq浏览器获取位置信息可能需要设置权限
<!DOCTYPE html>
<html>
<body>
<p>点击按钮获取您的坐标。</p>
<button onclick="getLocation()">试一试</button>
<p id="demo"></p>
<script>
var x = document.getElementById("demo");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, showError);
} else {
x.innerHTML = "此浏览器不支持地理定位。";
}
}
function showPosition(position) {
x.innerHTML = "Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude;
}
function showError(error) {
switch(error.code) {
case error.PERMISSION_DENIED:
x.innerHTML = "用户拒绝了地理定位请求。"
break;
case error.POSITION_UNAVAILABLE:
x.innerHTML = "位置信息不可用。"
break;
case error.TIMEOUT:
x.innerHTML = "获取用户位置的请求超时。"
break;
case error.UNKNOWN_ERROR:
x.innerHTML = "出现未知错误。"
break;
}
}
</script>
</body>
</html>
1.2.地图显示
要在地图中显示结果,您需要访问地图服务,如 Google 地图。
在下面的实例中,返回的纬度和经度用于在 Google 地图中显示位置(使用静态图像):
function showPosition(position) {
var latlon = position.coords.latitude + "," + position.coords.longitude;
var img_url = "https://maps.googleapis.com/maps/api/staticmap?center=
"+latlon+"&zoom=14&size=400x300&sensor=false&key=YOUR_KEY";
document.getElementById("mapholder").innerHTML = "<img src='"+img_url+"'>";
}
1.3.特定位置
本页演示了如何在地图上显示用户的位置。
地理定位对于特定位置的信息也非常有用,例如:
- 最新本地信息
- 显示用户附近的兴趣点
- 逐段导航(GPS)
getCurrentPosition()
方法在成功时返回一个对象。始终返回纬度、经度和精度属性。如果可用,则返回其他属性:
属性 | 返回数据 |
---|---|
coords.latitude | 以十进制数表示的纬度(始终返回) |
coords.longitude | 以十进制数表示的经度(始终返回) |
coords.accuracy | 位置的准确性(始终返回) |
coords.altitude | 平均海平面以上的海拔高度(如有返回) |
coords.altitudeAccuracy | 位置的高度精度(如有返回) |
coords.heading | 航向为从北顺时针方向的度数(如有返回) |
coords.speed | 以米/秒为单位的速度(如果可用,返回) |
timestamp | 响应的日期/时间(如果可用,则返回) |
地理定位对象还有其他有趣的方法:
watchPosition()
- 返回用户当前位置,并在用户移动时继续返回更新位置(如车内的GPS)。clearWatch()
- 停止watchPosition()
方法。
下面的实例显示watchPosition()
方法。您需要一个精确的GPS设备来测试(如智能手机),并且可以根据位置变化实时获取位置信息
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>自动实时定位</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 20px;
margin: 0;
}
#demo {
font-size: 15px;
line-height: 1.8;
color: #333;
text-align: left;
max-width: 500px;
margin: 20px auto;
padding: 15px;
border-radius: 8px;
background-color: #f9f9f9;
}
.loading {
color: #007acc;
font-style: italic;
}
.error {
color: red;
}
h2 {
color: #007acc;
}
</style>
</head>
<body>
<h2>📍 自动实时定位</h2>
<p>打开页面即自动获取您的位置,移动时信息会实时更新。</p>
<div id="demo">正在加载位置信息...</div>
<script>
const x = document.getElementById("demo");
let watchId = null;
// 页面加载完成后自动执行定位
window.onload = function () {
startLocation();
};
function startLocation() {
x.innerHTML = '<span class="loading">正在获取您的位置...</span>';
if (navigator.geolocation) {
watchId = navigator.geolocation.watchPosition(
showPosition,
showError,
{
enableHighAccuracy: true, // 使用 GPS 高精度
timeout: 10000,
maximumAge: 0,
distanceFilter: 5 // 每移动 5 米更新一次(部分设备支持)
}
);
} else {
x.innerHTML = '<span class="error">此浏览器不支持地理定位。</span>';
}
}
function showPosition(position) {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const accuracy = position.coords.accuracy; // 定位精度(米)
const speed = position.coords.speed; // 速度(m/s)
const altitude = position.coords.altitude; // 海拔(米),可能为 null
const timestamp = new Date(position.timestamp).toLocaleTimeString();
x.innerHTML = `
<strong>📍 当前位置</strong><br>
纬度: <strong>${lat.toFixed(6)}</strong><br>
经度: <strong>${lng.toFixed(6)}</strong><br>
精度: ±${accuracy} 米<br>
海拔: ${altitude ? altitude.toFixed(1) + ' 米' : '不可用'}<br>
速度: ${speed ? (speed * 3.6).toFixed(1) + ' km/h' : '0 km/h'}<br>
更新时间: ${timestamp}
`;
}
function showError(error) {
let message = "";
switch (error.code) {
case error.PERMISSION_DENIED:
message = "位置访问被拒绝,请检查浏览器权限设置。";
break;
case error.POSITION_UNAVAILABLE:
message = "无法获取位置信息,请检查 GPS 或网络。";
break;
case error.TIMEOUT:
message = "获取位置超时,请稍后重试。";
break;
default:
message = "未知错误,请重试。";
break;
}
x.innerHTML = `<span class="error">❌ ${message}</span>`;
}
// 可选:页面关闭或隐藏时停止监听,节省电量
window.addEventListener('beforeunload', function () {
if (watchId !== null) {
navigator.geolocation.clearWatch(watchId);
}
});
</script>
</body>
</html>
这里测试使用手机版qq浏览器测试。
2.Html--拖放
拖放是 HTML5 标准的组成部分:任何元素都是可拖放的。
拖放(Drag 和 Drop)是很常见的特性。它指的是您抓取某物并拖入不同的位置。
<!DOCTYPE HTML>
<html>
<head>
<style>
#div1 {
width: 350px;
height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
}
</style>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<p>将 W3Schools 图像拖到矩形中:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<img id="drag1" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="336" height="69">
</body>
</html>
这可能看起来很复杂,让我们来看看拖放事件的不同部分。
第一步:设置元素可拖拽--draggable
首先:要使元素可拖动,请将 draggable
属性设置为 true:
<img draggable="true">
第二步:设置元素拖拽事件--ondragstart 和 setData()
然后,规定当元素被拖动时发生的事情。
在上面的例子中,ondragstart
属性调用了一个 drag(event) 函数,规定拖动什么数据。
dataTransfer.setData()
方法设置拖动数据的数据类型和值:
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
在本例中,数据类型是 "text",而值是这个可拖动元素的 id ("drag1")。
第三步:设置拖到位置 - ondragover
ondragover
件规定被拖动的数据能够被放置到何处。
默认地,数据/元素无法被放置到其他元素中。为了实现拖放,我们必须阻止元素的这种默认的处理方式。
这个任务由 ondragover 事件的 event.preventDefault()
方法完成:
event.preventDefault()
第四步:进行放置 - ondrop
当放开被拖数据时,会发生 drop 事件。
在上面的实例中,ondrop 属性调用了一个函数 drop(event):
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
代码说明:
- 调用 preventDefault() 来阻止数据的浏览器默认处理方式(drop 事件的默认行为是以链接形式打开)
- 通过 dataTransfer.getData() 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据
- 被拖数据是被拖元素的 id("drag1")
- 把被拖元素追加到放置元素中
如何在两个 <div>元素之间来回拖放图像:
<!DOCTYPE HTML>
<html>
<head>
<style>
#div1, #div2 {
float: left;
width: 100px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
</style>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<h2>拖放</h2>
<p>在两个 div 元素之间来回拖动图像。</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<img src="img_w3slogo.gif" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
</body>
</html>
3.Html--本地存储
HTML 本地存储:优于 cookies。
通过本地存储(Local Storage),web 应用程序能够在用户浏览器中对数据进行本地的存储。
在 HTML5 之前,应用程序数据只能存储在 cookie 中,包括每个服务器请求。本地存储则更安全,并且可在不影响网站性能的前提下将大量数据存储于本地。
与 cookie 不同,存储限制要大得多(至少5MB),并且信息不会被传输到服务器。
本地存储经由起源地(origin)(经由域和协议)。所有页面,从起源地,能够存储和访问相同的数据。
HTML 本地存储对象
HTML 本地存储提供了两个在客户端存储数据的对象:
window.localStorage
- 存储没有截止日期的数据window.sessionStorage
- 针对一个 session 来存储数据(当关闭浏览器标签页时数据会丢失)
在使用本地存储时,请检测 localStorage 和 sessionStorage 的浏览器支持:
if (typeof(Storage) !== "undefined") {
// localStorage/sessionStorage 的代码。
} else {
// Sorry! 没有网络存储支持..
}
3.1.localStorage 对象
localStorage 对象存储的是没有截止日期的数据。当浏览器被关闭时数据不会被删除,在下一天、周或年中,都是可用的。
<!DOCTYPE html>
<html>
<body>
<div id="result"></div>
<script>
// Check browser support
if (typeof(Storage) !== "undefined") {
// Store
localStorage.setItem("lastname", "Smith");
// Retrieve
document.getElementById("result").innerHTML = localStorage.getItem("lastname");
} else {
document.getElementById("result").innerHTML = "抱歉,您的浏览器不支持网络存储...";
}
</script>
</body>
</html>
示例说明:
- 创建 localStorage 名称/值对,其中:name="lastname",value="Gates"
- 取回 "lastname" 的值,并把它插到 id="result" 的元素中
下面的例子对用户点击按钮的次数进行计数。在代码中,值字符串被转换为数值,依次对计数进行递增:
<!DOCTYPE html>
<html>
<head>
<script>
function clickCounter() {
if (typeof(Storage) !== "undefined") {
if (localStorage.clickcount) {
localStorage.clickcount = Number(localStorage.clickcount)+1;
} else {
localStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "You have clicked the button " + localStorage.clickcount + " time(s).";
} else {
document.getElementById("result").innerHTML = "抱歉,您的浏览器不支持网络存储...";
}
}
</script>
</head>
<body>
<p><button onclick="clickCounter()" type="button">单击我!</button></p>
<div id="result"></div>
<p>点击按钮可以看到计数器增加。</p>
<p>关闭浏览器选项卡(或窗口),重试,计数器会继续计数(不会重置)。</p>
</body>
</html>
3.2.sessionStorage 对象
sessionStorage
对象等同 localStorage 对象,不同之处在于只对一个 session 存储数据。如果用户关闭具体的浏览器标签页,数据也会被删除。
下例在当前 session 中对用户点击按钮进行计数:
<!DOCTYPE html>
<html>
<head>
<script>
function clickCounter() {
if (typeof(Storage) !== "undefined") {
if (sessionStorage.clickcount) {
sessionStorage.clickcount = Number(sessionStorage.clickcount)+1;
} else {
sessionStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "You have clicked the button " + sessionStorage.clickcount + " time(s) in this session.";
} else {
document.getElementById("result").innerHTML = "抱歉,您的浏览器不支持网络存储...";
}
}
</script>
</head>
<body>
<p><button onclick="clickCounter()" type="button">单击我!</button></p>
<div id="result"></div>
<p>点击按钮可以看到计数器增加。</p>
<p>关闭浏览器选项卡(或窗口),然后重试,计数器重置。</p>
</body>
</html>
4.Html--Web Workers API
web Workers 是在后台运行的 JavaScript,不会影响页面的性能。
在 HTML 页中执行脚本时,该页将变得无响应,直到脚本完成。
Web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 运行在后台。
<!DOCTYPE html>
<html>
<body>
<p>计数:<output id="result"></output></p>
<button onclick="startWorker()">开始工作</button>
<button onclick="stopWorker()">停止工作</button>
<p><strong>注意:</strong>Internet Explorer 9 及更早版本不支持 Web Workers。</p>
<script>
var w;
function startWorker() {
if (typeof(Worker) !== "undefined") {
if (typeof(w) == "undefined") {
// 使用 Blob 将 Worker 代码作为内联脚本
const workerScript = `
let count = 0;
setInterval(() => {
count++;
postMessage(count);
}, 500);
`;
// 创建一个 Blob 对象,类型为 JavaScript
const blob = new Blob([workerScript], { type: 'application/javascript' });
// 创建一个指向该 Blob 的 URL
const workerUrl = URL.createObjectURL(blob);
// 使用这个 URL 创建 Worker
w = new Worker(workerUrl);
}
w.onmessage = function(event) {
document.getElementById("result").innerHTML = event.data;
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support Web Workers...";
}
}
function stopWorker() {
if (w) {
w.terminate();
w = undefined;
}
}
</script>
</body>
</html>
注释: web worker 通常不用于如此简单的脚本,而是用于更耗费 CPU 资源的任务。
由于 web worker 位于外部文件中,它们无法访问下例 JavaScript 对象:
- window 对象
- document 对象
- parent 对象
5.Html--SSE
什么是 SSE(Server-Sent Events)?
SSE 是一种让服务器主动向浏览器推送数据的技术。它建立一个长期连接,服务器可以随时发送数据,浏览器通过 EventSource
API 接收。
✅ 特点:单向通信(服务器 → 浏览器)
对比:
- Ajax:浏览器请求,服务器响应(拉取)
- WebSocket:双向通信
- SSE:服务器主动推送,浏览器接收(推送)
const express = require('express');
const app = express();
// 静态文件服务(加载 public 文件夹下的 index.html)
app.use(express.static('public'));
// SSE 接口
app.get('/api/sse', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
});
// 每3秒发送一条普通消息
const messageInterval = setInterval(() => {
res.write(`data: 当前时间 ${new Date().toLocaleTimeString()}\n\n`);
}, 3000);
// 每5秒发送一个自定义事件(server-time)
const timeInterval = setInterval(() => {
res.write(`event: server-time\ndata: ${new Date().toISOString()}\nid: ${Date.now()}\n\n`);
}, 5000);
// 客户端断开时清理资源
req.on('close', () => {
console.log('客户端断开连接');
clearInterval(messageInterval);
clearInterval(timeInterval);
res.end();
});
});
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`🚀 服务器已启动:http://localhost:${PORT}`);
console.log(`👉 请在浏览器中访问:http://localhost:${PORT}`);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>SSE 测试</title>
</head>
<body>
<h1>🎉 SSE 实时消息</h1>
<div id="messages"></div>
<script>
if (typeof EventSource !== 'undefined') {
const es = new EventSource('/api/sse');
es.onmessage = function(event) {
const p = document.createElement('p');
p.textContent = '📩 ' + event.data;
document.getElementById('messages').appendChild(p);
};
} else {
document.body.innerHTML = '<p style="color:red;">❌ 浏览器不支持 SSE</p>';
}
</script>
</body>
</html>