Canvas_note基础学习(一)

159 阅读2分钟

bg.jpg 注: 添加语法提示/** @type {HTMLCanvasElement} */,放在获取canvas节点之前

获取canvas节点上下文

<canvas id="canvas" width="500" height="500"></canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

1.绘制基本图形

// x,y是起始点坐标,width,height是绘制的矩形长宽
1.填充的矩形
fillRect(x,y,width,height)
2.矩形边框
strokeRect(x,y,width,height)
3.清除指定矩形区域:
strokeRect(x,y,width,height)
例子:ctx.fillRect(25, 25, 100, 100);

2.绘制路径

  1. 首先路径需要起始点
  2. 然后使用绘图命令画出路径
  3. 封闭路径
  4. 路径一旦生成,只能通过描边或者填充来渲染图形
常用函数

beginPath():新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径 closePath():闭合路径之后图形绘制命令又重新指向到上下文中 stroke():通过线条来绘制图形的轮廓 fill():通过填充路径的内容区域生成实心的图形 moveTo(x, y):移动笔触 lineTo(下, y):绘制直线

绘制描边三角形

ctx.beginPath()
ctx.fillStyle = '#007acc'
ctx.moveTo(150,150)
ctx.lineTo(180,130)
ctx.lineTo(120,130)
ctx.closePath()
ctx.stroke()

绘制圆弧:arc(x, y, radius, startAngle, endAngle, anticlockwise)

x,y:圆心位置 radius:圆半径 startAngle, endAngle:起点终点位置(弧度制) anticlockwise:绘制方向(默认是顺时针,Boolean)

// 绘制扇形
ctx.beginPath()
ctx.fillStyle = '#007acc'
ctx.moveTo(50, 50)
ctx.arc(50, 50, 50, 0, 0.8 * Math.PI)
ctx.fill()

test.png

绘制色值

for(let i = 1;i<6;i++){
  for(let j = 1;j<6;j++){
    ctx.fillStyle = `rgba(${i*22.5},${j*22.5},${(i+j)*22.5},.7)`
    ctx.fillRect(i*20,j*20,20,20)
  }
}

1.png

3.样式

ctx.lineWidth = 20 // number
// 线段两端的样式
ctx.lineCap = 'butt' // butt(默认):线段末端以方形结束,round:圆形,square:方形结束
// 拐角样式
ctx.lineJoin = 'miter' // bevel:去除拐角的尖角,round:圆弧型,miter:默认
// 设置虚线
ctx.setLineDash([4, 2])// 4:实线的长度,2两条线的距离,setLineDash接收一个数组
ctx.lineDashOffset = -offset // 改变正负可以改变虚线方向

// 测试
let offset = 16
  function draw() {
    ctx.clearRect(0, 0, 500, 500)
    ctx.setLineDash([4, 2])// 4:实线的长度,2两条线的距离
    ctx.lineDashOffset = -offset // 改变正负可以改变虚线方向
    ctx.strokeRect(10, 10, 100, 100)
  }

  function march() {
    offset--
    if (offset < 0) {
      offset = 16
    }
    draw();
    setTimeout(march, 20)
  }
  march()
  
// 渐变
createLinearGradient(x1, y1, x2, y2):渐变起点(x1,y1)终点(x2,y2)
createRadialGradient(x1, y1, r1, x2, y2, r2):前三个点定义一个以(x1,y1)为原点,r1为半径,后面三个参数定义另一个以(x2,y2)为原点,半径为r2的圆
注: 半径为r2的圆的圆心一定要在r1圆内,并且r2的圆一定要包裹r1的圆,否则渐变会变的很奇怪

// 阴影
shadowOffsetX/shadowOffsetY=float,阴影偏移的的距离,右/下,为负则是:左/上
shadowBlur=float, 阴影的模糊程度
shadowColor=float, 阴影的颜色效果
// 填充
fill()
ctx.beginPath('evenodd')// nonzero:不填充;evenodd:
ctx.arc(200,200,30,0,Math.PI)
ctx.arc(200,200,50,0,Math.PI)
ctx.fill('evenodd')

4.字体

// 文本样式
font = value 使用与cssfont属性相同的语法,默认字体是10px sans-serif(参考链接:https://www.runoob.com/tags/canvas-font.html)
textAlign=value 文本对齐。可选值:start,end,left,right,center,默认值:start
textBaseline=value 基线对齐选项。可选值:top,hanging,middle,alphabetic,ideographic,bottom,默认值:alphabetic
direction=value 文本方向。可选值:ltr,rtl,inherit,默认值:inherit

 ctx.font = '40px arial italic '
 ctx.textAlign = 'start'
 ctx.textBaseline = 'alphabetic'
 ctx.direction = 'ltr'
 ctx.strokeStyle = 'red'
 ctx.strokeText('这是文本内容',100,50)

5.变形Transformations

  1. 状态的保存和恢复:Saving and restoring state
    a.save():保存画布的状态
    b.restore():saverestore方法是用来保存和恢复canvas状态的,都没有参数,Canvas的状态就是当前画面应用的所有样式和变形的一个快照
    c.Canvas中,适用save()方法来保存状态,适用restore()方法来恢复状态;canvas状态是以栈的方式来保存:每次调用save()方法,就会把栈顶的方法取出来,并把画布恢复到这个状态,用这个状态绘图。
  2. 移动Translating
// translate(x,y),x是左右偏移量;y是上下偏移量
// 代码
for (let i = 1; i < 5; i++) {
    for (let j = 1; j < 6; j++) {
      ctx.save()
      ctx.fillStyle = `rgb(${i*50},${j*50},${i*j*10})`
      ctx.translate(10+j*50,10+i*50)
      ctx.fillRect(0,0,25,25)
      ctx.fill()
      ctx.restore()
    }
  }
  1. 旋转 Rotating
// rotate方法,它用于以原点为中心旋转canvas
// ratate(angle):angle是旋转的角度,顺时针方向,以弧度为单位的值
// 代码
ctx.translate(150, 200)// 旋转中心
for(let i=1;i <7;i++) {
  ctx.rotate(Math.PI*2/6)
  ctx.beginPath()
  ctx.arc(50,50,25,0,Math.PI*2) // 前两个参数是相对旋转中心的位置
  ctx.fill()
}
  1. 缩放 Scalling
// scale(x,y) 两个参数都是实数,可以为负值,x为水平缩放因子,y为垂直缩放因子,如果比1小会缩小,比1大会放大,默认为1
// 注:缩放后面所有数值
// 代码
ctx.fillText('1',20,13)
  for(let i=1;i<5;i++){
    ctx.save()
    ctx.translate(100-i*20,100-i*20)
    ctx.scale(i*1,i*1)
    ctx.strokeRect(0,0,40,40)
    ctx.stroke()
    ctx.restore()
  }
  ctx.fillText('2',200,13)
  for(let i=1;i<5;i++){
    ctx.save()
    ctx.translate(200,20)
    ctx.scale(i,i)
    ctx.strokeRect(0,0,40,40)
    ctx.stroke()
    ctx.restore()
  }
  ctx.fillText('3',20,193)
  for(let i=1;i<5;i++){
    ctx.save()
    ctx.translate(i*20,200+i*20-20)
    ctx.scale(2*i,2*i)
    ctx.lineWidth = 2/(2*i) // 使线条的宽度保持一致
    ctx.strokeRect(0,0,20,20)
    ctx.stroke()
    ctx.restore()
  }
  1. 变形Transforms
transform(a,b,c,d,e,f)
a:水平方向的缩放
b:竖直方向的倾斜偏移
c:水平方向的倾斜偏移
d:竖直方向的缩放
e:水平方向的移动
f:竖直方向的移动

// 代码
ctx.fillStyle = 'rgb(231, 212, 233)'
ctx.fillRect(0, 0, 150, 150)
ctx.fillStyle = `rgb(0,0,0)`

ctx.transform(2, 2, 0.3, 1, 20, 20)
ctx.fillRect(0,0, 150, 150)

6.合成

  1. 制作刮刮卡
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  #thanks {
    width: 500px;
    height: 500px;
    position: absolute;
    z-index: -1;
    font-size: 50px;
    color: red;
    line-height: 500px;
    text-align: center;
  }

  #canvas {
    /* background-color: aliceblue; */
    border: 1px solid #000
  }
</style>

<body>
  <div id="thanks"></div>
  <canvas id="canvas" width="500" height="500"></canvas>
</body>
<script type="text/javascript">
  /**
   * @type {HTMLCanvasElement}
  */
  const ctx = document.getElementById('canvas').getContext('2d')

  let img = new Image()
  img.src = './story2.png'
  img.onload = function () {
    ctx.drawImage(img, 0, 0, 600, 400)
  }

  var isDraw = false
  canvas.onmousedown = function () {
    isDraw = true
  }
  canvas.onmouseup = function () {
    isDraw = false
  }
  canvas.onmousemove = function (e) {
    if (isDraw) {
      var x = e.pageX
      var y = e.pageY
      ctx.globalCompositeOperation = 'destination-out'
      ctx.beginPath()
      ctx.arc(x, y, 20, 0, 2 * Math.PI)
      ctx.fill()
    }
  }

  let random = ~~(Math.random() * 10);
  var ggk = document.querySelector('#thanks')
  random < 5 ? ggk.innerHTML = '恭喜你中奖了' + random : ggk.innerHTML = '谢谢惠顾' + random

</script>
</html>

总结

  1. 以上这些内容基本都是从MDN上面自学的,如有不对的地方欢迎指正;这里一下附上MDN的链接: developer.mozilla.org/zh-CN/docs/…
  2. 最后的一个刮刮卡是参考掘金一位大佬在掘金发的文章,现在找不到了,如有侵权马上删除;