Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

html5 canvas loading circle image

I'm trying to create a loading circle from an image in HTML5 canvas.

Here's the result I expect when percentage is at 50%:

enter image description here

here's what I've done after a lot of tests: (the blue stroke is just to see the circle, it'll be removed after)

var img = new Image(); 
img.onload = draw;
img.src = "http://i.imgur.com/HVJBZ1L.png";

var canvas = document.getElementsByTagName("canvas")[0];

canvas.width  = 500;
canvas.height = 500;

var ctx = canvas.getContext("2d");

function draw() {
    ctx.globalAlpha = 0.5
    ctx.drawImage(img, 0, 0);
    ctx.globalAlpha = 1;
    
    var X       = 50;
    var Y       = 50;
    var Radius  = img.width / 2;
    var end     = 40;
    var start   = 0;
    var PI2     = Math.PI * 2;
    var quart   = Math.PI / 2;
    var pct     = 50 / 100;
    var extent  = (end - start) * pct;
    var current = (end - start) / 100 * PI2 * pct - quart;
    
    var pattern = ctx.createPattern(img, 'no-repeat');
    
    ctx.beginPath();
    ctx.arc(X, Y, Radius, -quart, current);
    ctx.closePath();
    ctx.fillStyle=pattern;
  	ctx.fill();
    ctx.strokeStyle = "blue";
    ctx.stroke();
}
<canvas></canvas>

as you can see, the result here isn't as excepted

enter image description here

What is wrong?

like image 581
JeePing Avatar asked Jun 05 '17 14:06

JeePing


People also ask

How do I create a fill circle in HTML canvas?

The arc() method creates an arc/curve (used to create circles, or parts of circles). Tip: To create a circle with arc(): Set start angle to 0 and end angle to 2*Math. PI. Tip: Use the stroke() or the fill() method to actually draw the arc on the canvas.

How do I load an image into canvas in HTML?

Importing images into a canvas is basically a two step process: Get a reference to an HTMLImageElement object or to another canvas element as a source. It is also possible to use images by providing a URL. Draw the image on the canvas using the drawImage() function.

How do you circle a canvas?

To draw arcs or circles, we use the arc() or arcTo() methods. Draws an arc which is centered at (x, y) position with radius r starting at startAngle and ending at endAngle going in the given direction indicated by counterclockwise (defaulting to clockwise).


2 Answers

First, you need to correctly calculate your center point:

var X = img.width / 2;
var Y = img.height / 2;

Then you need to circle back in counter-clockwise direction tracing the inner radius Radius - 17:

ctx.beginPath();
ctx.arc(X, Y, Radius, -quart, current);
ctx.arc(X, Y, Radius - 17, current, -quart, true);
ctx.closePath();

If you aren't interested in the stroke outline, you could move to the center first, and then arc:

ctx.beginPath();
ctx.moveTo(X, Y);
ctx.arc(X, Y, Radius, -quart, current);
ctx.closePath();

Example:

var img = new Image(); 
img.onload = draw;
img.src = "http://i.imgur.com/HVJBZ1L.png";

var canvas = document.getElementsByTagName("canvas")[0];

canvas.width  = 500;
canvas.height = 500;

var ctx = canvas.getContext("2d");

function draw() {
    ctx.globalAlpha = 0.5
    ctx.drawImage(img, 0, 0);
    ctx.globalAlpha = 1;
    
    var X       = img.width / 2;
    var Y       = img.height / 2;
    var Radius  = img.width / 2;
    var end     = 40;
    var start   = 0;
    var PI2     = Math.PI * 2;
    var quart   = Math.PI / 2;
    var pct     = 50 / 100;
    var extent  = (end - start) * pct;
    var current = (end - start) / 100 * PI2 * pct - quart;
    
    var pattern = ctx.createPattern(img, 'no-repeat');
    
    ctx.beginPath();
    ctx.moveTo(X, Y);
    ctx.arc(X, Y, Radius, -quart, current);
    ctx.closePath();
    ctx.fillStyle = pattern;
    ctx.fill();
}
<canvas></canvas>
like image 175
le_m Avatar answered Oct 19 '22 23:10

le_m


const img = new Image(); 
img.src = "http://i.imgur.com/HVJBZ1L.png";
img.onload = imageLoaded;
var W,H; // width and height when image ready
const ctx = canvas.getContext("2d");
// define the distance of the progress 0- 100
const min = 0; 
const max = 100; 
var pattern;
var radius;
// get pattern, radius canvas size from image ans start animation
function imageLoaded(){
    requestAnimationFrame(mainLoop);
    W = this.width;
    H = this.height;
    pattern = ctx.createPattern(this, 'no-repeat');
    radius = W / 2;
    canvas.width  = W;
    canvas.height = H;    
}
// draw the background and forground images
// amount is the amount of progress. amount >= min amount <= max
function draw(amount) {  
    ctx.globalAlpha = 0.5
    ctx.drawImage(img, 0, 0);
    ctx.globalAlpha = 1;
 
    ctx.fillStyle=pattern;
    ctx.strokeStyle = "blue";
    ctx.beginPath();
    ctx.arc(  // draw inside circle CCW
      W/2,
      H/2, 
      radius - 17, 
      ((amount - min) / (max-min)) * Math.PI * 2 - Math.PI / 2,
      -Math.PI / 2,
      true
    );  
    ctx.arc( // draw outer circle CW
      W/2,
      H/2, 
      radius, 
      -Math.PI / 2,
      ((amount - min) / (max-min)) * Math.PI * 2 - Math.PI / 2
    );
    ctx.closePath();
  	ctx.fill();
    ctx.stroke();
}

// animate the thing.
function mainLoop(time){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    draw((time / 50) % max);

    requestAnimationFrame(mainLoop);
}
canvas { border : 2px solid black;}
<canvas id="canvas"></canvas>
like image 31
Blindman67 Avatar answered Oct 19 '22 22:10

Blindman67