This is my jsfiddle:
http://jsfiddle.net/c4upM/103/
I have the gray arc and the blue/green arc.
I am trying to make them more Elliptic, like:
and I didn't succeed.
I read this one: http://jsbin.com/ovuret/2/edit and tried to make it on my jsfiddle but I didn't succeed because the arc-s are painted in the function of: DrawCircle and DrawEllipseForProjection.
There are two functions: blueArc and grayarc. by the radian angle, there is a calculation in function circleInArc that places the small lightblue circle and the small gray circle (when you mouse over the canvas) in the arc-s.
I want these functions to work after the change but I didn't succeed.
these are the blue and gray arc-s:
function grayArc(strokeColor, cx, cy, radius, ctx, linewidth) {
ctx.beginPath();
ctx.arc(cx, cy, radius, Math.PI, Math.PI * 2);
ctx.lineWidth = linewidth;
ctx.strokeStyle = strokeColor;
ctx.stroke();
}
function blueArc(strokeColor, radianStart, radianEnd, cx, cy, radius, ctx, linewidth) {
ctx.beginPath();
ctx.arc(cx, cy, radius, radianStart, radianEnd);
ctx.lineWidth = linewidth;
ctx.strokeStyle = strokeColor;
ctx.stroke();
}
and this is the circleInArc function:
function circleInArc(fillColor, radianAngle, cx, cy, radius, ctx, linewidth) {
var x = cx + radius * Math.cos(radianAngle);
var y = cy + radius * Math.sin(radianAngle);
ctx.beginPath();
ctx.arc(x, y, linewidth / 2, 0, Math.PI * 2);
ctx.closePath();
ctx.fillStyle = fillColor;
ctx.fill();
return ({
x: x,
y: y,
radius: linewidth / 2
});
}
Any help appreciated!
You can try draw arc with bigger radius and not from Math.PI to 2*Math.PI but this one
ctx.arc(cx, cy, radius, Math.PI*5/4, Math.PI * 7/4);
and don't forget move the arc down for radius size
grayArc("rgb(177,177,177)", cx, cy+radius, radius*2, ctx, linewidth);
hope it will help
I've fiddled around a bit, and you'll propably have to adjust some of the values, but here's an example: Fiddle (Only the gray arc was adjusted)
The basic strategy is to save the state of the context, then scale it to your liking. If you only scale one axis.. voilá, ellipsis.
Also, I translated the origin of the canvas to the center of the arc before scaling, because they get scewed with the scaling. The center of the arc is then 0, 0.
After that the context can be restored like nothing ever happened, an you can stroke your transformed arc.
ctx.save();
ctx.translate(cx,cy);
ctx.scale(1.3, 1);
ctx.arc(0, 0, radius, 1.2*Math.PI, 1.8*Math.PI);
ctx.restore();
You'll propably want to play around with the radius, the ratio of scaling and maybe the range in which the arc gets drawn to fit your needs.
Edit: I cut down on the range of the arc which gets drawn, to prevent the stubby ends of the ellipsis showing. From 1.2*PI to 1.8*PI instead of 1*PI to 2*PI seems to look alright in the current case. :)
For future questions, please try to extract the a more basic example of your problem, to make it easier for those who want to help out. :)
Related
I am very new to the canvas so I have very little idea how it works.
This is the code for the circle that I have drawn in the middle of the screen.
ctx.save();
ctx.beginPath();
ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, 2 * Math.PI);
ctx.strokeStyle = "#2465D3";
ctx.stroke();
ctx.clip();
ctx.drawImage(imageFile, 200, 200, 500, 500);
ctx.restore();
ctx.stroke();
I want to show a picture inside of the circle.
The picture shows up in the circle in the wrong position with this code. I want the picture to be in the center of the circle like:
According to the syntax of drawImage(), I need dx and dy in this ctx.drawImage(image, dx, dy, dWidth, dHeight) to position the image correctly on the canvas (at the center of the circle).
Is there anything I can do to put the picture in the center of the circle without doing all sorts of
Pythagoras calculations?
Why I am doing it this way?
I cannot find one good coordinate for the picture and move on because the radius of the circle is not constant so that would not work. I would need to find the appropriate coordinate for the picture every time the radius of the circle changes to keep the picture in the middle of the circle.
My thought process was to find the corner coordinate of the square that the circle would make like in this picture
then to measure the distance between that point and the width of the canvas.
I think there must be a better way to do this. Is there a better way to do this? I am using this in a React App.
Your imagem must have the x and y position equals circle. The height and width imagem must have 2r.
x = canvas.width / 2;
y = canvas.height / 2
ctx.save();
ctx.beginPath();
ctx.arc(x,y, radius, 0, 2 * Math.PI);
ctx.strokeStyle = "#2465D3";
ctx.stroke();
ctx.clip();
ctx.drawImage(imageFile, x, y, 2 * radius, 2 * radius);
ctx.restore();
ctx.stroke();
Here canvas.width / 2 and canvas.height/ 2 are the coordinates for the center of the circle.
ctx.drawImage(
oneMoreRound,
canvas.width / 2,
canvas.height / 2,
radius * 2,
radius * 2
);
Only passing the above code puts the top left corner of the image to the center of the circle like this:
Subtracting the radius from the x and y coordinates puts that top left corner of the image in the top left corner of the square that the circle will create. That would put the image in the right position if the image is a square.
This is the solution
ctx.drawImage(
oneMoreRound,
canvas.width / 2 - radius,
canvas.height / 2 - radius,
radius * 2,
radius * 2
);
Sometimes you wish you could go back in time to tell your younger self that maths are indeed important! But I doubt I would've listened back then. I've been playing with trigonometry lately for animation purposes with the HTML5 canvas in this particular example.
It's a super simple animation: It positions an arc in a circular manner around the center of the canvas. The X and Y positions are calculated based upon the basic trigonometry functions sinus and cosinus. "SohCahToa". I think I'm starting to get it. But somehow I cannot figure out how to draw a square in the middle of one of the triangular sides.
let radius = 200;
let angle = 0;
x = centerX + Math.cos(angle) * radius;
ctx.beginPath();
ctx.fillRect(x/2, centerY, 20, 20);
https://codepen.io/melvinidema/pen/wvKPepa?editors=1010
So the arc is drawn by adding up the center of the canvas with the
rework formulas: (co)sinus - for X = Cos, for Y = Sin) of the angle times the radius of the circle.
If we only take the X position (red line) and want to draw the square half of the position of the arc. ( So in the middle of the red line ) we should just be able to divide the freshly calculated X position by two right? But if I do that, the square is magically drawn completely outside the circle.
What's happening? Why does it behave like this? And what calculation should I use instead for the square to position in the middle of the red line throughout the animation?
Thanks in advance!
Your x defined as:
x = centerX + Math.cos(angle) * radius;
but when you want to divide by 2, you just need to divide the Math.cos(angle) * radius, while the centerX is the zero point, and its stand as it is.
So the rect should be placed at:
centerX + Math.cos(angle)/2
Also, I think will be better if you reduce half of the rect width, and get:
centerX + Math.cos(angle)/2 - 10
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
let radius = 200;
function frame(angle) {
const cx = canvas.width / 2,
cy = canvas.height / 2,
x = Math.cos(angle) * radius,
y = Math.sin(angle) * radius;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(cx+x, cy+y);
ctx.lineTo(cx+x, cy);
ctx.lineTo(cx, cy);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(cx+x, cy+y, 10, 0, Math.PI*2);
ctx.fill();
ctx.fillRect(cx + x/2 - 10, cy - 10, 20, 20);
ctx.closePath();
requestAnimationFrame(()=>frame(angle+.03));
}
frame(0)
canvas {
display: block;
max-height: 100vh;
margin: auto;
}
<canvas width="500" height="500"></canvas>
This question already has an answer here:
All html canvas shapes are given the color of the last object added
(1 answer)
Closed 2 years ago.
I am drawing a filled ellipse (using arc()) on the javascript canvas:
ctx.arc(centerX, centerY, dotDiameter / 2, 0, 2 * Math.PI, false);
ctx.fillStyle = color1;
ctx.fill();
I then want to draw a line, that is clipped to this ellipse, in a different color.
ctx.clip(); // Clip to the ellipse
ctx.strokeStyle = color2;
ctx.moveTo(centerX - dotRadius, centerY);
ctx.lineTo(centerX + dotRadius, centerY);
ctx.stroke();
However, the ellipse is also stroked with color2.
How can I clip lines to my ellipse, but not have the ellipse stroked? Is there a way to remove the ellipse (aka arc) from the canvas after I call clip()?
Thanks!
(FYI, this is an oversimplification of my code. The lines that stroked are more complicated than a single horizontal line and the lines do need to be clipped.)
We can calculate a point on the perimeter of an ellipsis with some basic trigonometry...
ctx.moveTo(x, y);
x += radiusX * Math.cos(lineangle)
y += radiusY * Math.sin(lineangle)
ctx.lineTo(x, y);
See code snippet below, I'm drawing an ellipse and a line from center to edge.
ctx = document.getElementById('c').getContext('2d');
ctx.lineWidth = 2;
function draw(x, y, radiusX, radiusY, lineangle, color1, color2) {
ctx.beginPath()
ctx.ellipse(x, y, radiusX, radiusY, 0, 0, 2 * Math.PI, false);
ctx.fillStyle = color1;
ctx.fill();
ctx.beginPath()
ctx.strokeStyle = color2;
ctx.moveTo(x, y);
x += radiusX * Math.cos(lineangle)
y += radiusY * Math.sin(lineangle)
ctx.lineTo(x, y);
ctx.stroke();
}
angle = 0
function loop() {
ctx.clearRect(0,0, 500, 500);
draw(80, 80, 70, 50, angle, "red", "lime")
draw(240, 60, 80, 30, angle*0.7, "black", "cyan")
draw(360, 80, 30, 70, angle*2, "white", "black")
angle += 0.05
}
setInterval(loop, 100)
<canvas height="160" width="500" id="c">
I'm trying to solve an odd artifact that is occurring in my HTML5 Canvas animation. I'm trying to surround the text with lines that follow each other. When I get to clearing the third line, there is a line still there as if clearRect() didn't work correctly.
I've already googled and my draw functions do indeed use beginPath() and closePath() respectively, so you can imagine my frustration when this thing doesn't clear.
I'm hoping someone can help me see where I've gone wrong with this animation.
Here's an example of the draw code (because stack overflow is forcing me to put code in here if I link to JSFiddle)
function drawArc(xPos, yPos,
radius,
startAngle, endAngle,
anticlockwise,
lineColor, fillColor) {
var startAngle = startAngle * (Math.PI / 180);
var endAngle = endAngle * (Math.PI / 180);
var radius = radius;
context.strokeStyle = lineColor;
context.fillStyle = fillColor;
context.lineWidth = 1;
context.beginPath();
context.arc(xPos, yPos,
radius,
startAngle, endAngle,
anticlockwise);
context.fill();
context.closePath();
}
function drawLine(xStartPos, yStartPos, xEndPos, yEndPos, width, color) {
context.stokeStyle = color;
context.lineWidth = width;
context.beginPath();
context.moveTo(xStartPos, yStartPos);
context.lineTo(xEndPos, yEndPos);
context.stroke();
context.closePath();
}
JSFiddle: https://jsfiddle.net/xtkbnxx5/9/
With this version, it looks like the animation is stopping in the wrong place. However, If you comment out line 126 in the javascript and run it again, you will see that the line is just there and never gets cleared...
Any help would be greatly appreciated.
Your context.clearRect(...) statements are not clearing the entire canvas.
When I change you clearRect statements to
context.clearRect(0,0, canvas.width, canvas.height);
Then the second line eventually disappears.
https://jsfiddle.net/xtkbnxx5/10/
I wanted to draw some circles on the canvas with the following layout: A circle right in the centre of the canvas and four circles at the mid points of the four edges of the canvas. I've put up my code here jsfiddle. The circles are rendered, however there are multiple filled paths between them too, resulting in an amalgamated mess.
I'm drawing all the circles by using
ctx.arc(points[i].x, points[i].y, radius, 0, 2 * Math.PI, true);
How do I remove them ?
EDIT: working jsfiddle
Put closePath after each circular-arc so that the circles are not connected:
ctx.arc(points[i].x, points[i].y, radius, 0, 2 * Math.PI, true);
ctx.closePath();
You are probably wanting to fill after each arc.
Something like this should work
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, true);
ctx.fill();
for(var i = 0; i < points.length; i++){
var _ = points[i];
ctx.beginPath();
ctx.arc(_.x, _.y, 25, 0, 2 * Math.PI, true);
ctx.fill();
}