canvas基础2 -- 形状、简单场景

 七巧板

七巧板本质上就是 分别由几个直线 拼成一个个图形,再将这些图形结合起来

var tangram = [
      { p: [{ x: 0, y: 0 }, { x: 800, y: 0 }, { x: 400, y: 400 }], color: "#caff67" },
      { p: [{ x: 0, y: 0 }, { x: 400, y: 400 }, { x: 0, y: 800 }], color: "#67beef" },
      { p: [{ x: 800, y: 0 }, { x: 800, y: 400 }, { x: 600, y: 600 }, { x: 600, y: 200 }], color: "#ef3d61" },
      { p: [{ x: 600, y: 200 }, { x: 600, y: 600 }, { x: 400, y: 400 }], color: "#f9f5la" },
      { p: [{ x: 400, y: 400 }, { x: 600, y: 600 }, { x: 400, y: 800 }, { x: 200, y: 600 }], color: "#a594c0" },
      { p: [{ x: 200, y: 600 }, { x: 400, y: 800 }, { x: 0, y: 800 }], color: "#fa8ecc" },
      { p: [{ x: 800, y: 400 }, { x: 800, y: 800 }, { x: 400, y: 800 }], color: "#f6ca29" }
    ]
    const canvas = document.getElementById('canvas')
    canvas.width = 800
    canvas.height = 800
    const context = canvas.getContext('2d')

    for (let i = 0; i < tangram.length; i++) {
      draw(tangram[i], context)
    }

    function draw(piece, cxt) {
      cxt.beginPath()
      cxt.moveTo(piece.p[0].x, piece.p[0].y)
      for (var i = 1; i < piece.p.length; i++) {
        cxt.lineTo(piece.p[i].x, piece.p[i].y)
      }
      cxt.closePath()

      cxt.fillStyle = piece.color
      cxt.fill()

      cxt.strokeStyle = "black"
      cxt.lineWidth = 3
      cxt.stroke()
    }

图示:

箭头

    context.beginPath()
    context.moveTo(100, 350) 
    context.lineTo(500, 350) 
    context.lineTo(500, 200) 
    context.lineTo(700, 400)
    context.lineTo(500, 600)
    context.lineTo(500, 450)
    context.lineTo(100, 450)
    context.closePath()
    
    context.lineWidth = 5  
    context.strokeStyle = '#058'

    context.stroke() 

图示:

五角星

如下图所示:五角星外面的五个顶点都在外圆上,里面的五个顶点都在内圆上

五角星的10个顶点,外圆的每个顶点相差72度,同理,内圆的每个顶点也相差72度

算出每个顶点的坐标

最后用线段连接起来

代码:

    const canvas = document.getElementById('canvas')
    canvas.width = 800
    canvas.height = 800
    const context = canvas.getContext('2d')    

    const translateX = 400  // 让圆心在X轴的中心位置
    const bigRadius = 300   // 大圆半径
    const smallRadius = 150 // 小圆半径
    context.beginPath()
    for(let i = 0; i < 5; i++) {
      context.lineTo(
        Math.cos((18 + i * 72) / 180 * Math.PI) * bigRadius + translateX,
        -Math.sin((18 + i * 72) / 180 * Math.PI) * bigRadius + translateX
      )
      context.lineTo(
        Math.cos((54 + i * 72) / 180 * Math.PI) * smallRadius + translateX,
        -Math.sin((54 + i * 72) / 180 * Math.PI) * smallRadius + translateX
      )
    }
    context.closePath()

    context.lineWidth = 10
    context.stroke()

图示:

 绘制弯月

代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>

  <script>
    const canvas = document.getElementById('canvas')
    canvas.width = 800
    canvas.height = 800
    const context = canvas.getContext('2d')

    fillMoon(context, 2, 400, 400, 300, 0)

    function fillMoon(cxt, d, x, y, R, rot, fillColor) {
      cxt.save()
      cxt.translate(x, y)
      cxt.rotate(rot * Math.PI / 180)
      cxt.scale(R, R)
      pathMoon(cxt, d)
      cxt.fillStyle = fillColor || '#fb5'
      cxt.fill()
      cxt.restore()
    }

    function pathMoon(cxt, d) {
      cxt.beginPath()
      cxt.arc(0, 0, 1, 0.5*Math.PI, 1.5*Math.PI, true)
      cxt.moveTo(0, -1)
      cxt.arcTo(d, 0, 0, 1, dis(0, -1, d, 0) / d)
      cxt.closePath()
    }

    function dis(x1, y1, x2, y2) {
      return Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
    }

  </script>
</body>

</html>

图示:

星空

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>

  <script>
    const canvas = document.getElementById('canvas')
    canvas.width = 1200
    canvas.height = 800
    const context = canvas.getContext('2d')

    const skyStyle = context.createLinearGradient(0, 0, 0, canvas.height)
    skyStyle.addColorStop(0.0, 'black')
    skyStyle.addColorStop(1.0, '#035')
    context.fillStyle = skyStyle
    context.fillRect(0, 0, canvas.width, canvas.height)

    for (let i = 0; i < 200; i++) {
      const R = Math.random() * 5 + 5
      const r = R / 2.0
      const x = Math.random() * canvas.width
      const y = Math.random() * canvas.height * 0.65
      const rot = Math.random() * 360

      drawStar(context, r, R, x, y, rot)
    }

    fillMoon(context, 2, 900, 200, 100, 30)

    drawLand(context)

    function drawLand(cxt) {
      cxt.save()

      cxt.beginPath()
      cxt.moveTo(0, 600)
      cxt.bezierCurveTo(540, 400, 660, 800, 1200, 600)
      cxt.lineTo(1200, 800)
      cxt.lineTo(0, 800)
      cxt.closePath()

      const landStyle = cxt.createLinearGradient(0, 800, 0, 0)
      landStyle.addColorStop(0.0, '#030')
      landStyle.addColorStop(1.0, '#580')
      cxt.fillStyle = landStyle
      cxt.fill()

      cxt.restore()
    }

    function fillMoon(cxt, d, x, y, R, rot, fillColor) {
      cxt.save()
      cxt.translate(x, y)
      cxt.rotate(rot * Math.PI / 180)
      cxt.scale(R, R)
      pathMoon(cxt, d)
      cxt.fillStyle = fillColor || '#fb5'
      cxt.fill()
      cxt.restore()
    }

    function pathMoon(cxt, d) {
      cxt.beginPath()
      cxt.arc(0, 0, 1, 0.5 * Math.PI, 1.5 * Math.PI, true)
      cxt.moveTo(0, -1)
      //cxt.arcTo(d, 0, 0, 1, dis(0, -1, d, 0) / d)
      cxt.quadraticCurveTo(1.2, 0, 0, 1)
      cxt.closePath()
    }

    function dis(x1, y1, x2, y2) {
      return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    }

    function drawStar(cxt, r, R, x, y, rot) {
      cxt.save()

      cxt.translate(x, y)
      cxt.rotate(rot / 180 * Math.PI)
      cxt.scale(R, R)

      starPath(cxt)

      cxt.fillStyle = '#fb3'
      // cxt.strokeStyle = '#fd5'
      // cxt.lineWidth = 3
      // cxt.lineJoin = 'round'

      cxt.fill()
      //cxt.stroke()

      cxt.restore()
    }

    function starPath(cxt) {
      cxt.beginPath()
      for (let i = 0; i < 5; i++) {
        cxt.lineTo(
          Math.cos((18 + i * 72) / 180 * Math.PI),
          -Math.sin((18 + i * 72) / 180 * Math.PI)
        )
        cxt.lineTo(
          Math.cos((54 + i * 72) / 180 * Math.PI) * 0.5,
          -Math.sin((54 + i * 72) / 180 * Math.PI) * 0.5
        )
      }
      cxt.closePath()
    }

  </script>
</body>

</html>

图示:

圆角矩形

本质上是4条线段和4个弧线,共8个部分组成

代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>

  <script>
    const canvas = document.getElementById('canvas')
    canvas.width = 800
    canvas.height = 800
    const context = canvas.getContext('2d')

    drawRoundRect(context, 100, 100, 600, 400, 20)

    function drawRoundRect(cxt, x, y, width, height, radius) {
      cxt.save()
      cxt.translate(x, y)
      pathRoundRect(cxt, width, height, radius)
      cxt.strokeStyle = 'black'
      cxt.stroke()
      cxt.restore()
    }

    function pathRoundRect(cxt, width, height, radius) {
      cxt.beginPath()
      cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2)
      cxt.lineTo(radius, height)

      cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI)
      cxt.lineTo(0, radius)

      cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2)
      cxt.lineTo(width - radius, 0)

      cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2)
      cxt.closePath()
    }

  </script>
</body>

</html>

图示:

绘制2048棋盘

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <canvas id="canvas" style="border:1px solid #ccc;display:block;margin:50px auto;"></canvas>

  <script>
    const canvas = document.getElementById('canvas')
    canvas.width = 800
    canvas.height = 800
    const context = canvas.getContext('2d')

    fillRoundRect(context, 150, 150, 500, 500, 10, '#bbada0')
    for(let i = 0; i < 4; i++) {
      for (let j = 0; j < 4; j++) {
        fillRoundRect(context, 170+i*120, 170 + j * 120, 100, 100, 6, '#ccc0b3')
      }
    }

    function fillRoundRect(cxt, x, y, width, height, radius, fillColor) {
      if (2*radius > width || 2*radius > height) {
        return
      }

      cxt.save()
      cxt.translate(x, y)
      pathRoundRect(cxt, width, height, radius)
      cxt.fillStyle = fillColor || 'black'
      cxt.fill()
      cxt.restore()
    }

    function strokeRoundRect(cxt, x, y, width, height, radius, lineWidth, strokeColor) {
      if (2 * radius > width || 2 * radius > height) {
        return
      }

      cxt.save()
      cxt.translate(x, y)
      pathRoundRect(cxt, width, height, radius)
      cxt.lineWidth = lineWidth || 1
      cxt.strokeStyle = strokeColor || 'black'
      cxt.stroke()
      cxt.restore()
    }

    function pathRoundRect(cxt, width, height, radius) {
      cxt.beginPath()
      cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2)
      cxt.lineTo(radius, height)

      cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI)
      cxt.lineTo(0, radius)

      cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2)
      cxt.lineTo(width - radius, 0)

      cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2)
      cxt.closePath()
    }

  </script>
</body>

</html>

图示:

1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值