2.HTML5

HTML5.0 可不只是 将 HTML4 的标签之类进行了改变,而是一个生态,让一些事情成为可能,让前端真正的站了起来

注意:这里有部分内容,需要有前端基础


🥗第一部分:标签

1.语义化标签

本质就是名字不同的 div

<header></header>
<footer></footer>

<!-- 语义:导航条 -->
<nav></nav>

<!-- 语义:文章,可以被直接引用 -->
<article></article>
<!-- 语义:一般放到 article里面使用,表示里面的一段-->
<section></section>

<!-- 语义:侧边栏 -->
<aside></aside>

2.视频,音频

这俩的属性都一样,就是视频多了一个视频的展示,我觉得这块怎么能说做的好呢?就是仿照腾讯课堂的样式,做一个播放器

<!-- 视频和音频播放器,在每个浏览器中展示的效果都不一样,如果要展示效果一致的话,要自己封装 -->
<audio src="音频地址"></audio>
<video src="视频地址"></video>



🍥第二部分:属性


🍱第三部分:API


🍛第四部分:canvas(画布)

1.基础知识

<canvas id="canvas"></canvas>

<script>

    let canvas = document.getElementById('canvas')
    let ctx = canvas.getContext('2d') // 这个可以理解为画笔

    // 线(直线,三角形...)
    ctx.moveTo(x, y)
    ctx.lineTo(x, y)
    ctx.arcTo(B点x, By, C点x, C点y, 弧的数值) // 直线 + 圆弧(可以做圆角矩形)

    // 矩形
    ctx.rect(x, y, 宽度, 高度) // 画矩形
    ctx.strokeRect(x, y, 宽度, 高度) // 直接画出来了,都不用写构建路径
    ctx.fillRect(x, y, 宽度, 高度) // 直接画出来了,都不用写填充路径

    // 圆形(半圆,扇形,弧线,圆形)
    ctx.arc(圆心x, 圆心y, 半径, 弧度, 方向)

    // 贝塞尔曲线
    ctx.quadraticCurveTo(x1, y1, x2, y2); // 二次贝塞尔曲线(除了起点,还需要另外两个点)
    ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); // 三次贝塞尔曲线(除了起点,还需要三个点)

    // 设置样式
    ctx.fillStyle = 'red' // 设置填充颜色
    ctx.strokeStyle = 'blue' // 设置填充颜色
    ctx.lineWidth = 3 // 设置线条宽度
    ctx.font = '24px 黑体'

    ctx.fillText('实体文字', 文字显示的x, 文字显示的y); // 设置文字
    ctx.strokeText('空心文字', 文字显示的x, 文字显示的y); // 设置文字

    // 坐标平移 && 旋转 && 缩放
    ctx.translate(100, 100) // 修改坐标原点(坐标平移)
    ctx.rotate(Math.PI) // 旋转(单位是弧度,并且是根据坐标原点进行的旋转)
    ctx.scale(x点倍数, y点倍数) // 缩放

    // 保存和使用之前坐标系
    ctx.save() // 保存之前坐标系(可以保存坐标系的平移数据,缩放数据,旋转数据)
    ctx.restore() // 恢复之前的坐标系

    // 清除画布
    ctx.clearRect(x, y, 宽度, 高度) 

    // 重新开启一个路径
    ctx.beginPath()

    ctx.closePath() // 闭合路径,针对一个路径才能闭合
    ctx.stroke() // 构建路径
    ctx.fill() // 构建填充路径
 
</script>

canvas 坐标系统


2.画线

画线 要有一个起点和终点

let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')

ctx.moveTo(100, 100) // 起点
ctx.lineTo(100, 200) // 终点
ctx.stroke()

// 线端样式(线的两端)
ctx.lineCap = 'butt' // square 给线的两端 添加两个小方块 | round 给线的两端 添加圆角
ctx.lineJoin = 'mitter' // round bevel miter(miterLimit)

3.画矩形

用线也能画矩形,但是麻烦,用 ctx.rect() 更快

ctx.rect(x, y, 宽度, 高度) // 画矩形
ctx.strokeRect(x, y, 宽度, 高度) // 直接画出来了,都不用写构建路径
ctx.fillRect(x, y, 宽度, 高度) // 直接画出来了,都不用写填充路径


// 例如:一个一直往下落的矩形
let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d') 
let height = 0

let timer = setInterval(() => {
    ctx.clearRect(0, 0, 500, 500)
    ctx.strokeRect(100, height, 50, 50)
    if (height === 450) clearInterval(timer);
    height += 10;
}, 50);

4.画圆

需要知道 圆心(x, y),半径(r),弧度(需要用Math.PI表示:起始弧度,结束弧度),方向(顺时针0,逆时针-1)

let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d') 

// 基础圆形(扇形,半圆,圆形)
ctx.arc(100, 100, 50, 0, Math.PI, 0)
ctx.fill()

// 圆角矩形
ctx.moveTo(100, 110) // y轴多了10,是一个小技巧
ctx.arcTo(100, 200, 200, 200, 10)
ctx.arcTo(200, 200, 200, 100, 10)
ctx.arcTo(200, 100, 100, 100, 10)
ctx.arcTo(100, 100, 100, 200, 10)
ctx.stroke()

5.贝塞尔曲线

贝塞尔曲线,百度百科

// 二次贝塞尔曲线
ctx.moveTo(100, 100) // 起点
ctx.quadraticCurveTo(200, 200, 300, 100); // 除了起点,还需要另外两个点

// 三次贝塞尔曲线
ctx.moveTo(100, 100) // 起点
ctx.bezierCurveTo(200, 200, 300, 100, 400, 200); // 除了起点,还需要三个点
ctx.stroke()

// 案例:模拟一个波浪

6.坐标平移 && 旋转 && 缩放

ctx.translate(100, 100) // 修改坐标原点(坐标平移)
ctx.rotate(Math.PI / 6) // 是根据坐标原点进行的旋转
ctx.moveTo(0, 0) // 原来是 100, 100
ctx.lineTo(100, 0)
ctx.stroke()

// 缩放(所有点,都放大scale里面的倍数)
ctx.scale(2, 2)
ctx.strokeRect(100, 100, 100, 100)

7.save && restore

canvas的平移和旋转是对于全局来说的,如果想旋转之后的,还按照之前的用,需要先保存之前的,再回复

ctx.save() // 保存之前坐标系(可以保存坐标系的平移数据,缩放数据,旋转数据)

ctx.translate(100, 100) // 修改坐标原点(坐标平移)
ctx.rotate(Math.PI / 6) // 是根据坐标原点进行的旋转
ctx.moveTo(0, 0) // 原来是 100, 100
ctx.lineTo(100, 0)
ctx.stroke()

ctx.restore() // 恢复之前的坐标系

8.背景填充

// 填充颜色
ctx.fillStyle = 'red'
ctx.fillRect(100, 100, 100, 100)

// 填充图片(纹理的填充是以坐标系原点进行填充的)
let img = new Image()
img.src = 'https://itzkp-1253302184.cos.ap-beijing.myqcloud.com/github%E5%9B%BE%E7%89%87/notes/3.png'
img.onload = function () {
    ctx.translate(100, 100)
    ctx.fillStyle = ctx.createPattern(img, 'no-repeat')
    ctx.fillRect(0, 0, 100, 100)
}

// 线性渐变填充
let bg = ctx.createLinearGradient(100, 100, 200, 200);
bg.addColorStop(0, 'white'); // 渐变起点
bg.addColorStop(1, 'black'); // 渐变终点(当然中间也能写多个阶段的值)
ctx.fillStyle = bg
ctx.fillRect(100, 100, 100, 100)

// 辐射渐变
let bg = ctx.createRadialGradient(150, 150, 0, 180, 180, 180)
bg.addColorStop(0, 'white'); // 渐变起点
bg.addColorStop(1, 'black'); // 渐变终点(当然中间也能写多个阶段的值)
ctx.fillStyle = bg
ctx.fillRect(100, 100, 100, 100)

9.阴影

ctx.shadowColor = 'red'
ctx.shadowBlur = 10;
ctx.fillRect(100, 100, 100, 100)

10.文字

ctx.fillText('实体文字', 100, 100);
ctx.font = '24px 黑体'
ctx.strokeStyle = 'red'
ctx.strokeText('空心文字', 100, 200);

11.requestAnimationFrame动画

动画原理简介

动画的基本原理是依靠人类具有视觉暂留的特性人的眼睛看到一幅画或一个物体后,在 1/24 秒内不会消失(即每秒钟至少更换24张画面)。利用这一原理,在一幅画(一帧)还没消失前播放下一幅画(下一帧),就会给人造成流畅的视觉变化效果。

我们在实现动画的时候,经常用定时器,但是定时器有时候并不精确

requestAnimationFrame

由于 setTimeout 和 setInterval 的不精准问题,促使了 requestAnimationFrame 的诞生。 requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,你可以把它用在 DOM 上的效果切换或者 Canvas 画布动画中。 requestAnimationFrame 并不是定时器,但和 setTimeout 很相似,在没有 requestAnimationFrame 的浏览器一般都是用setTimeout模拟。 requestAnimationFrame 跟屏幕刷新同步(大多数是 60Hz )。如果浏览器支持 requestAnimationFrame , 则不建议使用 setTimeout 来做动画。

requestAnimationFrame 的兼容使用

// 下面是我们常规使用 requestAnimationFrame 的兼容写法,当浏览器不兼容的 requestAnimationFrame 时则通过使用 setTimeout 来模拟实现,且设定渲染间隔为 1000ms/60。

// 判断是否有 requestAnimationFrame 方法,如果有则模拟实现
window.requestAnimFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
    window.setTimeout(callback, 1000 / 30);
};

使用 requestAnimationFrame 实现动画

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>认识Canvas</title>
</head>
<body>
    <canvas id="canvas" width="500" height="500" style="border: 1px solid #33"></canvas>
    <script>
        var canvas = document.getElementById('canvas');
        var context = canvas.getContext('2d');
        // 兼容定义 requestAnimFrame
        window.requestAnimFrame =
        window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback) {
            window.setTimeout(callback, 1000 / 30);
        };

        // 绘制的圆的对象
        var circle = {
            x: 250,
            y: 250,
            radius: 50,
            direction: 'right',
            // 移动圆形
            move: function() {
                if (this.direction === 'right') {
                    if (this.x <= 430) {
                         this.x += 5;
                    } else {
                        this.direction = 'left';
                    }
                } else {
                    if (this.x >= 60) {
                         this.x -= 5;
                    } else {
                        this.direction = 'right';
                    }
                }
            },
            draw: function() {
                // 绘制圆形
                context.beginPath();
                // 设置开始角度为0,结束角度为 2π 弧度
                context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
                context.fillStyle = '#00c09b';
                context.fill();
            }
        }
        // 动画执行函数
        function animate() {
            // 随机更新圆形位置
            circle.move();
            // 清除画布
            context.clearRect(0, 0, canvas.width, canvas.height);
            // 绘画圆
            circle.draw();
            // 使用requestAnimationFrame实现动画循环
            requestAnimationFrame(animate);
        }

        // 先画第一帧的圆,即初始化的圆
        circle.draw();
        // 执行animate
        animate();        
    </script>
</body>
</html>

12.键盘事件处理

在制作 PC 端的游戏的时候,我们经常需要监听键盘的事件,以便响应用户的键盘操作。目前,对键盘事件的支持主要遵循的是 DOM0级。

按键相关事件

  • keydown:当用户按下键盘上的任意键时触发,而且如果按住按住不放的话,会重复触发此事件。
  • keypress:当用户按下键盘上的字符键时触发,而且如果按住不放的,会重复触发此事件(按下Esc键也会触发这个事件)。
  • keyup:当用户释放键盘上的键时触发。

按键过程

  • 首先会触发 keydown 事件
  • 然后紧接着触发 keypress 事件
  • 最后触发 keyup事件
  • 如果用户按下了一个字符键不放,就会重复触发 keydown 和 keypress 事件,直到用户松开该键为止。

键码(keyCode)对照表

简单实现键盘控制物体移动

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>物体移动</title>
</head>
<body>
    <canvas id="canvas" width="500" height="500"></canvas>
    <script>
      var canvas = document.getElementById('canvas');
      var context = canvas.getContext('2d');
      var rect = {
        x: 100, // 矩形的 x 坐标
        y: 400, // 矩形的 y 坐标
        width: 100, // 矩形的宽度
        height: 100, // 矩形的高度
        step: 30 // 矩形移动的步伐
      }
      // 全局监听键盘操作的 keydown 事件 
      document.onkeydown = function(e) {  
        // 获取被按下的键值 (兼容写法)
        var key = e.keyCode || e.which || e.charCode;
        switch(key) {
          // 点击左方向键
          case 37: 
            rect.x -= 20;
            drawRect();
            break;
          // 点击上方向键
          case 38: 
            rect.y -= 20;
            drawRect();
            break;
          // 点击右方向键
          case 39: 
            rect.x += 20;
            drawRect();
            break;
          // 点击下方向键
          case 40: 
            rect.y += 20;
            drawRect();
            break;
        } 
      };
      function drawRect() {
        // 清除画布
        context.clearRect(0, 0, canvas.width, canvas.height);
        // 绘制矩形
        context.fillRect(rect.x, rect.y, rect.width, rect.height);
      }
      // 第一次绘制
      drawRect();
    </script>
</body>
</html>

13.碰撞检测

矩形物体碰撞检测

// 判断四边是否都没有空隙
if (!(rect2.x + rect2.width < rect1.x) &&
    !(rect1.x + rect1.width < rect2.x) &&
    !(rect2.y + rect2.height < rect1.y) &&
    !(rect1.y + rect1.height < rect2.y)) {
    // 物体碰撞了
}

圆形物体碰撞检测

var dx = circle2.x - circle1.x;
var dy = circle2.y - circle1.y;
var distance = Math.sqrt((dx * dx) + (dy * dy));
if (distance < circle1.radius + circle2.radius) {
  // 两个圆形碰撞了
}

🍚第五部分:存储


🍢第六部分:交流


🍧第七部分:工作线程


🍩第八部分:位置感知


📚参考列表(致敬)