This is the 9th day of my participation in Gwen Challenge

Introduction to the

  • For better usecanvasTo achieve the effect of text particles.
  • Basically by creating one in the cachecanvasElement node, draw the text on thiscanvasNode. Then use thegetImageData()Function, getcanvasThe values of all images on. According to the image number color value, determine where to generate particles.

Text rendering

<! DOCTYPEhtml>
<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 type="text/css"></style>
  <body>
    <canvas height="400" width="600" id="canvas"></canvas>
  </body>
  <script>
    // Text particles
    / * *@type {HTMLCanvasElement} * /
    var canvas = document.getElementById('canvas')
    var ctx = canvas.getContext('2d')
    ctx.clearRect(0.0, canvas.width, canvas.height)

    function loadCanvas(value) {
      var fontSize = 100 // Text size
      // Text length
      var width = calWordWidth(value, fontSize)
      var canvasTxt = document.createElement('canvas')
      canvasTxt.width = width
      canvasTxt.height = fontSize
      var ctxTxt = canvasTxt.getContext('2d')
      ctxTxt.font = fontSize + 'px Microsoft YaHei'
      ctxTxt.fillStyle = 'orange'
      ctxTxt.fillText(value, 0, fontSize - 16) // Adjust the position of the drawing character

      // Put it in HTML
      document.body.appendChild(canvasTxt)
    }

    // Pass in the text
    loadCanvas('learning')

    /** * calculates the total length of text ** /
    function calWordWidth(value, fontSize) {
      var arr = value.split(' ')
      var reg = /\w/
      var width = 0
      arr.forEach(function (item, index) {
        if (reg.test(item)) {
          width += fontSize // Letter width
        } else {
          width += fontSize + 10 // Width of Chinese characters}})return width
    }
  </script>
</html>
Copy the code

  • This is mainly throughdocument.createElement('canvas')A node is created and the text information is drawn on the canvas.

Get the number of images using getImageData

  • getImageData()Method returnsImageDataObject that copies the pixel data of the rectangle specified on the canvas.
  • This object is a one-dimensional array. Because every pixelRGBA valuesIs made up ofFour values. soLike a numberCorresponding to arrayFour valuesAnd the array position is fixed.
    // Get the image number
    function getImage(canvas, ctx) {
      var imageData = ctx.getImageData(0.0, canvas.width, canvas.height)
      console.log('🚀 ~ file: index.html ~ line 39 ~ getImage ~ imageData', imageData)
    }
Copy the code

Add particle class

    var particles = [] // All particles
    /** * particle ** /
    function Particle(option) {
      this.radius = option.radius || 6
      this.color = option.color || '# 000'
      this.x = option.x || 0
      this.y = option.y || 0
      this.dynamicRadius = option.radius || 6
    }
    Particle.prototype.draw = function (ctx) {
      var x, y
      x = this.x * 3 + 50
      y = this.y * 3 + 50
      ctx.beginPath()
      ctx.arc(x, y, this.dynamicRadius, 0.2 * Math.PI, false)
      ctx.fillStyle = this.color
      ctx.fill()
    }
    Particle.prototype.update = function () {
      this.dynamicRadius = 5 + 2 * Math.sin(((new Date(a) /1000) % 1000) * this.radius)
    }
Copy the code
  • Create particle class to facilitate the later management of particle data.

Draw particles on canvas

    // Generate text
    function loadCanvas(value) {... getImage(canvasTxt, ctxTxt)// Put it in HTML
      // document.body.appendChild(canvasTxt)
    }
    
    // Get the image number
    function getImage(canvas, ctx) {
      var imageData = ctx.getImageData(0.0, canvas.width, canvas.height)

      var diff = 4
      var newCanvas = document.getElementById('canvas')
      var newCtx = newCanvas.getContext('2d')
      // Iterate over all arrays
      for (var j = 0; j < canvas.height; j += diff) {
        for (var i = 0; i < canvas.width; i += diff) {
          // The default transparency is 255 when colors are present
          var opacityIndex = (i + j * canvas.width) * 4 + 3
          if (imageData.data[opacityIndex] > 0) {
            // Add the particle object
            var par = new Particle({ radius: 0.color: '# 000'.x: i, y: j })
            particles.push(par)
            // particles.draw(newCtx)
          }
        }
      }
    }

    requestAnimationFrame(function loop() {
      // requestAnimationFrame(loop)
      ctx.clearRect(0.0, canvas.width, canvas.height)
      for (const particle of particles) {
        particle.draw(ctx)
      }
    })
    
    // Pass in the text
    loadCanvas('learning')...Copy the code

  • traverseimageDataThe object of thedata, the opacity defaults to 255 when the color is present, so this determines whether the fourth value is not zero to determine whether the pixel is in the text.
  • The resulting particle object is put into the array, and the later modification of the particle does not need to recalculate the position.

Add a simple animation

    requestAnimationFrame(function loop() {
      requestAnimationFrame(loop)
      ctx.clearRect(0.0, canvas.width, canvas.height)
      for (const particle of particles) {
        particle.update()
        particle.draw(ctx)
      }
    })
Copy the code
  • Because the particle object is already stored in an array. All we have to do isupdate()Function to add animation logic, and then redraw to achieve animation.