javascript - HTML5 canvas for 循环不会绘制数组中的第一个对象

标签 javascript html canvas

基本上就是这样。我试图循环遍历文本中的每个字母(在本例中文本是“marius”)。现在的问题是第一个字母从未被绘制。如果文本是“marius”,则绘制“arius”。我已经尝试了我能想到的,但我找不到错误。有谁知道我做错了什么?不用担心其他任何事情。代码还没写完,但是这个问题真是费了我的脑筋。提前致谢。 :)

WebFont.load({

  google: {
    families: ['Audiowide']
  },

  active: function() {

    // Just the requestAnimationFrame
    // for different types of browsers
    const requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;

    // Canvas
    const c = document.getElementById('canvas');
    const ctx = c.getContext('2d');
    const cWidth = c.width = window.innerWidth;
    const cHeight = c.height = window.innerHeight;

    // Framerate settings
    // Better not touch theese if you
    // do not know what you are doing
    let now, delta;
    let fps = (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) ? 29 : 60;
    let then = Date.now();
    const interval = 1000 / fps;



    /*-------------------------------------------------------
    					PREPARATION BELOW
    -------------------------------------------------------*/

    var text = 'marius';
    var letters = [];
    var lettersCount;
    const config = {
      'background': '#222',
      'letterSize': '72px',
      'letterFont': 'Audiowide',
      'letterSpacing': 50,
      'amp': 60,
      'yOffset': cHeight / 2
    };

    for (let i = 0, lettersCount = text.length; i < lettersCount; i++) {
      letters.push(new Letter(text[i]));
    }

    for (let i = 0, len = letters.length; i < len; i++) {
      var addThisToo = (i == 0) ? 0 : letters[i - 1].letterOffset;
      var letterWidth = getTextWidth(letters[i].letter, config.letterSize + ' ' + config.letterFont);
      letters[i].letterOffset = letterWidth + addThisToo;
    }

    /*-------------------------------------------------------
    					END PREPARATION
    -------------------------------------------------------*/



    /**
     * draw()
     * The draw function, where everything is happening
     * @return null
     */
    function draw() {

      looper();
      if (delta > interval) {

        // Calculate then
        then = now - (delta % interval);

        // All your own stuff here
        drawBackground();
        drawLetters();

      }

    }

    /**
     * drawLetters()
     * Draw the letters from letters Array
     * Sinusoidal wave!
     */
    function drawLetters() {

      for (let i = 0, len = letters.length; i < len; i++) {

        // Prepare X and Y of the letter
        let letterOffset = (i > 0) ? letters[i - 1].letterOffset : letters[i].letterOffset;
        let x = letters[i].xPos + letterOffset;
        let y = config.yOffset + (sin(letters[i].xPos / 45 + i) * config.amp);

        // Create gradient color
        var gradient = ctx.createLinearGradient(0, 0, cWidth, 0);
        gradient.addColorStop('0', '#ff6666');
        gradient.addColorStop('0.5', '#66ff66');
        gradient.addColorStop('1', '#6666ff');

        // Draw and fill the letter
        ctx.font = config.letterSize + ' ' + config.letterFont;
        ctx.fillText(letters[i].letter, x, y);
        ctx.fillStyle = gradient;

        // Update letter X and Y position
        letters[i].yPos += 0.05 * i;
        letters[i].xPos -= letters[i].xVel;


      }

    }

    /**
     * letter(letter)
     * Letter object
     * @return nul
     */
    function Letter(letter) {

      this.letter = letter;
      this.xPos = cWidth;
      this.yPos = 0;
      this.xVel = 2;
      this.yVel = 0;
      this.letterOffset = 0;

    }

    /**
     * Looper()
     * Looper function, do not touch!
     * @return null
     */
    function looper() {
      requestAnimationFrame(draw);
      now = Date.now();
      delta = now - then;
    }

    /**
     * drawBackground()
     * Draws the background
     * @return null
     */
    function drawBackground() {
      ctx.fillStyle = config.background;
      ctx.fillRect(0, 0, c.width, c.height);
    }

    /**
     * randInt(min, max)
     * Returns random integer between min - max
     * @param integer min
     * @param integer max
     * @return integer
     */
    function randInt(min, max) {
      max = max === undefined ? min - (min = 0) : max;
      return Math.floor(Math.random() * (max - min) + min);
    }

    /**
     * sin(x)
     * Sinus of X
     * @return float
     */
    function sin(x) {
      return Math.sin(x);
    }

    /**
     * getTextWidth(text, font)
     * Return the width of the text
     * @return integer
     */
    function getTextWidth(text, font) {
      ctx.font = font;
      var metrics = ctx.measureText(text);
      return Math.round(metrics.width);
    }

    /**
     * EventListener - Click
     */
    document.addEventListener('click', function(e) {

      let x, y;

      if (e.offsetX) {
        x = e.offsetX;
        y = e.offsetY;
      } else if (e.layerX) {
        x = e.layerX;
        y = e.layerY;
      }

    });

    requestAnimationFrame(draw);

  }

});
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js"></script>

<canvas id="canvas"></canvas>

最佳答案

您的实现中的问题是您在执行 fillText 调用后设置了 ctx.fillStyle。这意味着您只需设置第二个字母的 fillStyle,并且由于默认的 fillStyle 为黑色,因此第一个字母将不可见。如果你切换两条线,它就会起作用。

那么你还有第二个错误,那就是第一个和第二个字母位于相同的x位置。我改变了准备方法和绘制方法,使字母间距正常工作。

WebFont.load({

  google: {
    families: ['Audiowide']
  },

  active: function() {

    // Just the requestAnimationFrame
    // for different types of browsers
    const requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;

    // Canvas
    const c = document.getElementById('canvas');
    const ctx = c.getContext('2d');
    const cWidth = c.width = window.innerWidth;
    const cHeight = c.height = window.innerHeight;

    // Framerate settings
    // Better not touch theese if you
    // do not know what you are doing
    let now, delta;
    let fps = (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) ? 29 : 60;
    let then = Date.now();
    const interval = 1000 / fps;



    /*-------------------------------------------------------
    					PREPARATION BELOW
    -------------------------------------------------------*/

    var text = 'marius';
    var letters = [];
    var lettersCount;
    const config = {
      'background': '#222',
      'letterSize': '72px',
      'letterFont': 'Audiowide',
      'letterSpacing': 50,
      'amp': 60,
      'yOffset': cHeight / 2
    };

    for (let i = 0, lettersCount = text.length; i < lettersCount; i++) {
      letters.push(new Letter(text[i]));
    }

    for (let i = 1, len = letters.length; i < len; i++) {
      var addThisToo = letters[i - 1].letterOffset;
      var letterWidth = getTextWidth(letters[i - 1].letter, config.letterSize + ' ' + config.letterFont);
      letters[i].letterOffset = letterWidth + addThisToo + config['letterSpacing'];
    }

    /*-------------------------------------------------------
    					END PREPARATION
    -------------------------------------------------------*/



    /**
     * draw()
     * The draw function, where everything is happening
     * @return null
     */
    function draw() {

      looper();
      if (delta > interval) {

        // Calculate then
        then = now - (delta % interval);

        // All your own stuff here
        drawBackground();
        drawLetters();

      }

    }

    /**
     * drawLetters()
     * Draw the letters from letters Array
     * Sinusoidal wave!
     */
    function drawLetters() {

      for (let i = 0, len = letters.length; i < len; i++) {

        // Prepare X and Y of the letter
        let letterOffset = letters[i].letterOffset;
        let x = letters[i].xPos + letterOffset;
        let y = config.yOffset + (sin(letters[i].xPos / 45 + i) * config.amp);

        // Create gradient color
        var gradient = ctx.createLinearGradient(0, 0, cWidth, 0);
        gradient.addColorStop('0', '#ff6666');
        gradient.addColorStop('0.5', '#66ff66');
        gradient.addColorStop('1', '#6666ff');

        // Draw and fill the letter
        ctx.font = config.letterSize + ' ' + config.letterFont;
        ctx.fillStyle = gradient;
        ctx.fillText(letters[i].letter, x, y);

        // Update letter X and Y position
        letters[i].yPos += 0.05 * i;
        letters[i].xPos -= letters[i].xVel;


      }

    }

    /**
     * letter(letter)
     * Letter object
     * @return nul
     */
    function Letter(letter) {

      this.letter = letter;
      this.xPos = cWidth;
      this.yPos = 0;
      this.xVel = 2;
      this.yVel = 0;
      this.letterOffset = 0;

    }

    /**
     * Looper()
     * Looper function, do not touch!
     * @return null
     */
    function looper() {
      requestAnimationFrame(draw);
      now = Date.now();
      delta = now - then;
    }

    /**
     * drawBackground()
     * Draws the background
     * @return null
     */
    function drawBackground() {
      ctx.fillStyle = config.background;
      ctx.fillRect(0, 0, c.width, c.height);
    }

    /**
     * randInt(min, max)
     * Returns random integer between min - max
     * @param integer min
     * @param integer max
     * @return integer
     */
    function randInt(min, max) {
      max = max === undefined ? min - (min = 0) : max;
      return Math.floor(Math.random() * (max - min) + min);
    }

    /**
     * sin(x)
     * Sinus of X
     * @return float
     */
    function sin(x) {
      return Math.sin(x);
    }

    /**
     * getTextWidth(text, font)
     * Return the width of the text
     * @return integer
     */
    function getTextWidth(text, font) {
      ctx.font = font;
      var metrics = ctx.measureText(text);
      return Math.round(metrics.width);
    }

    /**
     * EventListener - Click
     */
    document.addEventListener('click', function(e) {

      let x, y;

      if (e.offsetX) {
        x = e.offsetX;
        y = e.offsetY;
      } else if (e.layerX) {
        x = e.layerX;
        y = e.layerY;
      }

    });

    requestAnimationFrame(draw);

  }

});
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js"></script>

<canvas id="canvas"></canvas>

关于javascript - HTML5 canvas for 循环不会绘制数组中的第一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44477909/

相关文章:

javascript - 在后续 PHP 代码中使用 Ajax 分配的变量

javascript - 将图像映射转换为 Canvas

javascript - Angular Radio ng-change 仅在第一次时有效

javascript - 展开后更改 anchor <a> 标签的背景图片 + CSS

javascript - 如何在嵌套表中选择不包含某些元素的标签?

html - 如何在该代码中垂直对齐 li 中的元素?

javascript - Facebook Canvas 应用程序 : Requests with Object

android - 如何水平旋转由 drawTextonPath 创建的圆形文本?

javascript - 如何获取传单 slider 的开始和结束

html - 如何正确叠加透明背景的图像?