H5内容之前一直没抽出时间整理,做个归纳使用的笔记。
记录包括一些新的标签、属性、新的api。
还有拖放drag、Web Workers、SSE与nodejs、WebSocket与nodejs的前后端详细使用案例
。
canvas
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">
</canvas>
</body>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
</script>
svg
<svg height="190">
<polygon points="100,10 40,180 190,60 10,60 160,180"
style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;">
</svg>
const test = () => {
//...执行内容
requestAnimationFrame(test)
}
test()
<video width="320" height="240" controls>
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
您的浏览器不支持Video标签。
</video>
<audio controls>
<source src="horse.ogg" type="audio/ogg">
<source src="horse.mp3" type="audio/mpeg">
您的浏览器不支持 audio 元素。
</audio>
被拖动的内容
draggable="true"
,表示允许被拖放。ondragstart
事件,表示拖放时储存的数据,可以将event作为入参,方便我们使用信息。 <img id="drag" src="./xx.jpg" draggable="true" ondragstart="drag(event)" width="336" height="69">
event.dataTransfer.setData
可以储存我们拖放时内容的信息,我们可以将id存入,入参前面是key,后面是value。 function drag(e) {
e.dataTransfer.setData("Text", e.target.id);
}
存放内容的容器或位置
ondragover
和ondrop
事件添加阻止默认事件。ondrop
事件,这个是鼠标将东西拖到该容器并松手时触发的事件,它可以用e.dataTransfer.getData
读取ondragstart
事件中使用event.dataTransfer.setData
储存的值。appendChild
将内容添加进自己的内容区。 <div id="box" ondrop="drop(event)" ondragover="allowDrop(event)">div>
function allowDrop(e) {
e.preventDefault();
}
function drop(e) {
e.preventDefault();
var id = e.dataTransfer.getData("Text");
e.target.appendChild(document.getElementById(id));
}
原理
draggable="true"
,当它被appendChild
调用添加进别的内容时,就会发生回流,让原来的被托放内容消失,就给人带来了拖放的效果。 <button onclick="test()">点击试试button>
function test() {
document.getElementById('box').appendChild(document.getElementById('drag'))
}
完整示例
<style>
#box {
width: 350px;
height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
}
style>
<body>
<p>拖动图片到矩形框中:p>
<div id="box" ondrop="drop(event)" ondragover="allowDrop(event)">div>
<br>
<img loading="lazy" id="drag" src="./xxx.jpg" ondragstart="drag(event)"
draggable="true" width="336" height="69">
<button onclick="test()">点击试试button>
body>
<script>
function allowDrop(e) {
e.preventDefault();
}
function drag(e) {
e.dataTransfer.setData("Text", e.target.id);
}
function drop(e) {
e.preventDefault();
var data = e.dataTransfer.getData("Text");
e.target.appendChild(document.getElementById(data));
}
function test() {
document.getElementById('box').appendChild(document.getElementById('drag'))
}
script>
navigator.geolocation.getCurrentPosition
获取位置,入参为函数。position.coords.longitude
和position.coords.latitude
。<body>
<p id="demo">点击按钮获取您当前坐标(可能需要比较长的时间获取):p>
<button onclick="getLocation()">点我button>
<script>
var x = document.getElementById("demo");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
else {
x.innerHTML = "该浏览器不支持获取地理位置。";
}
}
function showPosition(position) {
x.innerHTML = "纬度: " + position.coords.latitude +
"
经度: " + position.coords.longitude;
}
script>
body>
header,section, footer, aside, nav, main, article, figure
color,date,datetime,datetime-local,email,month,number,range,search,tel,time,url,week
datalist
input
的list
属性与datalist
的id
设置为相同的即可给input绑定一个待输入内容框,list
属性也是h5新的表单属性。 <input list="listName">
<datalist id="listName">
<option value="value1">
<option value="value2">
<option value="value3">
<option value="value4">
<option value="value5">
datalist>
<form oninput="x.value=parseInt(a.value)+parseInt(b.value)">0
<input type="range" id="a" value="50">100 +
<input type="number" id="b" value="50">=
<output name="x" for="a b"></output>
</form>
(已经常见的)
(不常见与不常用)
autocomplete
<form action="demo" autocomplete="on">
name:<input type="text" name="fname"><br>
E-mail: <input type="email" name="email" autocomplete="off"><br>
<input type="submit">
form>
type="email"
的input也允许随意输入。<form action="demo" novalidate>
E-mail: <input type="email" name="user_email">
<input type="submit">
form>
其他
还有一些关于覆盖表单属性的属性,个人并不常用,有兴趣自己查询:form 、formaction 、formenctype 、formmethod、formnovalidate 、formtarget 。
manifest="demo.appcache"
,并在html同源创建demo.appcache
Manifest文件就可以进行缓存,访问过的页面,离线了再次访问仍然可以访问。demo.appcache
CACHE MANIFEST
#v0.0.1
/index.html
/...
/...
if (typeof (Worker) !== undefined) {
console.log('支持Web worker')
}
test.js
let i = 0
setInterval(() => {
i++
//postMessage传递数据
postMessage(i)
}, 1000)
onmessage
监听web worker 文件的postMessage
事件,onmessage参数event中有一个data
属性就是从postMessage传来的。 let w
if (typeof (Worker) !== undefined) {
w = new Worker("/test.js")
}
w.onmessage = (event) => {
console.log(event.data)//1...2...3.....
}
w.terminate()
终止Web Worker<body>
<button onclick="start()">使用Web Worker</button>
<button onclick="stop()">终止Web Worker</button>
</body>
<script>
let w
const start = () => {
if (typeof (Worker) !== undefined) {
w = new Worker("/test.js")
}
w.onmessage = (e) => {
console.log(e.data)
}
}
const stop = () => {
w.terminate();
}
</script>
编写nodejs服务端
创建一个服务放在8844端口,我这里命名为/stream
,我用的express
,不喜欢的话用http
也行。
res.set
请求头的设置很关键,'Content-Type': 'text/event-stream'
这种是sse必须的类型,'Access-Control-Allow-Origin': '*'
解决跨域方便测试。
res.write
进行消息推送,因为要保持连接,所以肯定不能用send
。
import express from 'express'
const app = new express()
app.use(express.json())
app.get('/stream', (req, res) => {
res.set({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
'Access-Control-Allow-Origin': '*',
})
res.write('retry: 10000\n')
res.write('event: connecttime\n')
res.write('data: ' + new Date() + '\n\n')
res.write('data: ' + new Date() + '\n\n')
let interval = setInterval(function () {
res.write('data: ' + new Date() + '\n\n')
}, 1000)
req.connection.addListener(
'close',
function () {
clearInterval(interval)
},
false
)
})
app.listen(8844, () => {
console.log('开启')
})
// 以下是使用http的方案,同理
// import http from 'http'
// http
// .createServer(function (req, res) {
// var fileName = '.' + req.url
// if (fileName === './stream') {
// res.writeHead(200, {
// 'Content-Type': 'text/event-stream',
// 'Cache-Control': 'no-cache',
// Connection: 'keep-alive',
// 'Access-Control-Allow-Origin': '*',
// })
// res.write('retry: 10000\n')
// res.write('event: connecttime\n')
// res.write('data: ' + new Date() + '\n\n')
// res.write('data: ' + new Date() + '\n\n')
// let interval = setInterval(function () {
// res.write('data: ' + new Date() + '\n\n')
// }, 1000)
// req.connection.addListener(
// 'close',
// function () {
// clearInterval(interval)
// },
// false
// )
// }
// })
// .listen(8844, '127.0.0.1')
前端html页面
new EventSource('http://127.0.0.1:8844/stream')
请求对应的的服务。<body>
<div id="example">div>
body>
<script>
if (typeof (EventSource) !== "undefined") {
// 浏览器支持 Server-Sent
var source = new EventSource('http://127.0.0.1:8844/stream');
var div = document.getElementById('example');
source.onopen = function (event) {
div.innerHTML += 'Connection open ...
';
};
source.onerror = function (event) {
div.innerHTML += 'Connection close.
';
};
source.addEventListener('connecttime', function (event) {
div.innerHTML += ('Start time: '
+ event.data + '');
}, false);
source.onmessage = function (event) {
div.innerHTML += ('Ping: '
+ event.data + '');
};
}
script>
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
编写nodejs服务端
nodejs-websocket
。ws.createServer
创建服务,三个监听事件,close与error就不用讲了,text监听前客户端传递过来的消息。sendText
用于向客户端传递消息,实现双向通信。import ws from 'nodejs-websocket'
console.log('开始建立连接...')
const server = ws
.createServer(function (conn) {
conn.on('text', function (str) {
console.log('从客户端收到的信息:' + str)
conn.sendText('从服务端传来的信息:收到')
})
conn.on('close', function (code, reason) {
console.log('关闭连接')
})
conn.on('error', function (code, reason) {
console.log('异常关闭')
})
})
.listen(8001)
console.log('WebSocket建立完毕')
前端html页面
new WebSocket
连接ws服务端口,记得服务前加上ws:
。ws.send
向服务端发送消息。ws.onmessage
监听,可以在这里随时等待服务端传递信息回来。<body>
<div id="mess">正在连接...div>
<div class="values">
<div class="value" id="value1">西瓜div>
<div class="value" id="value2">苹果div>
<div class="value" id="value3">梨子div>
div>
<script>
const mess = document.getElementById("mess");
if (window.WebSocket) {
const ws = new WebSocket('ws://localhost:8001');
ws.onopen = function (e) {
console.log("连接服务器成功");
ws.send("瓦达西连接了服务器");
}
ws.onclose = function (e) {
console.log("服务器关闭");
}
ws.onerror = function () {
console.log("连接出错");
}
ws.onmessage = function (e) {
mess.innerHTML = "连接成功"
console.log(e)
}
document.querySelector(".values").onclick = function (e) {
const time = new Date();
ws.send(time + " 点击了“" + e.target.innerHTML + "”");
}
}
script>
body>