This article will cover some canvas related drawing techniques, including:

  • Drawing API
  • Image to load
  • Pixel processing

Drawing API

The related API can be referenced, but I won’t go into detail here.

  • CanvasRenderingContext2D

Here are some examples

The mouse drawing

The code is as follows:

<canvas id="mainCanvas" style="background-color: #fff;" width="800" height="400"></canvas>
Copy the code
const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const context = canvas.getContext('2d')
  if (context) {
    const { offsetLeft, offsetTop } = canvas
    let x
    let y

    const mouseMoveHandler = (e: MouseEvent) = > {
      x = e.pageX
      y = e.pageY
      x -= offsetLeft
      y -= offsetTop
      context.lineTo(x, y)
      context.lineCap = 'round'
      context.lineJoin = 'round'
      context.stroke()
    }

    canvas.addEventListener('mousedown'.(e) = > {
      context.beginPath()
      context.moveTo(e.pageX - offsetLeft, e.pageY - offsetTop)
      canvas.addEventListener('mousemove', mouseMoveHandler)
    })

    canvas.addEventListener('mouseup'.() = > {
      canvas.removeEventListener('mousemove', mouseMoveHandler)
    })
  }
}
Copy the code

Results the following

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

Draw the curve

Quadratic Bezier curve

Specific apis can reference documentation CanvasRenderingContext2D. QuadraticCurveTo ()

ctx.quadraticCurveTo(cpx, cpy, x, y);
Copy the code

It takes 2 points. The first point is the control point and the second point is the end point. The starting point is the most recent point of the current path, which can be changed using the moveTo() method before creating a quadratic Bezier curve.

The next step is to implement a demo that uses the mouse position as the control point to control the quadratic Bezier curve.

const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const context = canvas.getContext('2d')
  const { offsetLeft, offsetTop } = canvas

  const x0 = 300
  const y0 = 100
  const x1 = 600
  const y1 = 300

  if (context) {
    canvas.addEventListener('mousemove'.(e) = > {
      context.clearRect(0.0, canvas.width, canvas.height)
      const x = e.pageX - offsetLeft
      const y = e.pageY - offsetTop

      context.beginPath()
      context.moveTo(x0, y0)
      context.quadraticCurveTo(x, y, x1, y1)
      context.stroke()
    })
  }
}
Copy the code

Results the following

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

Quadratic Bezier curves through control points

const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const context = canvas.getContext('2d')
  const { offsetLeft, offsetTop } = canvas

  const x0 = 300
  const y0 = 100
  const x1 = 600
  const y1 = 300

  if (context) {
    canvas.addEventListener('mousemove'.(e) = > {
      context.clearRect(0.0, canvas.width, canvas.height)
      const x = e.pageX - offsetLeft
      const y = e.pageY - offsetTop

      const cpx = x * 2 - (x0 + x1) / 2
      const cpy = y * 2 - (y0 + y1) / 2

      context.beginPath()
      context.moveTo(x0, y0)
      context.quadraticCurveTo(cpx, cpy, x1, y1)
      context.stroke()
    })
  }
}
Copy the code

Its core is

const cpx = x * 2 - (x0 + x1) / 2
const cpy = y * 2 - (y0 + y1) / 2
Copy the code

Results the following

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

More curves

Draw a smooth curve, controlled by multiple points

import Ball from '.. /common/Ball'

const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const ctx = canvas.getContext('2d')

  if (ctx) {
    const points = []
    const num = 4

    for (let i = 0; i < num; i += 1) {
      const ball = new Ball(2)
      const x = Math.random() * canvas.width
      const y = Math.random() * canvas.height
      points.push({
        x,
        y,
      })
      ball.x = x
      ball.y = y
      ball.draw(ctx)
    }

    ctx.beginPath()
    ctx.moveTo(points[0].x, points[0].y)

    for (let i = 1; i < num - 2; i += 1) {
      const xAv = (points[i].x + points[i + 1].x) / 2
      const yAv = (points[i].y + points[i + 1].y) / 2
      ctx.quadraticCurveTo(points[i].x, points[i].y, xAv, yAv)
    }
    ctx.quadraticCurveTo(points[num - 2].x, points[num - 2].y, points[num - 1].x, points[num - 1].y)
    ctx.stroke()
  }
}
Copy the code

The xAv and yAv edges are set to the average of the x and y coordinates of the current and subsequent points in the loop, so that a smooth curve can be drawn

Results the following

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

A closed curve

import Ball from '.. /common/Ball'

const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const ctx = canvas.getContext('2d')

  if (ctx) {
    const points = []
    const num = 4

    for (let i = 0; i < num; i += 1) {
      const ball = new Ball(2)
      const x = Math.random() * canvas.width
      const y = Math.random() * canvas.height
      points.push({
        x,
        y,
      })
      ball.x = x
      ball.y = y
      ball.draw(ctx)
    }

    const xAv1 = (points[0].x + points[num - 1].x) / 2
    const yAv1 = (points[0].y + points[num - 1].y) / 2

    ctx.beginPath()
    ctx.moveTo(xAv1, yAv1)

    for (let i = 0; i < num - 1; i += 1) {
      const xAv = (points[i].x + points[i + 1].x) / 2
      const yAv = (points[i].y + points[i + 1].y) / 2
      ctx.quadraticCurveTo(points[i].x, points[i].y, xAv, yAv)
    }
    ctx.quadraticCurveTo(points[num - 1].x, points[num - 1].y, xAv1, yAv1)
    ctx.stroke()
  }
}
Copy the code

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

Graphics and fill colors

Generally speaking, the drawing order is as follows:

  • BeginPath Begins to draw
  • MoveTo moves the starting point
  • Graphics.linestyle line style
  • FillStyle fillStyle
  • LineTo, quadraticCurveTo, etc
  • ClosePath closed
  • The fill to fill
  • Stroke stroke

gradient

ctx.createLinearGradient(x0, y0, x1, y1)

The createLinearGradient() method requires you to specify four parameters representing the start and end points of the gradient line segment.

ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)

Arc () is the Canvas 2D API’s method for drawing arc paths. The arc path has a center at (x, y), radius r, and starts with startAngle and ends with endAngle in the direction specified by AnticLockWise (which defaults to clockwise).

const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const ctx = canvas.getContext('2d')

  if (ctx) {
    ctx.beginPath()
    const gradient = ctx.createLinearGradient(100.100.200.200)
    gradient.addColorStop(0.'#ff0000')
    gradient.addColorStop(1.'# 000000')
    ctx.fillStyle = gradient
    ctx.fillRect(100.100.100.100)

    const gradient2 = ctx.createLinearGradient(200.200.300.300)
    gradient2.addColorStop(0.'#ff0000')
    gradient2.addColorStop(0.6.'# 008880')
    gradient2.addColorStop(1.'# 000000')
    ctx.fillStyle = gradient2
    ctx.fillRect(200.200.100.100)

    const gradient3 = ctx.createRadialGradient(500.200.0.500.200.100)
    gradient3.addColorStop(0.'# 000000')
    gradient3.addColorStop(1.'#ff0000')
    ctx.arc(500.200.100.0.2 * Math.PI)
    ctx.fillStyle = gradient3
    ctx.fill()
  }
}
Copy the code

The effect is as follows:

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

Image to load

For some scenarios, you may need to draw an image inside the canvas. Let’s look at how to draw the image

Draw pictures

const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const ctx = canvas.getContext('2d')
  if (ctx) {
    const img = new Image()
    img.src = 'https://gw.alicdn.com/imgextra/i2/O1CN01gR6ymq1dfV5RmYxYk_!! 6000000003763-2-tps-658-411.png'
    img.addEventListener('load'.() = > {
      ctx.drawImage(img, 0.0.658.329.0.0.800.400)}}}Copy the code

Results the following

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

Operate pixels

Let’s try removing all the green pixels from the demo above and see what happens

const canvas: HTMLCanvasElement | null = document.querySelector('#mainCanvas')

if (canvas) {
  const ctx = canvas.getContext('2d')
  if (ctx) {
    const img = new Image()
    img.src = '.. /assets/1.png'
    img.addEventListener('load'.() = > {
      ctx.drawImage(img, 0.0.658.329.0.0, canvas.width, canvas.height)

      const imageData = ctx.getImageData(0.0, canvas.width, canvas.height)
      const pixels = imageData.data
      for (let i = 0; i < pixels.length; i += 4) {
        pixels[i + 1] = 0
      }
      ctx.putImageData(imageData, 0.0)}}}Copy the code

The effect is as follows:

The demo link gaohaoyang. Making. IO/canvas – prac…

Source link github.com/Gaohaoyang/…

conclusion

This article doesn’t cover much animation, but it does give you an example of how to draw on Canvas 2D, and shows you how to load images and manipulate pixels. This set the foundation for the following animation learning.