Can you draw images in an arc on a canvas? - javascript

You can draw arcs and you can draw images on a canvas using javascript, but is there anyway to do both? that is, is there anyway to draw an image as the arc instead of a solid line?
If not, is there a seperate way to arc an image?
I tried doing a pixel-by-pixel transformation of the image along the points of an arc, but it ended up being very slow and looking pretty poor since I can't directly get pixel data from javascript (or can you? I didnt see a way) so for each pixel, I needed to calculate the point along the arc, draw the current image pixel, refetch it, draw the image data to the calculated point, then clear that point on the canvas.

Have you tried setting the strokeStyle to a CanvasPattern based on an image? It looks like you could do something like this (assuming img is an HTMLImageElement that you want to draw from and ctx is a CanvasRenderingContext2D):
var pattern = ctx.createPattern(img, "repeat");
ctx.strokeStyle = pattern;
ctx.beginPath();
ctx.arc(123, 408, 80, 0, 1.5*Math.PI, false);
ctx.stroke();

Use this html to create arc : -
<canvas id="myCanvas" width="578" height="250"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = .8 * Math.PI;
var endAngle = 2.2 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 30;
// line color
context.strokeStyle = 'blue';
context.stroke();
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 8 * Math.PI;
var endAngle =2.3 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 30;
// line color
context.strokeStyle = 'red';
context.stroke();
</script>

Related

How to reduce canvas stroke with animation

I am trying to add some animation on changing the endAngle of a canvas arc like this but it is not working. How can I do this?
var steps =30;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 1.5 * Math.PI;
var endAngle = 1.4999 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 15;
context.strokeStyle = 'black';
context.stroke();
setTimeout(function(){
endAngle = endAngle - 1;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.stroke();
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="250" height="250"></canvas>
new answer
Whenever you draw something on the canvas it doesn't erase what was previously drawn on it. You have to do that manually like this:
context.fillStyle="#ffffff";
context.fillRect(0,0,250,250);
//draw here
full solution:
<html>
<body>
<canvas id="myCanvas" width="250" height="250"></canvas>
<script language=javascript>
var steps =30;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 1.5 * Math.PI;
var endAngle = 1.49 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 15;
context.strokeStyle = 'black';
context.stroke();
setInterval(function(){
context.fillStyle="#ffffff";
context.fillRect(0,0,250,250);
endAngle = endAngle - 0.01;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.stroke();
}, 10);
</script>
</body>
</html>
old answer
Well there are a few things. You've got your clockwise and counterclockwise mixed up causing the circle to be completely full before your "animation" starts.
if you want it clockwise then put the end angle ahead like this:
var startAngle = 1.5 * Math.PI;
var endAngle = 1.51 * Math.PI;
And then increase the angle in your animation timeout instead of decrease:
endAngle = endAngle+1;
and finally, your timeout should be an interval, not a timeout. The timeout will only run once. simple as changing it to
setInterval(function(){...
You also don't need jquery for this code by the way.

fill ouline of arc in html5 canvas

I want to draw a shape like this using html5 canvas
but I don't want to use curves.
is there any way to draw it using arc function ?
or at least how can I draw a curve exactly like when I have given center point and radius for an arc function.
Thanks a million .
This should help, try this:
<canvas id="myCanvas" width="200" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 0 * Math.PI;
var endAngle = 1 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineTo(x - radius, 200);
context.lineTo(x + radius, 200);
context.closePath();
context.stroke();
context.fillStyle = 'red';
context.fill();
</script>

canvas hole in html5 with image not working

I am trying to create a hole in canvas; and loading image in canvas after.
I want this canvas to contain a hole at a top layer.
I just read about counter-clockwise canvas rules and then created hole with counter clockwise position as below-
var c = document.getElementById("canvas-front");
var ctx = c.getContext("2d");
var centerX = c.width / 2;
var centerY = c.offsetTop;
var radius = 30;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI,true);//boolean true to counter-clockwise
ctx.fillStyle = 'black';
ctx.fill();
I have canvas before image in it-
After applying image in this canvas-
Canvas-
<canvas id="canvas-front" width="261" height="506"></canvas>
As you can see from both the images, I can't get this hole in canvas work.
How do I create this arc so that image doesn't overlap this.
I get this issue solved-
What I had to do-
On change of file I did empty to canvas and redrew image and then while image is being loaded
the arc is being created to counter-clockwise position-
Drawing the canvas again on image change-
var canvas = document.getElementById("canvas-front");
canvas.width = canvas.width;//blanks the canvas
var c = canvas.getContext("2d");
Creating image and giving it required src from changed input-
var img = new Image();
img.src = e.target.result;
Loading image and creating arc parallely-
img.onload = function () {
c.drawImage(img, 0, 0);
var centerX = canvas.width / 2;
var centerY = canvas.offsetTop;
var radius = 30;
c.beginPath();
c.arc(centerX, centerY, radius, 0, 2 * Math.PI, true);
c.fillStyle = 'black';
c.fill();
}

Adding alert to canvas faces

I'm currently trying to make so that when you click on one of the happy face you get an alert box which says "thanks for the feed back", but I'm currently not sure to to incoperate that in tho my code! Thanks! Here is the fiddle http://jsfiddle.net/bsjs9/
<html lang="en">
<head>
<meta charset="utf-8" />
<title>SmileMore</title>
</head>
<body>
<h1>
Bring your Charts to life with HTML5 Canvas</h1>
</hgroup>
<p>
Rendering Dynamic charts in JS
</p>
<div class="smile">
<canvas id="myDrawing" width="200" height="200" style="border:1px solid #EEE"></canvas>
<canvas id="canvas" width="200" height="200" style="border:1px solid #EEE"></canvas>
</div>
<script>
var FacePainter = function(canvasName)
{
var canvas = document.getElementById(canvasName);
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 0;
var endAngle = 2 * Math.PI;
function drawFace() {
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.stroke();
ctx.fillStyle = "yellow";
ctx.fill();
}
function drawSmile(startAngle, endAngle)
{
var x = canvas.width / 2;
var y = 150;
var radius = 40;
ctx.beginPath();
ctx.arc(x, y, radius, startAngle * Math.PI, endAngle * Math.PI);
ctx.lineWidth = 7;
// line color
ctx.strokeStyle = 'black';
ctx.stroke();
}
function drawEyes() {
var centerX = 40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
//left eye
var centerX = -40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
}
this.drawHappyFace = function() {
drawFace();
drawEyes();
drawSmile(1.1, 1.9);
}
this.drawSadFace = function() {
drawFace();
drawEyes();
drawSmile(1.9, 1.1);
;
}
}
new FacePainter('canvas').drawHappyFace();
new FacePainter('myDrawing').drawSadFace();
</script>
</body>
</html>
</body>
</html>
As an extra assignment I would like to know if anyone knows how to fix the "happy" smile, its kinda way off! Thanks all!
Since you draw the happy face on its own canvas, you can simple put an onclick handler on the canvas.
<canvas id="myDrawing" width="200" height="200" style="border:1px solid #EEE" onclick="alert('thanks');"></canvas>
Regarding the smiles, I added a new ofsy parameter to drawSmile, which offsets the arc origin vertically.
Here is the updated fiddle.
If you only want to show the alert, when the user clicks inside the face, you need to get the click coordinates and hittest it against the circle. You can see this in this fiddle.

building a color wheel in html5

I am just learning some details about html5 canvas, and in the progress, I am trying to build a simple color wheel by wedges (build a 1 degree wedge at a time and add it up to 360 degree). However, I am getting some weird marks on the gradient as shown in the following image:
.
Here is the fiddle that produced the colorwheel: http://jsfiddle.net/53JBM/
In particular, this is the JS code:
var canvas = document.getElementById("picker");
var context = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 100;
var counterClockwise = false;
for(var angle=0; angle<=360; angle+=1){
var startAngle = (angle-1)*Math.PI/180;
var endAngle = angle * Math.PI/180;
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.closePath();
context.fillStyle = 'hsl('+angle+', 100%, 50%)';
context.fill();
}
If anyone can point out what I am doing wrong or if there is a better way to accomplish what I am attempting to do it would be much appreciated :)
Is this enough to you, please check
var startAngle = (angle-2)*Math.PI/180;
Try this it looks great.
Thanks by the way this is exactly what I was trying to make.
var canvas = document.getElementById("picker");
var context = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 100;
var counterClockwise = false;
for(var angle=0; angle<=360; angle+=1){
var startAngle = (angle-2)*Math.PI/180;
var endAngle = angle * Math.PI/180;
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.closePath();
var gradient = context.createRadialGradient(x, y, 0, x, y, radius);
gradient.addColorStop(0,'hsl('+angle+', 10%, 100%)');
gradient.addColorStop(1,'hsl('+angle+', 100%, 50%)');
context.fillStyle = gradient;
context.fill();
}
<body>
<canvas id="picker"></canvas>
</body>
Similar approach, just for the color
var canvas = document.getElementById("picker");
var context = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 50;
var thickness = 0.6;
for(var angle=0; angle<=360; angle+=1){
var startAngle = (angle-2)*Math.PI/180;
var endAngle = angle * Math.PI/180;
context.beginPath();
context.arc(x, y, (1-thickness/2)*radius, startAngle, endAngle, false);
context.lineWidth = thickness*radius;
context.strokeStyle = 'hsl('+angle+', 100%, 50%)';
context.stroke();
}
<body>
<canvas id="picker"></canvas>
</body>
Edit: full project here: https://github.com/dersimn/jquery-colorwheel

Categories

Resources