首页 > 其他分享 >系统化学习前端之HTML篇(02)

系统化学习前端之HTML篇(02)

时间:2023-02-20 16:46:34浏览次数:64  
标签:02 10 ctx HTML error position 100 绘制 系统化

写在前面

前面已经梳理了HTML的基础标签使用,常规开发的话,基础标签已经完全满足日常工作了。但是,我们往往不满足于简单的页面,还需要提升,这个提升包括了页面SEO的提升、页面内容的提升以及页面交互的提升等等,语义化、canvas、音视频等特性也随之被催生出来。

语义化

语义化被提出,最重要的目的是提高页面的SEO。搜索引擎排名对目前的电商类网站有着举足轻重的地位,前端开发也开始规范化,定义标签不再清一色div和span嵌套了。

  • <header></header> 定义文档的页眉;

  • <footer></footer> 定义文档的页脚;

  • <nav></nav> 定义导航链接部分;

  • <section></section> 定义文档区块;

  • <article></article> 定义文档内容;

  • <aside></aside> 定义侧边栏部分;

  • <figure></figure> 定义独立区块,相对于原有div区块有缩进;

  • <figcaption></figcaption> 定义独立区块的标题,与figure配合使用;

  • <details></details> 定义关联内容描述,标题可折叠;

  • <summary></summary> 定义关联内容描述的标题,与detail配合使用;

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>HTML5</title>
</head>
<body>
	<div>
		<div>figure</div>
		<figure>
			<figcaption>title</figcaption>
			content: All the growth is a leap in the dark.
		</figure>
		<div>figure</div>
	</div>
	<div>
		<div>details</div>
		<details>
			<summary>标题</summary>
			content: All the growth is a leap in the dark.
		</details>
		<div>details</div>
	</div>
</body>
</html>

注意:部分语义化标签与原有标签的功能一致,只是标签名不同。

增强表单

  1. 输入列表

<datalist></datalist>本身不可见,为input标签提供输入建议,用户可从列表中选取输入,datalist与input通过id关联,具体用法如下:

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>HTML5</title>
</head>
<body>
	<datalist id="river">  
		<option>长江</option>  
		<option>嘉陵江</option>
		<option>金沙江</option>
		<option>黑龙江</option>
	</datalist>  
	<input type="text" list="river">
</body>
</html>

  1. 进度条

<progress value="10" max="100"></progress> 进度条控件,通过value属性指定进度,通过max定义最大范围;

  1. 刻度尺

<meter min="0" max="100" low="10" high="60" optimum="90" value="70"></meter> 用于标示一个值所处范围:判定value是否合适:value在min-low范围内为不可接受(红色),value在low-hight范围内为可以接受(黄色),value在high-max范围内为非常优秀(绿色);

  1. 输出

<output></output> 语义标签,无任何样式,相当于span,用法:<output>输出</output>

音视频

  1. 音频

音频标签使用如下:

<audio>
	<source src="xxx/xxx.mp3">  
	<source src="xxx/xxx.wav">  
	<source src="xxx/xxx.webm">  
	浏览器版本太低,无法播放音频。
</audio>

注意:audio标签默认生成300*32的inline-block,播放按照source源顺序执行,一旦成功播放,不执行后续,当所有音频无法播放,提示:浏览器版本太低,无法播放音频。

  • audio标签属性:

    • audio标签属性:

      • autoplay
        自动播放,默认为false;

      • controls
        是否显示播放控件,默认为false;

      • loop
        循环播放,默认为false;

      • muted
        静音,默认为fasle;

      • preload
        音频的预加载策略;属性有:auto(预加载音频的元数据(部分画面)及缓冲一定时长视频,默认为auto),metadate(预加载音频的元数据),none(不预加载任何数据)

  • audio-DOM对象
    可以通过dom操作获取audioDOM对象;

    • 属性

      • currentTime:当前播放时长;

      • duration:总时长;

      • paused:当前音频是否处于暂停状态;

      • volumn:当前音量,属性值为数字,范围(0-1);

      • playbackRate:播放速率,默认值为1,正常播放;

      • muted: 是否静音;

    • 方法

      • play() 播放;

      • pause() 暂停;

    • 事件

      • onplay:当前音频开始播放触发的事件;

      • onpause:当前音频暂停播放触发的事件;

  1. 视频
    视频标签使用如下:
<video>
	<source src="xxx/xxx.mp4">  
	<source src="xxx/xxx.ogg">  
	<source src="xxx/xxx.webm">  
	浏览器版本太低,无法播放视频。
</video>

注意:video标签默认生成300*150的inline-block,播放按照source源顺序执行,一旦成功播放,不执行后续,当所有视频无法播放,提示:浏览器版本太低,无法播放视频。

  • video标签属性:

    • autoplay
      自动播放,默认为false;

    • controls
      是否显示播放控件,默认为false;

    • loop
      循环播放,默认为false;

    • muted
      静音,默认为fasle;

    • preload
      音频的预加载策略;属性有:auto(预加载音频的元数据(部分画面)及缓冲一定时长视频,默认为auto),metadate(预加载音频的元数据),none(不预加载任何数据)

    • poster
      播放前显示海报 <video poster="xxx/xxx.png"></video>

  • video-DOM对象
    可以通过dom操作获取videoDOM对象;

    • 属性

      • currentTime:当前播放时长;

      • duration:总时长;

      • paused:当前视频是否处于暂停状态;

      • volumn:当前音量,属性值为数字,范围(0-1);

      • playbackRate:播放速率,默认值为1,正常播放;

      • muted: 是否静音;

    • 方法

      • play() 播放;

      • pause() 暂停;

    • 事件

      • onplay:当前视频开始播放触发的事件;

      • onpause:当前视频暂停播放触发的事件;

Canvas

Canvas 是 HTML5 提出的绘图 API,绘制图形为位图。Canvas 的出现使得网页在不依赖图片(资源开销较大)的情况下,可以绘制各种图案。

Canvas 本质是一个 300 * 150 (默认大小) 的 inline-block,我们也称之为画布。绘制图像需要通过与画布绑定且唯一的画笔对象,使用相应的 api 进行绘制。

基本步骤如下:

  1. HTML 中创建画布
	<canvas width="400" height="400" id="c1"></canvas>
  1. JS 中获取画布,绑定画笔
	var c1 = document.getElementById("c1");
	var ctx = c1.getContext("2d"); // ctx 为画笔对象
  1. 通过 api 绘制图像
	ctx.strokeStyle = "red";
	ctx.strokeRect(10,10,100,100); // 坐标为(10, 10)的点处开始绘制宽高100的矩形
点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Canvas</title>
	<style type="text/css">
		#c1 {
			width: 400px;
			height: 400px;
			border: 1px solid #ccc;
		}
	</style>
</head>
<body>
	<!-- 分别注释 css 或者 canvas 宽高对比效果 -->
	<canvas width="400" height="400" id="c1">您的浏览器不支持 canvas 标签。</canvas>
	<script type="text/javascript">
		var c1 = document.getElementById("c1");
		var ctx = c1.getContext("2d");
		ctx.strokeStyle = "red";
		ctx.strokeRect(10,10,100,100)
	</script>
</body>
</html>

注意:

  1. 画布的宽高需要使用 html 属性或者 js 指定,不能使用 css 设置,因为 css 的宽高和 画布实际宽高是不一致的。
  2. Canvas 作图是有坐标轴概念的,例如A点至B点画一条实线,需要A,B点坐标。因此,画布的左上角定为坐标原点,左右为x轴(右为正),上下为y轴(下为正)。

Canvas 绘制图形API

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Canvas</title>
	<style type="text/css">
		#c1 {
			border: 1px solid #ccc;
		}
	</style>
</head>
<body>
	<canvas width="400" height="400" id="c1"></canvas>
	<script type="text/javascript">
		var c1 = document.getElementById("c1");
		var ctx = c1.getContext("2d");

		// 可将绘制图形api 粘贴至此处观察效果。

	</script>
</body>
</html>
  1. 绘制基本线条

    • 绘制直线
    ctx.beginPath();
    ctx.moveTo(10,10); // 起始点(10,10)
    ctx.lineTo(100,10); // 终止点(100,10)
    ctx.stroke();
    
    • 绘制二次曲线
    ctx.beginPath();
    ctx.moveTo(10,10);
    ctx.quadraticCurveTo(200,100,300,300); // 终止点(300,300),控制点(200,100)
    ctx.stroke();
    
    • 绘制贝塞尔曲线
    ctx.beginPath();
    ctx.moveTo(10,10);
    ctx.bezierCurveTo(20,90,100,50,200,200); // 终止点(200,200),控制点1(20,90),控制点2(100,50)
    ctx.stroke();
    
    • 绘制圆弧
    ctx.beginPath();
    // 以(100,100)为圆心,半径为50,起点0弧度,终点1.5π弧度,顺时针画圆弧
    ctx.arc(100, 100, 50, 0, 2*Math.PI*0.75, false); 
    ctx.stroke();
    

    注意:arc()最后一个参数为Boolean类型,默认false表示顺时针,true表示逆时针,可缺省。

  2. 绘制简单形状

    • 绘制圆形
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, 2*Math.PI); // 以(100,100)为圆心,半径为50,顺时针画圆
    ctx.stroke();
    
    • 绘制矩形
    ctx.beginPath();
    ctx.rect(40,40,100,100)
    ctx.stroke();
    
    • 绘制三角形
    ctx.beginPath();
    ctx.moveTo(30,30);
    ctx.lineTo(150,150);
    ctx.lineTo(30,150);
    ctx.closePath(); // 闭合路径,使用直线连接起点和终点。
    ctx.stroke();
    
    • 绘制圆角矩形
    ctx.beginPath();
    ctx.moveTo(40,30);
    ctx.arcTo(130,30,130,130,10); // 控制点1(130,30),控制点2(130,130),半径为10
    ctx.arcTo(130,130,30,130,10);
    ctx.arcTo(30,130,30,30,10);
    ctx.arcTo(30,30,130,30,10);
    ctx.stroke();
    

    注意:arcTo()需要两个控制点绘制圆弧,具体使用可参照 MDN arcTo

  3. 绘制渐变

    • 绘制线性渐变
    var gradient = ctx.createLinearGradient(10,10,300,300); // 创建线性渐变对象,起点(10,10),终点(300,300)
    gradient.addColorStop(0, "blue");  // 设置比例及渐变色
    gradient.addColorStop(0.5, "red");  
    gradient.addColorStop(1, "#0f0");
    ctx.fillStyle = gradient; // 应用渐变色
    ctx.fillRect(10,10,300,300); // 绘制图形
    

    注意:canvas绘图有两种方式:fill() 填充 和 stroke() 描边,对应两种方式可以设置相应的属性 fillStyle 和 fillStyle。其他属性可参考 canvas 属性

    • 绘制径向渐变
    // 圆心为(160,160)生成半径30和100的圆,交集部分圆环为径向对象范围
    var gradient = ctx.createRadialGradient(160,160,30,160,160,100); 
    gradient.addColorStop(0, "blue");  
    gradient.addColorStop(0.5, "red");  
    gradient.addColorStop(1, "#0f0");
    ctx.fillStyle = gradient; 
    ctx.fillRect(10,10,300,300);
    
  4. 绘制特殊效果

    • 绘制阴影效果
    ctx.save(); // 保存当前画笔状态(无状态画笔)
    ctx.shadowBlur = 10; // 设置阴影模糊级数
    ctx.shadowOffsetX = 20; // 设置阴影水平偏移,可设置负值。
    ctx.shadowOffsetY = 20; // 设置阴影垂直偏移,可设置负值。
    ctx.shadowColor = 'black'; // 设置阴影颜色,不可使用 #fff
    ctx.fillStyle = '#00f';
    ctx.beginPath();
    ctx.fillRect(20,20,100,100);
    ctx.restore(); // 恢复上一次save的画笔状态(无状态画笔),save 和 restore 之间的画笔是阴影画笔,可注释这行,查看效果
    ctx.fillStyle = 'skyblue';
    ctx.beginPath();
    ctx.fillRect(150,20,100,100);
    
    • 绘制透明效果
    ctx.fillStyle = 'red';
    ctx.fillRect(20,20,100,100);
    ctx.globalAlpha = 0.2; // 设置透明度alpha为0.2,范围 0 - 1
    ctx.fillStyle = 'blue';
    ctx.fillRect(60,60,100,100);
    ctx.fillStyle = 'green'; // 未使用 save 和 restore, green 使用了 blue的 alpha为0.2的画笔
    ctx.fillRect(80,80,100,100);
    
  5. 绘制图像

    • 放缩图像
    var image = new Image(); //创建图片对象
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	ctx.drawImage(image, 10, 10, 200, 200) // 坐标(10,10)点处开始绘制图像,图像宽高 200*200,宽高可缺省,表示不放缩
    }
    

    注意:绘制图像一定要在图像加载完成以后,即onload触发以后。

    • 裁剪图像
    var image = new Image();
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	// 坐标(10,10)处,宽高 200*200 的图像,从坐标(20,20)处裁剪出宽高 50*50 的图像按照宽高 200*200显示。
    	ctx.drawImage(image, 20, 20, 50, 50, 10, 10, 200, 200) 
    }
    
    • 平铺图像
    var image = new Image();
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	var pattern = ctx.createPattern(image, 'repeat'); // createPattern设置平铺模式,可选值有:repeat(默认), repeat-x, repeat-y, no-repeat
    	ctx.fillStyle = pattern;
    	ctx.fillRect(5,5,395,395);
    }
    
    • 反转像素
    ctx.fillStyle = '#f00';
    ctx.fillRect(10,10,100,100);
    var imageData = ctx.getImageData(10,10,50,50); // 从坐标(10,10)处,获取图像信息对象,宽高为50*50
    for(var i=0;i<imageData.data.length;i+=4) { // imageData.data: ArrayBuffer包含了图像像素信息,以RGBA的顺序存放,范围0-255
    	imageData.data[i] = 255 - imageData.data[i];
    	imageData.data[i + 1] = 255 - imageData.data[i + 1];
    	imageData.data[i + 2] = 255 - imageData.data[i + 2];
    	imageData.data[i + 3] = 255;
    }
    ctx.putImageData(imageData,35,35); // 按照处理的图像信息(反转像素后的50*50图像),在坐标(35,35)处生成图像
    

    注意:反转像素使用的是填充矩形,使用 image 可以绘制图像,但获取像素信息会导致跨域报错:Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.

    如下代码测试报错

    var image = new Image();
    image.src = "https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png";
    image.onload = function () {
    	ctx.drawImage(image,10,10);
    	var imageData = ctx.getImageData(10,10,image.width,image.height)
    	console.log(imageData)
    }
    
  6. 绘制文本

    • 填充文本
    // font为综合属性,依次对应值:font-style  font-variant font-weight font-size/line-height font-family
    ctx.font="normal normal 400 30px/1.5 Microsoft YaHei"; 
    ctx.fillStyle = 'skyblue';
    ctx.fillText('Hello Canvas!', 50,50); // 坐标(50,50)处,绘制填充文本 Hello Canvas!
    
    • 描边文本
    ctx.font="normal normal 400 30px/1.5 Microsoft YaHei";
    ctx.strokeStyle = 'skyblue'; // 可以设置渐变,生成渐变文本
    ctx.strokeText('Hello Canvas!', 50,100);
    
  7. 绘制动画

    • canvas 动画相关API
    ctx.ratate(弧度); // 绘图旋转,轴为原点旋转,旋转具有累加效果;  
    ctx.translate(x,y);  // 绘图移动,原点由(0,0)移动到(x,y);  
    ctx.scale(x, y); // 绘图缩放,x,y表示缩放比例,>1表示放大,<1表示缩小;
    ctx.clearRect(0,0,c1.width,c1,height); // 从原点处,宽高为画布宽高,清除图像
    

    注意:clearRect() 是 canvas 绘制动画的关键 api,canvas 绘制动画的本质是一遍遍擦除重绘,如 canvas 时钟案例

Svg

Svg 是基于 XML 绘制的矢量图,Svg 图像是可以通过 DOM 元素获取的,并且可以通过 DOM 方法设置图像属性。

Svg 绘图类似于 Canvas 本质是一个 300*150 的 inline-block,也称之为画布。绘制图像是通过一系列 svg 标签,每个 svg 标签可以获取其 DOM 对象,并执行 DOM 操作。

基本步骤如下:

	<svg id="s1" width="400" height="400">
		<!-- svg 绘图标签 -->
	</svg>

Svg 绘图标签

  1. 绘制线条

    • 绘制直线
    <line x1="10" y1="10" x2="200" y2="200" style="stroke: blue; stroke-width: 3;" />
    

    注意:svg 与 canvas 一样具有坐标系概念,并且坐标系一致。

    • 绘制折线
    <polyline points="20,30 50,70 100,60 150,120" style="fill: none; stroke: #f00; stroke-width: 3;" />
    
    • 绘制曲线
    <path d="M 10 110 C 20 140, 40 140, 50 110" stroke="black" fill="transparent"/>
    

    注意: path路径标签有很强大的功能,不单单是绘制曲线,根据d的value值命令不同,可以绘制更多图像。详细可以查看 path MDN

  1. 绘制简单形状

    • 绘制矩形
    <rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="2"/>
    
    • 绘制多边形
    <polygon points="50,160 55,180 70,180 60,190 65,205 50,195 35,205 40,190 30,180 45,180" stroke="green" fill="transparent" stroke-width="5"/>
    
    • 绘制圆
    <circle cx="25" cy="75" r="20" stroke="red" fill="transparent" stroke-width="5"/>
    
    • 绘制椭圆
    <ellipse cx="75" cy="75" rx="20" ry="5" stroke="red" fill="transparent" stroke-width="5"/>
    
  2. 绘制渐变

    • 绘制线性渐变
    <defs>
    	<linearGradient id="linear" x1="0" x2="0" y1="0" y2="1">
    		<stop offset="0%" stop-color="red"/>
    		<stop offset="50%" stop-color="black" stop-opacity="0"/>
    		<stop offset="100%" stop-color="blue"/>
    	</linearGradient>
    </defs>
    <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#linear)"/>
    
    • 绘制径向渐变
    <defs>
    	<radialGradient id="radial" cx="0.25" cy="0.25" r="0.5">
    	<stop offset="0%" stop-color="red"/>
    	<stop offset="100%" stop-color="blue"/>
    	</radialGradient>
    </defs>
    <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#radial)"/>
    
  3. 绘制文本

    • 绘制填充文本
    <text x="30" y="80" fill="skyblue" style="font-size: 30px;">Hello Svg!</text>
    
    • 绘制描边文本
    <text x="30" y="40" fill="none" stroke="blue" stroke-width="1" style="font-size: 30px;">Hello Svg!</text>
    
  4. 绘制图像

    <image xlink:href="https://images.cnblogs.com/cnblogs_com/blogs/766345/galleries/2274688/o_230215035425_canvas.png" x="10" y="10" height="150px" width="200px"/>
    
  5. 绘制变换

    <rect x="20" y="20" width="20" height="20" transform="translate(30,40)" />
    <rect x="50" y="20" width="20" height="20" transform="rotate(45)" />
    <rect x="90" y="20" width="20" height="20" transform="scale(0.5, 1)" />
    

地理定位

HTML5 地理定位功能依托于浏览器 window.navigator.geolocation 属性,通过判断该属性是否存在可以检测浏览器是否支持地理定位功能。该属性包含三个地理定位 api:getCurrentPosition(), watchPosition(), clearPosition()

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>地理位置</title>
</head>
<body>
	<div>Geolocation</div>
	<script type="text/javascript">
		if(window.navigator.geolocation) {
			console.log(window.navigator.geolocation)
		} else {
			alert('您的浏览器不支持地理定位功能!')
		}
	</script>
</body>
</html>
  1. getCurrentPosition

    用于获取用户当前的地理位置信息,该方法有三个参数,success回调,error回调,options参数(可缺省)。

    window.navigator.geolocation.getCurrentPosition(
    	position => {
    		console.log(position.timestamp, position.coords)
    		// position.coords.latitude 纬度
    		// position.coords.longtitude 经度
    		// position.coords.altitude 海拔
    		// position.coords.accuracy 经纬度的精度(米)
    		// position.coords.altitudeAccuracy 海拔的进度(米)
    		// position.coords.heading 前进方向,用面朝正北方向顺时针旋转角度表示
    		// position.coords.speed 前进速度
    	},
    	error => {
    		if(error.code === 1) {
    			alert('用户拒绝位置服务')
    		} else if(error.code === 2) {
    			alert('获取不到位置信息')
    		} else if(error.code === 3) {
    			alert('获取位置信息超时')
    		} else {
    			console.log(error)
    			alert('发生位置错误')
    		}
    	},
    	{
    		enableHighAccuracy: true, // 是否要求高精度的位置信息
    		timeout: 100 * 1000,
    		maximumAge: 30 * 1000, // 最大缓存时间
    	}
    )
    
  2. watchPosition

    用于持续监听用户当前的地理位置信息,地理位置发生变化自动调用该函数,参数与 getCurrentPosition 一致。

    var watchId = window.navigator.geolocation.watchPosition(
    	position => {
    		console.log(position.timestamp, position.coords)
    		// position.coords.latitude 纬度
    		// position.coords.longtitude 经度
    		// position.coords.altitude 海拔
    		// position.coords.accuracy 经纬度的精度(米)
    		// position.coords.altitudeAccuracy 海拔的进度(米)
    		// position.coords.heading 前进方向,用面朝正北方向顺时针旋转角度表示
    		// position.coords.speed 前进速度
    	},
    	error => {
    		if(error.code === 1) {
    			alert('用户拒绝位置服务')
    		} else if(error.code === 2) {
    			alert('获取不到位置信息')
    		} else if(error.code === 3) {
    			alert('获取位置信息超时')
    		} else {
    			console.log(error)
    			alert('发生位置错误')
    		}
    	},
    	{
    		enableHighAccuracy: true,
    		timeout: 3 * 1000,
    		maximumAge: 30 * 1000,
    	}
    )
    

    注意:watchPosition 会返回一个句柄,本质是一个数字,类似 setInterval 返回一致,该句柄用于停止监听。

  3. clearPosition

    用于停止 watchPosition 的监听,该方法有一个参数:watchPosition() 的返回值。

    var watchId = window.navigator.geolocation.watchPosition(
    	position => {
    		console.log(position.timestamp, position.coords)
    		// position.coords.latitude 纬度
    		// position.coords.longtitude 经度
    		// position.coords.altitude 海拔
    		// position.coords.accuracy 经纬度的精度(米)
    		// position.coords.altitudeAccuracy 海拔的进度(米)
    		// position.coords.heading 前进方向,用面朝正北方向顺时针旋转角度表示
    		// position.coords.speed 前进速度
    	},
    	error => {
    		if(error.code === 1) {
    			alert('用户拒绝位置服务')
    		} else if(error.code === 2) {
    			alert('获取不到位置信息')
    		} else if(error.code === 3) {
    			alert('获取位置信息超时')
    		} else {
    			console.log(error)
    			alert('发生位置错误')
    		}
    	},
    	{
    		enableHighAccuracy: true,
    		timeout: 3 * 1000,
    		maximumAge: 30 * 1000,
    	}
    )
    
    window.navigator.geolocation.clearPosition(watchId)
    

    注意:以上方法可以获取用户的地理位置信息,但是我们获取都是经纬度和海拔信息,无法转换成常规的地址信息。因此,需要借助地图 API 做逆地址解析,如 百度地图 BMap高德地图 AMap

Web Worker

Web Worker是多线程工作,运行在后台的JavaScript,无法请求或访问页面,不会影响页面性能。

Web Worker 创建流程:

  1. 主进程中创建 worker 对象

    var worker = new Worker('./worker.js')
    
  2. 数据传递

    • 主线程传递数据
    worker.postMessage(params); // postMessage只接受一个参数
    
    • worker 线程传递数据
    self.postMessage(params); // self 可省略,即 postMessage();
    
  3. 接收数据

    • 主线程接收数据
    worker.onmessage = function(event) {
    	event.data // worker 传递的参数
    }
    
    • worker 线程接收数据
    self.onmessage = function(event) {
    	event.data // 主线程传递的参数
    }
    
  4. 关闭 worker 线程

    • 主线程关闭 worker 线程
    worder.terminate();
    
    • worker 线程内部关闭
    self.close();
    

    注意:web worker 需要加载 worker.js 文件,而浏览器因同源策略无法加载本地文件,需要借助服务器将 worker.js 资源静态化,可参照 web worker demo

Web Storage

  1. sessioStorage
    sessioStorage 将数据保存在 session 对象中,而 session 对象是浏览器打开窗口的过程中,为用户浏览网站提供的内存对象(session 对象与窗口绑定),一旦浏览器关闭,内存会被清空。因此,sessioStorage 是临时存放数据,随浏览器关闭而销毁。

    sessioStorage.setItem(key,value); // key, value 必须为字符串
    
    sessioStorage.getItem(key);
    
    sessioStorage.removeItem(key;
    
    • 清空
    sessioStorage.clear();
    

    注意:浏览器同源策略对 sessioStorage 的影响:

    1. 不同源的情况下,A,B 页面是断然无法共享 sessioStorage 的。
    2. 同源的情况下,B 页面由 A 页面中链接导航打开,则 B 页面 session 对象是 A 页面 session 对象的复制,且为值引用,相互对立,不受干扰。
    3. 同源的情况下,A,B 页面是不同窗口分别打开的,则 A,B 页面的 session 对象无关联。
  2. localStorage
    localStorage 将数据保存在客户端本地,通常保存在磁盘或其他存储介质中,浏览器关闭不会影响磁盘和存储介质(存储与”源“绑定)。因此,localStorage 是永久存储(不主动清理和损毁磁盘的情况下)。

    localStorage.setItem(key,value); // key, value 必须为字符串,引用类型数据可以通过JSON方式进行存储,JSON API: JSON.stringify(), JSON.parse()
    
    localStorage.getItem(key);
    
    localStorage.removeItem(key;
    
    • 清空
    localStorage.clear();
    

    注意:浏览器同源策略对 localStorage 的影响:

    1. 不同源的情况下,A,B 页面是断然无法共享 localStorage 的。
    2. 同源的情况下,A,B 页面共享 localStorage,共用同一存储,相互干扰,相互影响,可以监听 storage 事件来观测 local 数据变化。

Web SQL

Web SQl 是客户端数据库,同服务器端 SQL Serve 和 Oracle 一致,可以使用 SQL 语句进行一些数据库操作,如表和数据的增删改查等;Web SQL的三个核心 API:

  1. openDatabase

    用于打开或创建数据库对象的方法,指定数据名,存在即打开,不存在则创建;

    var db = openDatabase('testDB', '1.0', 'this is a db for test', 5 * 1024 * 1024) // 参数分别为:数据库名称,版本,描述,大小
    if(!db) {
    	alert('创建/打开 数据库失败')
    } else {
    	// 执行数据库操作(transacion, executeSql)
    	alert('创建/打开 数据库成功')
    }
    
  2. transacion

    用于创建并控制事务,可进行事务提交和回滚。事务:一系列数据操作的集合,所有操作完成,事务提交,否则,事务回滚,取消所有操作。

    • 创建表操作
    const createTabelSQL = "create table if not exists User (id UNIQUE, name TEXT)"
    const createData = []
    
    db.transaction(res => {
    	res.executeSql(
    		createTabelSQL,
    		createData,
    		success => {
    			alert('创建 User 表成功')
    		},
    		error => {
    			alert('创建 User 表失败,原因:', error.message)
    		}
    	)
    })
    
    • 删除表操作
    const dropSQL = "drop table User"
    const dropData = []
    
    db.transaction(res => {
    	res.executeSql(
    		dropSQL,
    		dropData,
    		success => {
    			alert('表 User 删除成功')
    		},
    		error => {
    			alert('表 User 删除失败,原因:', error.message)
    		}
    	)
    })
    

    注意:transacion 参数为回调函数,回调函数内部执行 executeSql。

  3. executeSql

    用于执行 SQL 操作,参数有四个,分别为:sql,data,success回调, error回调。

    • 插入数据
    const insertSQL = "insert into User(id, name) values(?, ?)"
    const insertData = [1, '张三']
    
    db.transaction(res => {
       res.executeSql(
       	insertSQL,
       	insertData,
       	success => {
       		alert('数据插入成功')
       	},
       	error => {
       		alert('数据插入失败,原因:', error.message)
       	}
       )
    })
    
    • 更新数据
    const updateSQL = "update User set name=? where id=?"
    const updateData = ["李四", 1]
    
    db.transaction(res => {
       res.executeSql(
       	updateSQL,
       	updateData,
       	success => {
       		alert('更新 User 表成功')
       	},
       	error => {
       		alert('更新 User 表失败,原因:', error.message)
       	}
       )
    })
    
    • 查询数据
    const selectSQL = "select * from User"
    const selectData = []
    
    db.transaction(res => {
       res.executeSql(
       	selectSQL,
       	selectData,
       	(success, data) => {
       		console.log(data.rows)
       	},
       	error => {
       		alert('数据查询失败,原因:', error.message)
       	}
       )
    })
    
    • 删除数据
    const deleteSQL = "delete from User"
    const deleteData = []
    
    db.transaction(res => {
      res.executeSql(
      	deleteSQL,
      	deleteData,
      	success => {
      		alert('数据删除成功')
      	},
      	error => {
      		alert('数据删除失败,原因:', error.message)
      	}
      )
    })
    

    注意:executeSql 第二个参数是必须的,为空可以设置为空数组。此外,SQL 语句中可以使用 ? 占位符,按照顺序对应 data 中的数据项。

Web Socket

Web Socket 是全双工通信,应用 Web Socket 技术可以做到:web 端在任意时刻请求服务端,服务端在任意时刻推送 web 端;与 http 相比,Web Socket 解决了服务端无法主动向 web 端推送的功能,更是有效解决了消息时效性问题,目前多应用于响应系统。

Web Socket 基于 nodejs 的简单使用

web 端:

let ws = new WebSocket('ws://127.0.0.1:3000/public')
ws.onopen = () => {
	ws.send('hello server')
};
ws.onmessage = ev => {
	console.log(ev.data)
}

服务端:

const express = require('express')
const path = require('path')
const http = require('http')
const Ws = require('ws').Server

const app = express()
app.use('/public',express.static(path.resolve(__dirname, './public/')))

const server = http.createServer(app)
server.listen(3000)

let wsServer = new Ws({ server })
wsServer.on('connection', socket => {
  socket.on('message', msg => {
    console.log('客户端发送过来的消息:' + msg);
    socket.send('服务器说:你好客户端')
  })
});

注意:上例是使用 ws 模块进行的简单使用,项目地址:web socket demo,市场上有多种 web socket库,调用方式也不同,如 socket.io 库

拖放 API

拖放 API 是指:drag 和 drop 行为过程触发的 7 个事件,以及拖放的两个对象:源对象(拖的对象),目标对象(放的对象)。

在 HTML5 当中,任何元素均可以被拖放,但是实施拖放必须指定元素属性 draggable = true

点击查看代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>拖放 API</title>
	<style type="text/css">
		#origin {
			width: 100px;
			height: 100px;
			background-color: skyblue;
			float: left;
		}
		#desination {
			width: 200px;
			height: 200px;
			background-color: orchid;
			float: right;
			margin-right: 100px;
		}
	</style>
</head>
<body>
	<div id="origin" draggable="true"></div>
	<div id="desination"></div>
	<script type="text/javascript">
		const origin = document.getElementById('origin')

		origin.addEventListener('dragstart',function(event) {
			console.log('拖 开始')
			console.log(event)
		})

		origin.addEventListener('drag', function(event) {
			console.log('拖 进行')
		})

		origin.addEventListener('dragend', function(event) {
			console.log('拖 结束')
		})


		const desination = document.getElementById('desination')

		desination.ondragenter = function(event) {
			console.log('拖 进入')
		}

		desination.ondragover = function(event) {
			console.log('拖 悬停')
			// event.preventDefault()
		}

		desination.ondragleave = function(event) {
			console.log('拖 离开')
		}

		desination.ondrop = function(event) {
			console.log('放')
		}

	</script>
</body>
</html>

针对两个对象的 7 个事件如下:

  1. 源对象(origin)

    • origin.ondragstart
      拖动开始触发的事件,拖放过程执行 1 次。

    • origin.ondrag
      拖动过程中触发的事件,拖放过程执行 多 次。

    • origin.ondragend
      拖动结束触发的事件,拖放过程执行 1 次。

  2. 目标对象

    • desination.ondragenter
      源对象进入目标对象区域触发的事件,拖放过程执行 1 次。
    • desination.ondragover
      源对象悬停目标对象上方触发的事件,拖放过程执行 n 次。
    • desination.ondragleave
      源对象离开目标对象区域触发的事件,拖放过程执行 0 或 1 次。
    • desination.ondrop
      源对象在目标对象上方释放时触发的事件,拖放过程执行 0 或 1 次。

注意:dragover 默认行为是悬停上方,释放后立即执行 dragleave,而释放后执行 drop 需要阻止 dragover 默认行为,因此执行 dragleave 或 drop 是需要根据 dragover 是否阻止默认行为来决定的。

拖放事件对象中的 dataTransfer 对象:

源对象和目标对象可以借助 dataTransfer 对象的 setData() 和 gerData() 方法进行数据传递;

const origin = document.getElementById('origin')

origin.addEventListener('dragstart',function(event) {
	console.log('拖 开始')
	event.dataTransfer.setData('name', 'blue block')
})

const desination = document.getElementById('desination')

desination.ondragover = function(event) {
	event.preventDefault()
}

desination.ondrop = function(event) {
	console.log('放')
	const name = event.dataTransfer.getData('name')
	console.log(name)
}

注意:dataTransfer 对象的 setDragImage() 方法可以自定义拖放图标,该方法有三个参数:image,图标与 x 轴偏移量,图标与 y 轴偏移量。

写在后面

HTML5 新特性暂时更新致此吧,还有其他特性会以碎片化学习前端系列更新。博客中新特性均是基本使用,没有涉及工作中的应用场景,我的考虑是先广而全,后精而深,慢慢会结合场景更新。

标签:02,10,ctx,HTML,error,position,100,绘制,系统化
From: https://www.cnblogs.com/huangminghua/p/17104375.html

相关文章