HTML学习笔记(四) Canvas

<canvas> 标签用于定义图形容器,容器本身是没有画图能力的,但我们可以使用脚本来绘制图形

1、创建画布

在 HTML 中,使用 <canvas> 标签可以创建一个矩形画布,这个画布的默认宽高为 300*150

如果要改变画布的大小,建议通过内联样式或者脚本进行设置,否则很容易会出现画布扭曲的情况

<!DOCTYPE html>
<html>
<head>
    <title>Canvas Demo</title>
</head>
<body>
    <canvas id="graph" width="300" height="300">您的浏览器不支持 canvas 标签</canvas>
</body>
</html>

2、创建画笔

在 JavaScript 中,使用 getContext() 方法可以创建一个渲染上下文对象

这个对象就相当于是这个画布的画笔,拥有一系列用于画图的方法

<script>
	var canvas = document.getElementById('graph')
    var context = canvas.getContext('2d')
    // 开始画图
</script>

3、绘制矩形

Canvas 只支持一种原生图形的绘制方法,那就是矩形,其它图形都必须通过路径生成

  • strokeRect(x, y, width, height):绘制一个矩形的边框
  • fillRect(x, y, width, height):绘制一个填充的矩形
  • clearRect(x, y, width, height):清空指定的矩形区域

其中,参数 x、y 定义矩形左上角的坐标,参数 width、height 定义矩形的宽高

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    ctx.strokeRect(10, 10, 100, 100)
</script>

4、绘制路径

图形的基本元素是路径,路径是线段和点的集合,在 Canvas 中每一个路径都是闭合的

  • beginPath():新建一条路径
  • closePath():结束一条路径,它会从当前点到起始点拉一条直线,使得路径闭合
  • moveTo(x, y):将画笔移动到指定坐标
  • stroke():绘制图形(闭合路径)的边框
  • fill():填充图形(闭合路径)的内容,如果路径没有闭合,首先闭合路径

  • lineTo(x, y):创建一条直线路径,从 当前坐标(x, y) 连接一条直线
<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    ctx.beginPath()
    ctx.moveTo(150, 90)
    ctx.lineTo(60, 210)
    ctx.lineTo(240, 210)
    ctx.closePath() // 结束一条路径,从当前点到起始点拉一条直线,使得路径闭合
    ctx.stroke() // 绘制图形(闭合路径)的边框
</script>
<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    ctx.beginPath()
    ctx.moveTo(150, 90)
    ctx.lineTo(60, 210)
    ctx.lineTo(240, 210)
    ctx.fill() // 填充图形(闭合路径)的内容,如果路径没有闭合,首先闭合路径
</script>
  • arc(x, y, r, startAngle, endAngle, anticlockwise):创建一段圆弧路径

    (x, y) 为圆心,以 r 为半径,从 startAngle 开始,到 endAngle 结束,画一段圆弧

    如果 anticlockwisetrue,则逆时针画,如果 anticlockwisefalse,则顺时针画

  • arcTo(x1, y1, x2, y2, radius):创建一段圆弧路径

    首先我们想象从 当前坐标(x1, y1) 画一条直线,然后从 (x1, y1)(x2, y2) 画一条直线

    这个方法的作用就是画一段半径为 radius 并且与两条直线相切的圆弧

    注意哦,从 当前坐标(x1, y1) 的直线也会留在画布上

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')

    ctx.beginPath()
    ctx.arc(150, 150, 100, Math.PI*1.5, Math.PI*0.5, true)
    ctx.fill()

    ctx.beginPath()
    ctx.moveTo(50, 50)
    ctx.arcTo(250, 50, 250, 250, 100)
    ctx.stroke()
</script>
  • quadraticCurveTo(cpx, cpy, x, y):绘制二次贝塞尔曲线

    其中,(cpx, cpy) 表示控制点的坐标,(x, y) 表示结束点的坐标

  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y):绘制三次贝塞尔曲线

    (cp1x, cp1y) 是第一个控制点的坐标,(cp2x, cp2y) 是第二个控制点的坐标,(x, y) 是结束点的坐标

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
    ctx.beginPath()
    ctx.moveTo(25, 100)
    ctx.quadraticCurveTo(75, 50, 125, 100)
    ctx.stroke()

    ctx.beginPath()
    ctx.moveTo(175, 250)
    ctx.bezierCurveTo(205, 200, 245, 200, 275, 250)
    ctx.stroke()
</script>

5、绘制文字

我们可以使用以下两个方法绘制文字:

  • strokeText(text, x, y):在指定坐标 (x, y) 处创建空心文本 text
  • fillText(text, x, y):在指定坐标 (x, y) 处创建实心文本 text

还能使用以下属性指定文字样式:

  • font:指定文本样式,与 CSS font 属性取值相同,默认值为 10px sans-serif
  • textAlign:指定文本对齐选项,可选值有 startendleftrightcenter
  • textBaseline:指定基线对齐选项,可选值有 alphabetictopmiddlebottomideographichanging
  • direction:指定文本方向,可选值有 inheritltrrtl
<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
    ctx.font = '50px sans-serif'
    ctx.strokeText('Hello', 80, 160)
</script>

6、添加样式

(1)颜色

除了使用默认的黑色之外,我们还可以给图形设置指定的颜色

  • strokeStyle:设置图形边框的颜色
  • fillStyle:设置图形内容的颜色

注意,一旦设置上面两个属性,那么新绘制的图形都是使用指定好的颜色

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
    for (let i = 0; i <= 5; i += 1) {
        for (let j = 0; j <= 5; j += 1) {
            let r = randInt(0, 255)
            let g = randInt(0, 255)
            let b = randInt(0, 255)
            ctx.fillStyle = `rgb(${r}, ${g}, ${b})`
            ctx.fillRect(j * 50, i * 50, 50, 50)
        }
    }

    function randInt(start, end) {
        return Math.floor(Math.random() * (end - start + 1) + start)
    }
</script>

(2)渐变

除了使用常规的颜色,还能通过渐变对象使用渐变效果,渐变效果可以添加在图形、文本上

首先创建一个渐变对象

  • createLinearGradient(x1, y1, x2, y2):创建线性渐变

    (x1, y2) 定义渐变线的起点坐标,(x2, y2) 定义渐变线的终点坐标,渐变效果沿渐变线展开

  • createRadialGradient(x1, y1, r1, x2, y2, r2):创建径向渐变

    定义一个以 (x1, y1) 为坐标、以 r1 为圆心的圆,定义一个以 (x2, y2) 为坐标、以 r2 为圆心的圆

    渐变效果发生在两个圆之间

然后给渐变对象定义渐变的效果

  • addStopColor(position, color):指定渐变颜色

    position 是一个 0 ~ 1 之间的数值,定义在渐变中的相对位置,color 用于定义在该处的颜色

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
    var grd = ctx.createLinearGradient(0, 0, 100, 100)
    grd.addColorStop(0.0, 'red')
    grd.addColorStop(0.5, 'green')
    grd.addColorStop(1.0, 'blue')
    
    ctx.fillStyle = grd
    ctx.fillRect(0, 0, 100, 100)
</script>

(3)形状

除了可以指定颜色,我们还可以指定线段的形状

  • lineWidth:指定线段宽度
<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
    for (let i = 0; i <= 2; i += 1) {
        ctx.beginPath()
        ctx.moveTo(100, i * 20 + 50)
        ctx.lineTo(200, i * 20 + 50)
        ctx.lineWidth = i * 10 + 1
        ctx.stroke()
    }
</script>
  • lineCap:指定线段末端的样式,其取值有三个:

    若为 butt,则以方形结束

    若为 round,则以圆形结束

    若为 square,则以方形结束,但增加一个宽度与线段宽度相同,高度是宽度一半的矩形区域

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
    let lineCap = ['butt', 'round', 'square']
    for (let i = 0; i <= 2; i += 1) {
        ctx.beginPath()
        ctx.moveTo(100, i * 20 + 50)
        ctx.lineTo(200, i * 20 + 50)
        ctx.lineWidth = 10
        ctx.lineCap = lineCap[i]
        ctx.stroke()
    }
</script>
  • lineJoin:指定线段之间的连接样式,其取值有三个:

    若为 miter,通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域

    若为 round,填充一个额外的、圆心在相连部分末端的扇形

    若为 bevel,填充一个额外的、以三角形为底的区域

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
    let lineJoin = ['miter', 'round', 'bevel']
    for (let i = 0; i <= 2; i += 1) {
        ctx.beginPath()
        ctx.moveTo(100, i * 20 + 50)
        ctx.lineTo(150, i * 20 + 100)
        ctx.lineTo(200, i * 20 + 50)
        ctx.lineWidth = 10
        ctx.lineJoin = lineJoin[i]
        ctx.stroke()
    }
</script>

7、创建图片

  • drawImage(image, x, y, width, height)

    参数 image 表示图片的来源,既可以是一个 Image 对象,也可以是一个 <img> 元素

    参数 xy 定义图片位置,表示左上角的坐标;参数 widthheight 定义图片大小,表示图片的宽高度

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
	var img = new Image()
    img.src = 'https://cdn.pixabay.com/photo/2020/02/15/16/09/loveourplanet-4851331__340.jpg'
    
    img.onload = function() {
        ctx.drawImage(img, 0, 0, 300, 300)
    }
</script>
  • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight):剪裁图片

    参数 image 表示图片的来源,既可以是一个 Image 对象,也可以是一个 <img> 元素

    sx, sy, sWidth, sHeight 定义对原图片的切片,dx, dy, dWidth, dHeight 定义在画布上的绘制

<script>
    var cvs = document.getElementById('graph')
    var ctx = cvs.getContext('2d')
    
	var img = new Image()
    img.src = 'https://cdn.pixabay.com/photo/2020/02/15/16/09/loveourplanet-4851331__340.jpg'
    
    img.onload = function() {
        ctx.drawImage(img, 180, 40, 100, 100, 0, 0, 300, 300)
    }
</script>

【 阅读更多 HTML 系列文章,请看 HTML学习笔记

posted @ 2020-03-10 21:06  半虹  阅读(157)  评论(0编辑  收藏  举报