Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 Canvas + JS Not Working on IOS/Safari

I've implemented a canvas element with a javascript particle effect. The effect is working on every browser but IOS/Safari. I've done a bit of research and IOS/Safari supports HTML5/Canvas: According to Browser Support Charts for HTML5/Canvas

$(function() {
  var WIDTH = window.innerWidth * .9,
    HEIGHT = window.innerHeight,
    MAX_PARTICLES = 100,
    DRAW_INTERVAL = 60,
    canvas = document.querySelector('#pixies'),
    context = canvas.getContext('2d'),
    gradient = null,
    pixies = new Array();

  function setDimensions() { 
    WIDTH = window.outerWidth;
    HEIGHT = window.innerHeight;
    canvas.width = WIDTH; 
    canvas.height = HEIGHT; 
  }

  setDimensions();
  window.addEventListener('resize', setDimensions);

  function Circle() {
    this.settings = {ttl:8000, xmax:5, ymax:2, rmax:10, rt:1, xdef:960, ydef:540, xdrift:4, ydrift: 4, random:true, blink:true};

    this.reset = function() {
      this.x = (this.settings.random ? WIDTH*Math.random() : this.settings.xdef);
      this.y = (this.settings.random ? HEIGHT*Math.random() : this.settings.ydef);
      this.r = ((this.settings.rmax-1)*Math.random()) + 1;
      this.dx = (Math.random()*this.settings.xmax) * (Math.random() < .5 ? -1 : 1);
      this.dy = (Math.random()*this.settings.ymax) * (Math.random() < .5 ? -1 : 1);
      this.hl = (this.settings.ttl/DRAW_INTERVAL)*(this.r/this.settings.rmax);
      this.rt = Math.random()*this.hl;
      this.settings.rt = Math.random()+1;
      this.stop = Math.random()*.2+.4;
      this.settings.xdrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
      this.settings.ydrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
    }

    this.fade = function() {
      this.rt += this.settings.rt;
    }

    this.draw = function() {
      if(this.settings.blink && (this.rt <= 0 || this.rt >= this.hl)) {
          this.settings.rt = this.settings.rt*-1;
      } else if(this.rt >= this.hl) {
          this.reset();
      }

      var newo = 1-(this.rt/this.hl);
      context.beginPath();
      context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
      context.closePath();

      var cr = this.r*newo;
      gradient = context.createRadialGradient(this.x, this.y, 0, this.x, this.y, (cr <= 0 ? 1 : cr));
      gradient.addColorStop(0.0, 'rgba(255,255,255,'+newo+')');
      gradient.addColorStop(this.stop, 'rgba(255,255,255,'+(newo*.6)+')');
      gradient.addColorStop(1.0, 'rgba(255,255,255,0)');
      context.fillStyle = gradient;
      context.fill();
    }

    this.move = function() {
      this.x += (this.rt/this.hl)*this.dx;
      this.y += (this.rt/this.hl)*this.dy;
      if(this.x > WIDTH || this.x < 0) this.dx *= -1;
      if(this.y > HEIGHT || this.y < 0) this.dy *= -1;
    }

    this.getX = function() { return this.x; }
    this.getY = function() { return this.y; }
  }

  for (var i = 0; i < MAX_PARTICLES; i++) {
    pixies.push(new Circle());
    pixies[i].reset();
  }

  function draw() {
    context.clearRect(0, 0, WIDTH, HEIGHT);
    for(var i = 0; i < pixies.length; i++) {
      pixies[i].fade();
      pixies[i].move();
      pixies[i].draw();
    }
  }

  setInterval(draw, DRAW_INTERVAL);
});
#particles {
  position: absolute;
  background: navy;
  width: 200px;
  height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="particles">
   <canvas id="pixies"></canvas>
</div>

Any ideas why this isn't working in IOS/Safari? The actual site in question is this one: www.pjmaskslive.com

like image 260
Joel Hoelting Avatar asked Oct 30 '22 07:10

Joel Hoelting


1 Answers

The issue appears to be that the canvas elements width is set 0 on the aforementioned website. So I would assume that the issue is setting the WIDTH variable at the start. This might be due to an ongoing bug with iOS 10 as mentioned in this question.

An alternative approach might be to use document.body.getBoundingClientRect().width as an alternative to window.innerWidth and/or window.outerWidth. screen.width could also be used, however, these could also have the same issues as your previous methods.

Seems like a safari issue rather than your code either way!

like image 122
Lennart Avatar answered Nov 15 '22 06:11

Lennart