I wrote this algorithm to draw a regular polygon:
var sides = 6,
radius = 50;
ctx.beginPath();
ctx.moveTo(x, y - radius);
for(n = 1; n <= sides; n++)
ctx.lineTo(
x + (radius * Math.sin(n * 2 * Math.PI / sides)),
y + (-1 * radius * Math.cos(n * 2 * Math.PI / sides))
);
ctx.stroke();
It works wonderfully, but I need to incorporate a way to rotate the polygon, without using the ctx.rotate() function.
Thanks for your help. If you down vote, please tell me why so I can improve this question.
Here's code to generate a regular polygon with the first vertex at zero-angle-right-of-center:
The code uses trigonometry to rotate the polygon instead of context.rotate.
function regularPolygon(cx,cy,sides,radius,radianRotation){
var deltaAngle=Math.PI*2/sides;
var x=function(rAngle){return(cx+radius*Math.cos(rAngle-radianRotation));}
var y=function(rAngle){return(cy+radius*Math.sin(rAngle-radianRotation));}
ctx.beginPath();
ctx.moveTo(x(0),y(0));
for(n = 1; n <= sides; n++){
var angle=deltaAngle*n;
ctx.lineTo(x(angle),y(angle));
}
ctx.closePath();
ctx.stroke();
}
Related
//draw method
draw() {
//draw the ball
ctx.beginPath();
ctx.arc(this.xPos, this.yPos, this.radius, 0, 2 * Math.PI), false;
ctx.moveTo(this.xPos, this.yPos);
var i;
//use a for loop
for (i = 1; i < 8; i++) {
var x = this.radius * Math.cos(i * 2 / 7 * Math.PI) + this.xPos;
var y = this.radius * Math.sin(i * 2 / 7 * Math.PI) + this.yPos;
ctx.lineTo(x, y);
ctx.moveTo(this.xPos, this.yPos);
}
ctx.lineTo(this.xPos, this.yPos);
ctx.fillStyle = "rgba(125, 125, 125, 1)";
ctx.strokeStyle = "red";
ctx.fill();
ctx.stroke();
}
I'm completely new to graphics programming, and I am wondering how I could use a rotate method to shift all the lines in the circle (created by the draw method) by a fixed amount of radians as it moves
here is an image of the output:
There are more efficient ways to go about this, but they would require things like webgl or webgpu so just to get what you want going:
This is the 2D rotation matrix:
Add a theta parameter to your draw method and outside of the draw parameter increment it by a small amount like 0.001 on each iteration of a loop (remember to clear your canvas before drawing).
Then inside of your method, calculate the center C of your circle. The formula to rotate ANY shape round its centroid C'is:
R(theta) * (S - C) + C
Where S is the set of all points in your shape and R(theta) is the rotation matrix evaluated at theta.
In other words, for every pair of (x, y) coordinates in the cartwheel, you first subtract the center, then you multiply the resulting vector <x, y> by the rotation matrix FROM THE LEFT (R * V), the final vector <x', y'> represents the rotated shape.
I created this codepen to show what I got.
I managed to generate a hexagon avatar with progressbar around it using the awesome open source Hexagon Progress jQuery Plugin from Max Lawrence.
He also helped me to improve his own code a little but I don't want to bother him again.
Maybe someone here can help me to round the corners of this hexagon.
I want it to looks something like this (from the awesome Vikinger Html template) but need to be open source because my software is all open source. I can't use the Vikinger code.
So far I read that I have to stop the line before the end and add a quadratic curve to the next line start but I could not managed to do that.
His code do something like this on line 505:
ctx.moveTo(this.coordBack[0].x + offset, this.coordBack[0].y + offset);
for(var i = 0; i < this.coordBack.length; i++) {
ctx.lineTo(this.coordBack[i].x + offset, this.coordBack[i].y + offset);
}
Unfortunatelly, I am not that good in javascript or math.
Two ways to do this. The easy way, and the long winded, lots of math way.
Easy rounded corners
To create simple rounded polygons you can use ctx.arcTo. It will do all the math for the corners.
To create the polygon the following functions create a point and a path (array of points)
const Point = (x,y) => ({x, y});
function polygon(sides, rad, rot = 0) {
var i = 0, step = Math.PI * 2 / sides, path = [];
while (i < sides) {
path.push(Point(Math.cos(i * step + rot) * rad, Math.sin((i++) * step + rot) * rad));
}
return path;
}
To create a hexagon. Note that the polygon is centered over its local origin 0,0
const hexagon = polygon(6, 100);
To render the rounded polygon you need to work from the line segment centers. The following function will stroke the path with the rounded corners.
function strokeRoundedPath(cx, cy, path, radius, style, width) {
ctx.setTransform(1,0,0,1,cx,cy);
var i = 0;
const len = path.length
var p1 = path[i++], p2 = path[i];
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.strokeStyle = style;
ctx.beginPath();
ctx.lineTo((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
while (i <= len) {
p1 = p2;
p2 = path[(++i) % len];
ctx.arcTo(p1.x, p1.y, (p1.x + p2.x) / 2, (p1.y + p2.y) / 2, radius);
}
ctx.closePath();
ctx.stroke();
ctx.setTransform(1,0,0,1,0,0);
}
strokeRoundedPath(200, 200, hexagon, 20, "#000", 18);
Progress bar
Creating a progress bar is not as simple as the starting point can not be on a rounded corner, and moving over the rounded corners will need a lot of math to get the correct coordinates. This will negate the point of using easy arcToand need us to write the equivalent in JS (Way to slack for that today)
Using line dash for progress
There is however a hack that uses the line dash to create the effect you may be happy with. The snippet demonstrates this
const barWidth = 10;
const cornerRadius = barWidth * 2 + 8;
const polyRadius = 100;
const inset = 1;
const barRadius = polyRadius - barWidth * inset;
var progress = 0.0;
const approxLineLen = barRadius * Math.PI * 2;
const hexBar = polygon(6, barRadius);
const hexPoly = polygon(6, polyRadius);
const hexPolyInner = polygon(6, polyRadius - barWidth * 2 * inset);
const ctx = canvas.getContext("2d");
ctx.setLineDash([approxLineLen]);
loop()
function point(x,y) { return {x, y} }
function polygon(sides, radius, rot = 0) {
var i = 0;
const step = Math.PI * 2 / sides, path = [];
while (i < sides) {
path.push(point(Math.cos(i * step + rot) * radius, Math.sin((i++) * step + rot) * radius));
}
return path;
}
function roundedPath(path, radius) {
var i = 0, p1 = path[i++], p2 = path[i];
const len = path.length
ctx.moveTo((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
while (i <= len) {
p1 = p2;
p2 = path[(++i) % len];
ctx.arcTo(p1.x, p1.y, (p1.x + p2.x) / 2, (p1.y + p2.y) / 2, radius);
}
}
function strokeRoundedPath(cx, cy, path, radius, style, width) {
ctx.setTransform(1,0,0,1,cx,cy);
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.strokeStyle = style;
ctx.beginPath();
roundedPath(path, radius);
ctx.closePath();
ctx.stroke();
}
function fillRoundedPath(cx, cy, path, radius, style) {
ctx.setTransform(1,0,0,1,cx,cy);
ctx.fillStyle = style;
ctx.beginPath();
roundedPath(path, radius);
ctx.fill();
}
function loop() {
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,canvas.width,canvas.height);
fillRoundedPath(polyRadius, polyRadius, hexPoly, cornerRadius, "#000");
fillRoundedPath(polyRadius, polyRadius, hexPolyInner, cornerRadius - barWidth * inset * 2, "#F80");
ctx.lineDashOffset = approxLineLen - (progress % 1) * approxLineLen;
strokeRoundedPath(polyRadius, polyRadius, hexBar, cornerRadius - barWidth * inset, "#09C", barWidth);
progress += 0.005;
requestAnimationFrame(loop);
}
<canvas id="canvas" width = "210" height="210"></canvas>
I created some Functions, these will draw Rectangles, Circles, Hexagons etc.
One of them looks like this:
rotation = 45;
function hex(hex_sides, hex_size, hex_color){
x = ctx.canvas.width/2;
y = ctx.canvas.height/2;
ctx.save();
ctx.rotate(rotation*Math.PI/180);
ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
ctx.moveTo(x + hex_size * Math.cos(0), y + hex_size * Math.sin(0));
ctx.restore();
for (i = 0; i < hex_sides+1; i++) {
ctx.lineTo(x + hex_size * Math.cos(i * 2 * Math.PI / hex_sides), y + hex_size * Math.sin(i * 2 * Math.PI / hex_sides));
}
ctx.strokeStyle = hex_color;
ctx.stroke();
}
Now i call the Functions to Draw the Shapes inside my animation loop.
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
circle(200);
circle(220);
hex(6, 180, "#fff");
rotation += 0.4;
requestAnimationFrame(loop);
}
I'm incrementing the var rotation inside the loop but it does not rotate the whole shape but just one line of it instead. Other Shapes i cant get to rotate at all.
I think i got a wrong approach, maybe because of my confusion about .save() and .restore() or .beginPath() and .closePath().
In General the behaviour is very strange when i start to use .translate() and .rotate()
The entire Code is here.
UPDATE
It is definitely something about this line:
ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
Somehow it does not translate correctly. The rotation now happens almost around the middle but i want the Object to rotate around its own axis.
I changed the hex() function to:
ctx.save();
ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
ctx.rotate(rotation*Math.PI/180);
ctx.moveTo(x + hex_size * Math.cos(0), y + hex_size * Math.sin(0));
for (i = 0; i < hex_sides+1; i++) {
ctx.lineTo(x + hex_size * Math.cos(i * 2 * Math.PI / hex_sides), y + hex_size * Math.sin(i * 2 * Math.PI / hex_sides));
}
ctx.strokeStyle = hex_color;
ctx.stroke();
ctx.restore();
I think it's usual question, but I have some problems with displaying dots in canvas. The first thing I'd like to know is how to draw dot like this (please zoom it).
The second thing is, how to draw a shadow to each element of the grid of this dots, with the light source in the center.
What I have at this moment right here:
the part of my code:
context.fillStyle = "#ccc";
context.shadowColor = '#e92772';
context.shadowOffsetX = 15;
context.shadowOffsetY = 15;
while (--e >= 1) {
x -= z;
if(x < 0) {
x = z*w;
y -= z;
}
context.moveTo(x, y);
context.fillRect( x, y, 1, 1 );
outs = a[e];
}
Also, I've tried to use "context.arc();", but I think "context.fillRect();" is more easier. And one else moment, when I use "while (--e >= 0)" instead of "while (--e >= 1)" I have two more dots, on the top. Why?
If you know some articles or tutorials, would you give me the link to them. Preferably without the use of the frameworks. Thanks.
You can use some trigonometry to simulate 3D dots with a light source.
HERE IS AN ONLINE DEMO
This is one way you can do it, there are of course others (this was the first that came to mind):
Draw the grid with some dots on the main canvas
Render a radial gradient to an off-screen canvas
Change composition mode so anything is draw on already existing pixels
Calculate distance and angle to light source and draw the dot to each grid point offset with the angle/dist.
Here is some code from the demo that does this.
Draw the grid with dots
We skip one grid point as we will fill each dot later with the gradient dot which otherwise would paint over the neighbor dot.
/// draw a grid of dots:
for (y = 0; y < ez.width; y += gridSize * 2) {
for (x = 0; x < ez.height; x += gridSize * 2) {
ctx.beginPath();
ctx.arc(x + offset, y + offset, radius, 0, arcStop);
ctx.closePath();
ctx.fill();
}
}
Create a light "reflection"
Prepare the gradient dot to an off-screen canvas (dctx = dot-context). I am using easyCanvas for the setup and to give me an off-screen canvas with center point already calculated, but one can setup this manually too of course:
grd = dctx.createRadialGradient(dot.centerX, dot.centerY, 0,
dot.centerX, dot.centerY, gridSize);
grd.addColorStop(0, '#fff');
grd.addColorStop(0.2, '#777'); // thighten up
grd.addColorStop(1, '#000');
dctx.fillStyle = grd;
dctx.fillRect(0, 0, gridSize, gridSize);
Do the math
Then we do all the calculation and offsetting:
/// change composition mode
ctx.globalCompositeOperation = 'source-atop';
/// calc angle and distance to light source and draw each
/// dot gradient offset in relation to this
for (y = 0; y < ez.width; y += gridSize) {
for (x = 0; x < ez.height; x += gridSize) {
/// angle
angle = Math.atan2(lightY - y, lightX - x);
//if (angle < 0) angle += 2;
/// distance
dx = lightX - x;
dy = lightY - y;
dist = Math.sqrt(dx * dx + dy * dy);
/// map distance to our max offset
od = dist / maxLength * maxOffset * 2;
if (od > maxOffset * 2) od = maxOffset * 2;
/// now get new x and y position based on angle and offset
offsetX = x + od * Math.cos(angle) - maxOffset * 0.5;
offsetY = y + od * Math.sin(angle) - maxOffset * 0.5;
/// draw the gradient dot at offset
ctx.drawImage(dot.canvas, x + offsetX, y + offsetY);
}
}
Shadow
For the shadow you just inverse the offset while using the composition mode destination-over which will draw outside the already drawn pixels:
/// Shadow, same as offsetting light, but in opposite
/// direction and with a different composite mode
ctx.globalCompositeOperation = 'destination-over';
for (y = 0; y < ez.width; y += gridSize) {
for (x = 0; x < ez.height; x += gridSize) {
/// angle
angle = Math.atan2(lightY - y, lightX - x);
//if (angle < 0) angle += 2;
/// distance
dx = lightX - x;
dy = lightY - y;
dist = Math.sqrt(dx * dx + dy * dy);
/// map distance to our max offset
od = dist / maxLength * maxOffset * 2;
if (od > maxOffset * 4) od = maxOffset * 4;
/// now get new x and y position based on angle and offset
offsetX = x - od * Math.cos(angle) + gridSize * 0.5;
offsetY = y - od * Math.sin(angle) + gridSize * 0.5;
ctx.beginPath();
ctx.arc(x + offsetX, y + offsetY, radius, 0, arcStop);
ctx.fill();
}
}
This can all be optimized of-course into a single loop pair but for overview the code is separated.
Additional
In the demo I added mouse tracking so the mouse becomes the light-source and you can see the dot-reflection changes while you move the mouse. For best performance use Chrome.
To match your need just scale down the values I am using - or - draw to a big off-screen canvas and use drawImage to scale it down to a main canvas.
while searching that How can I made a moving circle using php, I found this question.But as I am not much expert in php so most of the things were not being understandable by me.So I thought now I must consult the experts :)
I want to Draw a circle which will move in circular motion on my php page.
MY EFFORT : I have tried alot to figure this out but the only thing I found that It would be achieved by canvas HTML5.But I got stuck in cartesian , radius etc.These things are really confusing me.
Anhy suggestions please.
The mathematics behind is:
x = centerX + radius * Math.cos(angle * Math.PI / 180);
y = centerY + radius * Math.sin(angle * Math.PI / 180);
Now you can input the result to a div element which contains the ball:
var element = document.getElementById('ball');
var angle = 0;
var x = 0;
var y = 0;
var w = (window.innerWidth - 50) / 2;
var h = (window.innerHeight - 50) / 2;
function ballCircle() {
x = w + w * Math.cos(angle * Math.PI / 180);
y = h + h * Math.sin(angle * Math.PI / 180);
ball.style.left = x + 'px';
ball.style.top = y + 'px';
angle++;
if (angle > 360) {
angle = 0;
}
setTimeout(ballCircle,20);
}
ballCircle();
I made a demo on jsfiddle here: http://jsfiddle.net/AqKYC/
PHP is a server-side programming language. It sounds like what you want to do is animate a circle in the browser. PHP does not run in the browser, so you cannot use PHP to animate a circle.
You can, however, create a <canvas> and use JavaScript to animate it. Here is a MDN tutorial on canvas, including animations.
As an alternative to canvas, you could use a simple <div>, turn it into a circle with CSS border-radius: 50%, and then animate it with either pure JavaScript, or jQuery.
Here's a jsfiddle with the circle drawn and using jQuery.animate to move it right, left, and right again.
jQuery.animate is fully documented here.
Here is a sample for a html5 moving circle with a tutorial explaining the code and how it's done. The code is under gplv3 license so obviously free too.
https://www.youtube.com/watch?v=6j4Y14TEO6s
Snippet in focus
ctx.strokeStyle = 'rgb(255,0,0)';
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.stroke();
Another sample is as follows where it shows the animated perspective of the same if that's what you are looking for.
https://www.youtube.com/watch?v=eKDeKFFZDNo
The focus is to break the animation at some point and thus the below snippet in focus in the redraw section of the code.
if (!ctx.isPointInPath(300,500)) {
x = x + 1;
y = y + 2;
ctx.strokeStyle = colorToHex(getRandom(255),getRandom(255),getRandom(255));
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.stroke();
}