Kaizokupuffball
Kaizokupuffball

Reputation: 2843

HTML5 canvas for loop wont draw the first object in array

So basically. I'm trying to loop through each letter in a text (in this case the text is "marius"). Now, the problem is that the first letter is never drawn. If the text is "marius", it draws "arius". I've tried what I can think of, but I can't find the error. Does anyone know what I am doing wrong? Don't worry about anything else. The code is not done, but this problem if eating my brains out. Thanks in advance. :)

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>

Upvotes: 2

Views: 76

Answers (1)

NtFreX
NtFreX

Reputation: 11377

The problem in your implementation is that you set the ctx.fillStyle after you do the fillText call. This means that you only set the fillStyle of the second letter and as the default fillStyle is black the first will not be visible. If you switch the two lines it will work.

Then you have a second mistake which is that the first and the second letter are at the same x position. I changed the preparation method and the draw method to make the letter spacing work properly.

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>

Upvotes: 3

Related Questions