codershame初试canvas

105 阅读7分钟

Canvas是什么

  • Canvas 中文名叫 “画布”,是 HTML5 新增的一个标签。
  • Canvas 允许开发者通过 JS在这个标签上绘制各种图案。
  • Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法, 在某些情况下可以 “代替” 图片。
  • Canvas 可用于动画、游戏、数据可视化、图片编辑器、实时视频处理等领域。

Canvas和SVG的区别

CanvasSVG
用JS动态生成元素(一个HTML元素)用XML描述元素(类似HTML元素那样,可用多个元素来描述一个图形)
位图(受屏幕分辨率影响)矢量图(不受屏幕分辨率影响)
不支持事件支持事件
数据发生变化需要重绘不需要重绘

总结

  • 如果你需要高质量的矢量图形、复杂的图形设计、SEO优化、图形的可编辑性和可访问性,那么SVG是更好的选择。
  • 如果你需要高性能的图形渲染、大量的动态渲染、复杂的图像合成,或者图形不需要高清晰度或缩放,那么Canvas可能更适合你的需求。

起步

注意点

  1. 默认宽高 canvas默认宽度为300px,默认高度为150px。不设置宽高,取默认值
  2. 设置宽高,不需要带单位
  3. 不能通过css设置canvas的宽高,否则会被拉伸
  4. 线条的默认宽度是 1px ,默认颜色是黑色。但由于默认情况下 canvas 会将线条的中心点和像素的底部对齐,所以会导致显示效果是 2px 和非纯黑色问题。

基础图形

直线

<canvas id="c" width="300" height="200"></canvas>

<script>
const cvs = document.querySelector("#c")

const ctx = cvs.getContext("2d")

ctx.moveTo(100,100) // 坐标起点 移动到(100,100)(x轴坐标,y轴坐标)
ctx.lineTo(200,100) // 下一个坐标(x,y)
ctx.stroke() // 将所有坐标连在一起
</script>

设置样式

  • lineWidth 线的粗细 (不要带单位 )
  • strokeStyle 线的颜色
  • lineCap 线帽:默认 butt;圆形:round;方形:square

<canvas id="c" width="300" height="200"></canvas>

<script>
const cvs = document.querySelector("#c")

const ctx = cvs.getContext("2d")

ctx.moveTo(50,100) // 坐标起点 移动到(100,100)(x轴坐标,y轴坐标)
ctx.lineTo(200,100) // 下一个坐标(x,y)
// 设置宽度
ctx.lineWidth = '20px'
// 设置颜色
ctx.strokeStyle = 'pink'
// 设置线帽
ctx.lineCap = 'round'
ctx.stroke() // 将所有坐标连在一起
</script>

新开路径

为什么要开辟新的路径:防止多条线段绘制时,样式污染
开辟路径的方法

  • beginPath()
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')

  ctx.moveTo(20, 100)
  ctx.lineTo(200, 100)
  ctx.lineWidth = 10
  ctx.strokeStyle = 'pink'
  ctx.stroke()

  ctx.beginPath() // 重新开启一个路径
  ctx.moveTo(20, 120.5)
  ctx.lineTo(200, 120.5)
  ctx.lineWidth = 4
  ctx.strokeStyle = 'red'
  ctx.stroke()
</script>

折线

直线差不多,可以使用moveTo(),lineTo(),stroke()实现

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')
  
  ctx.moveTo(50,200)
  ctx.lineTo(100,50)
  ctx.lineTo(200,200)
  ctx.lineTo(250,50)
  
  ctx.stroke()
  
</script>

矩形

使用strokeRect() 描边矩形

  • strokeStyle:设置描边属性(颜色,渐变,图案)
  • strokeRect(x,y,width,height):描边矩形(x,y是矩形的左上角起点,width和height是矩形的宽高)
  • strokeStyle 必须写在前面,否则样式不生效

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')
  // 设置线条颜色
  ctx.strokeStyle = 'pink'
  // 描边矩形  起点坐标(50,50) 宽度200 长度100
  ctx.strokeRect(50,50,200,100)
</script>

使用fillRect() 填充矩形

需要注意fillStyle 需要用在fillRect前面,不然样式不生效

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')
  // 设置填充颜色
  ctx.fillStyle = 'pink'
  // 描边矩形  起点坐标(50,50) 宽度200 长度100
  ctx.fillRect(50,50,200,100)
</script>

同时使用strokeRect()和fillRect()

同时使用会产生描边和填充的效果

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')
  // 设置填充颜色
  ctx.fillStyle = 'yellow'
  // 描边矩形  起点坐标(50,50) 宽度200 长度100
  ctx.fillRect(50,50,200,100)
  
  // 设置线条颜色
  ctx.strokeStyle = 'pink'
  // 描边矩形  起点坐标(50,50) 宽度200 长度100
  ctx.strokeRect(50,50,200,100)
</script>

使用rect() 生成矩形

与strokeRect()和fillRect()不同,使用rect()绘制矩形时,需要调用stroke()和fill()辅助渲染,否则绘制不出来

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')
  // 设置填充颜色
  ctx.fillStyle = 'yellow'
   // 设置线条颜色
  ctx.strokeStyle = 'pink'
  
  ctx.rect(50,50,200,100)
  
  ctx.stroke()
  ctx.fill()
</script>

清空矩形 clearRect()

使用clearRect可以清空指定区域

clearRect(x,y,width,height)

通过如下代码可以实现清空画布

    // const cnv = document.querySelector("#c")
    clearRect(0,0,cnv.width,cnv.height) // cnv为canvas dom对象

多边形

canvas绘制多边形,需要使用moveTo(),lineTo()和closePath()

三角形

canvas没有直接提供类似与rect()的方法绘制三角形,需要确定3个点的坐标,使用stroke或者fill实现

 <canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')

  ctx.moveTo(50, 50)
  ctx.lineTo(200, 50)
  ctx.lineTo(200, 200)
  // 手动闭合
  ctx.closePath()

  ctx.lineJoin = 'miter' // 线条连接的样式。miter: 默认; bevel: 斜面; round: 圆角
  ctx.lineWidth = 20
  ctx.stroke()
</script>

菱形

临边相等的平行四边形就是菱形

 <canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const ctx = cnv.getContext('2d')

  ctx.moveTo(150, 50)
  ctx.lineTo(250, 100)
  ctx.lineTo(150, 150)
  ctx.lineTo(50, 100)
  // 手动闭合
  ctx.closePath()

  ctx.stroke()
</script>

圆形

使用arc() 可以绘制圆
语法:

arc(x,y,r,sAngle,eAngle, counterClockwise)
  • xy:圆心坐标
  • r:圆的半径
  • sAngle: 开始角度
  • eAngle: 结束角度
  • counterClockwise: 绘制方向(true:逆时针,false:顺时针)默认false

<canvas id="canvas" width="300" height="300"></canvas>
    
    <script>
        const canvas = document.querySelector("#canvas")
        
        const ctx = canvas.getContext("2d")
        ctx.beginPath()
        ctx.arc(150,150,80, 0, 360)
        ctx.closePath()
        ctx.stroke()
    </script>

半圆

<canvas id="canvas" width="300" height="300"></canvas>
    
    <script>
        const canvas = document.querySelector("#canvas")
        
        const ctx = canvas.getContext("2d")
        ctx.beginPath()
        ctx.arc(150,150,80, 0, 180 * Math.PI / 180)
        ctx.closePath()
        ctx.stroke()
    </script>

使用arcTo()绘制圆弧

语法:

arcTo(cx, cy, x2,y2, radius)

arcTo() 方法利用 开始点、控制点和结束点形成的夹角,绘制一段与夹角的两边相切并且半径为 radius 的圆弧。
  • cx:两切线焦点的横坐标
  • cy:两切线焦点的纵坐标
  • x2:结束点的横坐标
  • y2:结束点的横坐标
  • radius:半径

文本

样式

语法:

ctx.font= 'font-style font-variant font-weight font-size/line-height font-family'

描边 strokeText && 填充 fillText

哈哈 哈哈
语法:

// 描边
strokeText(text, x, y, maxWidth)
// 填充
fillText(text, x, y, maxWidth)
  • text: 字符串 要绘制的内容
  • x: 横坐标
  • y: 纵坐标
  • maxWidth: 可选参数,表示文本最大的渲染宽度,超出会被压缩

描边样式 strokeStyle() && 填充样式 fillStyle()

语法:

ctx.strokeStyle='red'

ctx.fillStyle = 'green'

获取文本长度

measureText().width 可以获取文本长度

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  let text = 'hello Canvas'
  cxt.font = 'bold 40px Arial'
  cxt.fillText(text, 40, 80)

  console.log(cxt.measureText(text).width) // 80
</script>

水平对齐方式 textAlign

使用 textAlign 属性可以设置文字的水平对齐方式,一共有5个值可选

  • start: 默认。在指定位置的横坐标开始。
  • end: 在指定坐标的横坐标结束。
  • left: 左对齐。
  • right: 右对齐。
  • center: 居中对齐。

垂直对齐方式 textBaseline

使用 textBaseline 属性可以设置文字的垂直对齐方式。

在使用 textBaseline 前,需要自行了解 css 的文本基线。

textBaseline 可选属性:

  • alphabetic: 默认。文本基线是普通的字母基线。
  • top: 文本基线是 em 方框的顶端。
  • bottom: 文本基线是 em 方框的底端。
  • middle: 文本基线是 em 方框的正中。
  • hanging: 文本基线是悬挂基线。

图片渲染

在 Canvas 中可以使用 drawImage() 方法绘制图片。
通常渲染图片有2种方式,一种是在js中实现,另一种是通过拿到dom中的图片拿到canvas中渲染
语法


drawImage(img,dx,dy)

// 设置图片宽高
drawImage(img,dx,dy,dw,dh)

// 截取图片
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)

  • image: 要渲染的图片对象。

  • dx: 图片左上角的横坐标位置。

  • dy: 图片左上角的纵坐标位置。

  • dw 用来定义图片的宽度

  • dh 定义图片的高度。


截取图片 参数缺一不可

  • image: 图片对象
  • sx: 开始截取的横坐标
  • sy: 开始截取的纵坐标
  • sw: 截取的宽度
  • sh: 截取的高度
  • dx: 图片左上角的横坐标位置
  • dy: 图片左上角的纵坐标位置
  • dw: 图片宽度
  • dh: 图片高度



<canvas id="c" width="300" height="200"></canvas>
<img src='/xx/xx' />
<script>
    const canvas = document.querySelector("#c")
    const ctx = canvas.getContext("2d")
    
    // 创建Image对象
    const img = new Image()
    // 引入图片 // js 版本
    img.src = '/public/hero.png'
    // 获取 dom  // DOM版
    // const img = document.querySelector("img").src
    // 等待图片加载完成
    img.onload = () => {
        ctx.drawImage(img, 200, 300)
    }
    
</script>




总结

上面主要是记录了关于canvas的绘制基础图形的一些笔记记录,关于进阶部分,等待后续学习之后,继续深入探索。