Search code examples
javascriptioshtmlcanvasmaterialize

Canvas element not rendering on iOS devices


I have a canvas element on my site that renders perfectly in the desktop browser as well as on Android devices, but will not render on iOS devices (iPad, iPhone) - neither Safari nor Chrome on ios. I'm using Materialize as my CSS framework.

Is there something I need to add to my code?

Here is live version

var next; //initialize for interval
	//paint random colored pattern on profile screen
	function paintCanvas() {

		const c = document.querySelector("#canvas");
		const ctx = c.getContext("2d");
		c.width = window.outerWidth;

		const width = c.width;
		const height = 612; //canvas height

		const min = 0;
		const max = width;
		const yMid = height/2;
		var y1 = yMid;
		var y2 = yMid;

		function getRandomColor(){

			let r = Math.floor(Math.random()*256);
			let g = Math.floor(Math.random()*256);
			let b = Math.floor(Math.random()*256);
			let color = `rgba(${r}, ${g}, ${b}, 0.5)`;
			return color;
		}

		var x = 0;

		function paint() {

			if (x==(max/2)-2) {
				clearInterval(next);
			}
			ctx.lineWidth = 4; //sets width of line 
	    	ctx.strokeStyle = getRandomColor(); //assigns random color
	    	ctx.beginPath(); //start line
	    	ctx.moveTo(x,y1); //moves the origin
	    	ctx.lineTo(max-x,y2); //go to the bottom right corner
	 		ctx.moveTo(x, y2);
	 		ctx.lineTo(max-x, y1);
	    	ctx.stroke();
	    	
	    	if(y1==0) {
	    		x++;
	    	} else {
		    	y1--;
		    	y2++;
		    }

	    }

		next = setInterval(paint, 0.05);
	}

	paintCanvas();
main {
 position: relative;
}

#canvas {
	position: absolute;
	top:0;
	left:0;
	width: 100%;
	z-index: 0;
}
<main id="#top" role="main">

  <canvas id="canvas" width="100%" height = "612px"></canvas>
  
</main>


Solution

  • I solved this problem by enabling Web Inspector on my Ipad (Settings>>Safari>>Advanced) and then connecting to a friends Mac PC. Using Safari on the Mac, I was able to enable Web Inspector and thus view Apple's Developer Tools (Settings>>Advanced>>Show Develop Menu In Menu Bar).

    I found that the width for my <canvas> element was returning to zero. This meant that window.innerWidth was either returning 0 or null and thus resizing my canvas to zero width rather than to the width of the device.

    This led me to try using screen.width instead. This solved the problem. Since I know that window.innerWidth works on all other devices, I added a check on navigator.platform to use screen.width only on iOS devices.

        var next; //initialize for interval
    	//paint random colored pattern on profile screen
    	function paintCanvas() {
    
    		const c = document.querySelector("#canvas");
    		const ctx = c.getContext("2d");
    		
            //____________________________________________
            // ----------- FIX FOR THIS PROBLEM ----------
            //____________________________________________
    
            if ( navigator.platform != "iPad" && navigator.platform != "iPhone" && navigator.platform != "iPod" ) {
    		    c.width = window.outerWidth; 
                //I'll use window.innerWidth in production
    	    } else {
    		    c.width = screen.width;
    	    }
    
    		const width = c.width;
    		const height = 612; //canvas height
    
    		const min = 0;
    		const max = width;
    		const yMid = height/2;
    		var y1 = yMid;
    		var y2 = yMid;
    
    		function getRandomColor(){
    
    			let r = Math.floor(Math.random()*256);
    			let g = Math.floor(Math.random()*256);
    			let b = Math.floor(Math.random()*256);
    			let color = `rgba(${r}, ${g}, ${b}, 0.5)`;
    			return color;
    		}
    
    		var x = 0;
    
    		function paint() {
    
    			if (x==(max/2)-2) {
    				clearInterval(next);
    			}
    			ctx.lineWidth = 4; //sets width of line 
    	    	ctx.strokeStyle = getRandomColor(); //assigns random color
    	    	ctx.beginPath(); //start line
    	    	ctx.moveTo(x,y1); //moves the origin
    	    	ctx.lineTo(max-x,y2); //go to the bottom right corner
    	 		ctx.moveTo(x, y2);
    	 		ctx.lineTo(max-x, y1);
    	    	ctx.stroke();
    	    	
    	    	if(y1==0) {
    	    		x++;
    	    	} else {
    		    	y1--;
    		    	y2++;
    		    }
    
    	    }
    
    		next = setInterval(paint, 0.05);
    	}
    
    	paintCanvas();
    main {
     position: relative;
    }
    
    #canvas {
    	position: absolute;
    	top:0;
    	left:0;
    	width: 100%;
    	z-index: 0;
    }
    <main id="#top" role="main">
    
      <canvas id="canvas" width="100%" height = "612px"></canvas>
      
    </main>