Getting a shape to draw on the html5 canvas - javascript

I have a function that basically uses lines to draw a psuedo circle of a specific size and fills it in a colour.
However when I try to call my method, it does not draw and I found no errors on the debug console (I'm using chrome) and jsfiddle threw up no errors for me.
Here is the code:
function drawLineCircle (x, y, size, colour, scale, segments) {
context.save();
context.strokestyle = '#000000';
context.fillStyle = colour;
context.lineWidth = 3;
context.beginPath();
var anglePerSegment = Math.PI *2 / segments;
for (var i = 0; i <= segments; i = i + 1){
var angle = anglePerSegment * i;
var radius = size * scale;
var a = x + radius * cos (angle);
var b = y + radius * sin (angle);
if (i == 0)
context.moveTo (a, b);
else
context.lineTo (a, b);
}
context.stroke();
context.fill();
context.closePath();
context.restore();
}
Any help would be greatly appreciated!

There are a couple of problems with your code:
You are not defining context
cos and sin are properties of Math
Here is a corrected example: http://jsfiddle.net/REw7j/1/
function drawLineCircle (x, y, size, colour, scale, segments) {
var canvas = document.getElementById('example');
var context = canvas.getContext('2d');
context.save();
context.strokestyle = '#000000';
context.fillStyle = colour;
context.lineWidth = 3;
context.beginPath();
var anglePerSegment = Math.PI *2 / segments;
for (var i = 0; i <= segments; i = i + 1){
var angle = anglePerSegment * i;
var radius = size * scale;
var a = x + radius * Math.cos (angle);
var b = y + radius * Math.sin (angle);
if (i == 0)
context.moveTo (a, b);
else
context.lineTo (a, b);
}
context.stroke();
context.fill();
context.closePath();
context.restore();
}

Related

HTML5 Canvas sub-pixel position rendering issue

I'm trying to draw multiple rectangles positioned very densely in a straight line so they form a single shape like so:
const canvas = document.getElementById("c");
const ctx = canvas.getContext("2d");
const a = 87;
const l = 300;
const col = 'rgba(0,0,64)';
const q = 4; // density - change
ctx.moveTo(300, 100);
ctx.lineTo(
300 + (Math.cos(degtorad(a)) * l),
100 + (Math.sin(degtorad(a)) * l)
);
ctx.strokeStyle = col;
ctx.lineWidth = 3;
ctx.stroke();
stack(l, a, col);
function stack(length, angle, color) {
ctx.fillStyle = color;
for (let i = 1; i < length * q; i++) {
let x = 100 + (Math.cos(degtorad(angle)) * i / q);
let y = 100 + (Math.sin(degtorad(angle)) * i / q);
console.log(`x:${x}, y:${y}`);
ctx.beginPath();
ctx.rect(x, y, 150, 100);
ctx.fill();
}
}
function degtorad(angle) {
return angle * (Math.PI / 180.0);
}
https://jsfiddle.net/fallenartist/qeo7a1gx/
However, I don't like the jagged edge at all! It looks like there are issues with canvas rendering at sub-pixel coordinates. Notice how rendering of edges of absolutely positioned rectangles differ from a straight line:
Can anyone explain why is this? And how it can be improved?

Filling the color to specific section of HTML canvas in JavaScript like Windows Paint

I am now trying to deeply understand the canvas and JavaScript. Now I am drawing an image on HTML canvas using JavaScript. I can draw the image successfully. But I am having a problem with filling the colour. This is the picture I have drawn using JavaScript and canvas.
This is the JavaScript code.
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
//circles
var center_y = 150;//Y
var center_x = 150;
var lineWidth = 10;
context.lineWidth=lineWidth;
context.beginPath();
context.arc(center_x,center_y ,50,0,2*Math.PI);
context.strokeStyle = "#FF00FF";
context.stroke();
context.beginPath();
context.arc(center_x,center_y ,40,0,2*Math.PI);
context.strokeStyle = "#990000";
context.stroke();
context.beginPath();
context.arc(center_x,center_y ,30,0,2*Math.PI);
context.strokeStyle = "#0099CC";
context.stroke();
context.lineWidth = 1;
x1 = 150;
y1 = 150;
r = 140;
theta = 0.5;
context.moveTo(x1, y1);
context.lineTo(x1 + r * Math.cos(theta), y1 + r * Math.sin(theta));
context.stroke();
theta = 1;
context.moveTo(x1, y1);
context.lineTo(x1 + r * Math.cos(theta), y1 + r * Math.sin(theta));
context.stroke();
theta = 1.5;
context.moveTo(x1, y1);
context.lineTo(x1 + r * Math.cos(theta), y1 + r * Math.sin(theta));
context.stroke();
theta = 2;
context.moveTo(x1, y1);
context.lineTo(x1 + r * Math.cos(theta), y1 + r * Math.sin(theta));
context.stroke();
theta = 2.5;
context.moveTo(x1, y1);
context.lineTo(x1 + r * Math.cos(theta), y1 + r * Math.sin(theta));
context.stroke();
theta = 3;
context.moveTo(x1, y1);
context.lineTo(x1 + r * Math.cos(theta), y1 + r * Math.sin(theta));
context.stroke();
Basically, what I am doing is drawing circles from smaller to bigger with the same center. Then draw the line from the same center increasing the degree equally after each line is drawn. Yes, the image is drawn successfully. But there is an issue with what I want to achieve. As you can see, for coloring the circle, I set the line with of circle to ten and set the color for the line. So the whole circle line has only one color. But what I would like to do is I want to set the different color for each section of the circle. I set the section by separating with the lines as follow.
So, what I want to do is, I want to set the different color to section A of circle "1" from section B of circle "1" and so on. In Microsoft Paint software, if we paint a section, if the section is bordered properly, only the bordered area section is painted. So, I would like to do something like that.
You should probably draw different arcs for the different sections by changing the last 2 parameters of the arc method:
context.arc(cx,cy ,radius, theta_start, theta_end);
I made this jsfiddle for you: https://jsfiddle.net/gtato/znxzvjnp/
If you want to set to set the different color to section A of circle "1" from section B of circle "1" and so on, you can use draw arcs next to each other. You have to calculate the angle from and to and make sure these are adjacent.
Here is a small example on how you can draw something like a piechart with random colors:
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.lineWidth = 1;
x1 = 150;
y1 = 150;
r = 150;
let prevAngle = 0;
let angle = 0;
let fraction = 0.05;
for (i = 0; i * fraction <= 1; i++) {
context.fillStyle = getRandomColor();
// Calculate new angle from previous one
angle = prevAngle + fraction * Math.PI * 2;
//create a path
context.beginPath();
context.moveTo(x1, y1);
context.arc(x1, y1, r, prevAngle, angle, false);
context.lineTo(x1, y1);
//fill it
context.fill();
// Create a stroke
context.strokeStyle = "#000000";
context.stroke();
prevAngle = angle;
}
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
<canvas width="500" height="500" id="canvas">
</canvas>

How to use RequestAnimationFrame correctly?

I made a diffuse animation and used RequestAnimationFrame to achieve it.I tried hundreds of times to improve my program.But it doesn't work!!!Where's my wrong?
function draw_point(x, y){
x += 10.5;
y += 10.5;
radius = 0;
var context = $("#canvas_graph")[0].getContext('2d');
window.webkitRequestAnimationFrame(render(x, y, radius, context));
};
function drawCircle(x, y, radius, context){
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.closePath();
context.lineWidth = 2;
context.strokeStyle = 'red';
context.stroke();
radius += 0.2;
if (radius > 10) {
radius = 0;
}
};
//The effect of diffusion is achieved by changing the attribute
function render(x ,y, radius, context){
return function step(){
var prev = context.globalCompositeOperation;
context.globalCompositeOperation = 'destination-in';
context.globalAlpha = 0.95;
context.fillRect(0, 0, 890, 890);
context.globalCompositeOperation = prev;
drawCircle(x, y, radius,context);
window.webkitRequestAnimationFrame(step);
};
};
draw_point(100, 100);
But this can be used normally.Function render through the globalAlpha attribute so that the circle is getting lighter.Newly drawn circles are getting bigger.Small rounds are becoming lighter and lighter by using the globalAlpha property again and again.
var context = $("#canvas_graph")[0].getContext('2d');
var radius = 0;
var x = 100;
var y = 100;
function drawCircle(){
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.closePath();
context.lineWidth = 2;
context.strokeStyle = 'red';
context.stroke();
radius += 0.2;
if (radius > 10) {
radius = 0;
}
};
function render(){
var prev = context.globalCompositeOperation;
context.globalCompositeOperation = 'destination-in';
context.globalAlpha = 0.95;
context.fillRect(0, 0, 890, 890);
context.globalCompositeOperation = prev;
drawCircle();
window.webkitRequestAnimationFrame(render);
};
window.webkitRequestAnimationFrame(render);
In addition,when canvas animation move up, how to restore the background?
Adjust your draw_point function like so. What you have currently is executing the render function right away, you want to pass a reference to requestAnimationFrame, not inserting a function call there
function draw_point(x, y){
x += 10.5;
y += 10.5;
radius = 0;
var context = $("#canvas_graph")[0].getContext('2d');
window.webkitRequestAnimationFrame(function() {
render(x, y, radius, context));
}
};

Canvas line drawing animation

I am new learner of animation using HTML5 Canvas. I am struggling to create line drawing animation in a canvas with desired length of a line.
Here is the code
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
width = canvas.width = window.innerWidth,
height = canvas.height = window.innerHeight;
var x = 200;
var y = 200;
draw();
update();
function draw() {
context.beginPath();
context.moveTo(100, 100);
context.lineTo(x, y);
context.stroke();
}
function update() {
context.clearRect(0, 0, width, height);
x = x + 1;
y = y + 1;
draw();
requestAnimationFrame(update);
}
html,
body {
margin: 0px;
}
canvas {
display: block;
}
<canvas id="canvas"></canvas>
The line is growing on Canvas in the above code. But how to achieve that the 200px wide line and animate the movement in x and y direction. And the same animation with multiple lines using for loop and move them in different direction.
Check the reference image ....
Need to move each line in a different direction
Thanks in advance
Find a new reference image which i want to achieve
You need to either use transforms or a bit of trigonometry.
Transforms
For each frame:
Reset transforms and translate to center
Clear canvas
Draw line from center to the right
Rotate x angle
Repeat from step 2 until all lines are drawn
var ctx = c.getContext("2d");
var centerX = c.width>>1;
var centerY = c.height>>1;
var maxLength = Math.min(centerX, centerY); // use the shortest direction for demo
var currentLength = 0; // current length, for animation
var lenStep = 1; // "speed" of animation
function render() {
ctx.setTransform(1,0,0,1, centerX, centerY);
ctx.clearRect(-centerX, -centerY, c.width, c.height);
ctx.beginPath();
for(var angle = 0, step = 0.1; angle < Math.PI * 2; angle += step) {
ctx.moveTo(0, 0);
ctx.lineTo(currentLength, 0);
ctx.rotate(step);
}
ctx.stroke(); // stroke all at once
}
(function loop() {
render();
currentLength += lenStep;
if (currentLength < maxLength) requestAnimationFrame(loop);
})();
<canvas id=c></canvas>
You can use transformation different ways, but since you're learning I kept it simple in the above code.
Trigonometry
You can also calculate the line angles manually using trigonometry. Also here you can use different approaches, ie. if you want to use delta values, vectors or brute force using the math implicit.
For each frame:
Reset transforms and translate to center
Clear canvas
Calculate angle and direction for each line
Draw line
var ctx = c.getContext("2d");
var centerX = c.width>>1;
var centerY = c.height>>1;
var maxLength = Math.min(centerX, centerY); // use the shortest direction for demo
var currentLength = 0; // current length, for animation
var lenStep = 1; // "speed" of animation
ctx.setTransform(1,0,0,1, centerX, centerY);
function render() {
ctx.clearRect(-centerX, -centerY, c.width, c.height);
ctx.beginPath();
for(var angle = 0, step = 0.1; angle < Math.PI * 2; angle += step) {
ctx.moveTo(0, 0);
ctx.lineTo(currentLength * Math.cos(angle), currentLength * Math.sin(angle));
}
ctx.stroke(); // stroke all at once
}
(function loop() {
render();
currentLength += lenStep;
if (currentLength < maxLength) requestAnimationFrame(loop);
})();
<canvas id=c></canvas>
Bonus animation to play around with (using the same basis as above):
var ctx = c.getContext("2d", {alpha: false});
var centerX = c.width>>1;
var centerY = c.height>>1;
ctx.setTransform(1,0,0,1, centerX, centerY);
ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(0,0,0,0.8)";
ctx.shadowBlur = 16;
function render(time) {
ctx.globalAlpha=0.77;
ctx.fillRect(-500, -500, 1000, 1000);
ctx.globalAlpha=1;
ctx.beginPath();
ctx.rotate(0.025);
ctx.shadowColor = "hsl(" + time*0.1 + ",100%,75%)";
ctx.shadowBlur = 16;
for(var angle = 0, step = Math.PI / ((time % 200) + 50); angle < Math.PI * 2; angle += step) {
ctx.moveTo(0, 0);
var len = 150 + 150 * Math.cos(time*0.0001618*angle*Math.tan(time*0.00025)) * Math.sin(time*0.01);
ctx.lineTo(len * Math.cos(angle), len * Math.sin(angle));
}
ctx.stroke();
ctx.globalCompositeOperation = "lighter";
ctx.shadowBlur = 0;
ctx.drawImage(ctx.canvas, -centerX, -centerY);
ctx.drawImage(ctx.canvas, -centerX, -centerY);
ctx.globalCompositeOperation = "source-over";
}
function loop(time) {
render(time);
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
body {margin:0;background:#222}
<canvas id=c width=640 height=640></canvas>
Here is what I think you are describing...
window.onload = function() {
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
width = canvas.width = 400,
height = canvas.height = 220,
xcenter = 200,
ycenter = 110,
radius = 0,
radiusmax = 100,
start_angle1 = 0,
start_angle2 = 0;
function toRadians(angle) {
return angle * (Math.PI / 180);
}
function draw(x1, y1, x2, y2) {
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.stroke();
}
function drawWheel(xc, yc, start_angle, count, rad) {
var inc = 360 / count;
for (var angle = start_angle; angle < start_angle + 180; angle += inc) {
var x = Math.cos(toRadians(angle)) * rad;
var y = Math.sin(toRadians(angle)) * rad;
draw(xc - x, yc - y, xc + x, yc + y);
}
}
function update() {
start_angle1 += 0.1;
start_angle2 -= 0.1;
if(radius<radiusmax) radius++;
context.clearRect(0, 0, width, height);
drawWheel(xcenter, ycenter, start_angle1, 40, radius);
drawWheel(xcenter, ycenter, start_angle2, 40, radius);
requestAnimationFrame(update);
}
update();
};
html,
body {
margin: 0px;
}
canvas {
display: block;
}
<canvas id="canvas"></canvas>
This is one that is a variable length emerging pattern. It has a length array element for each spoke in the wheel that grows at a different rate. You can play with the settings to vary the results:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = canvas.width = window.innerWidth;
var height = canvas.height = window.innerHeight;
var xcenter = width/4;
var ycenter = height/2;
var radius;
var time;
if(width>height) {
radius = height*0.4;
}
else {
radius = width*0.4;
}
var start_angle1 = 0;
var start_angle2 = 0;
function toRadians (angle) {
return angle * (Math.PI / 180);
}
function draw(x1,y1,x2,y2) {
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.stroke();
}
var radmax=width;
var rads = [];
var radsinc = [];
function drawWheel(xc,yc,start_angle,count,rad) {
var inc = 360/count;
var i=0;
for(var angle=start_angle; angle < start_angle+180; angle +=inc) {
var x = Math.cos(toRadians(angle)) * rads[rad+i];
var y = Math.sin(toRadians(angle)) * rads[rad+i];
draw(xc-x,yc-y,xc+x,yc+y);
rads[rad+i] += radsinc[i];
if(rads[rad+i] > radmax) rads[rad+i] = 1;
i++;
}
}
function update() {
var now = new Date().getTime();
var dt = now - (time || now);
time = now;
start_angle1 += (dt/1000) * 10;
start_angle2 -= (dt/1000) * 10;
context.clearRect(0,0,width,height);
drawWheel(xcenter,ycenter,start_angle1,50,0);
drawWheel(xcenter,ycenter,start_angle2,50,50);
requestAnimationFrame(update);
}
function init() {
for(var i=0;i<100;i++) {
rads[i] = 0;
radsinc[i] = Math.random() * 10;
}
}
window.onload = function() {
init();
update();
};
html, body {
margin: 0px;
}
canvas {
width:100%;
height:200px;
display: block;
}
<canvas id="canvas"></canvas>

How I can set text to canvas circle

I used this question and I create shape like this and but now I don't know how I can set text to each circle in just first time click? (like tic tac toe)
Here you go! - I merged it for ease. Just click on circle to see text on it.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var radius = 70;
var lineWidth = 5;
var cols = 3;
var rows = 2;
var distance = 50;
var circles = [];
//click circle to write
canvas.onclick = function(e) {
// correct mouse coordinates:
var rect = canvas.getBoundingClientRect(), // make x/y relative to canvas
x = e.clientX - rect.left,
y = e.clientY - rect.top,
i = 0, circle;
// check which circle:
while(circle = circles[i++]) {
context.beginPath(); // we build a path to check with, but not to draw
context.arc(circle.x, circle.y, circle.radius, 0, 2*Math.PI);
if (context.isPointInPath(x, y) && !circle.clicked) {
circle.clicked = true;
context.fillStyle = "blue";
context.font = "bold 34px Arial";
context.textAlign="center";
context.fillText("Yeah", circle.x, circle.y);
break;
}
}
};
//draw circles
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
// Draw circle
var offset = radius * 2 + lineWidth + distance;
var center = radius + lineWidth;
var x = j * offset + center;
var y = i * offset + center;
circles.push({
id: i + "," + j, // some ID
x: x,
y: y,
radius: radius,
clicked:false
});
console.log(circles)
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = lineWidth;
context.strokeStyle = '#003300';
if (j != cols - 1) {
// Draw horizontal line
var hLineX = x + radius;
var hLineY = y;
context.moveTo(hLineX, hLineY);
context.lineTo(hLineX + distance + lineWidth, hLineY);
}
if (i > 0) {
// Draw vertical line
var vLineY = y - radius - distance - lineWidth;
context.moveTo(x, vLineY);
context.lineTo(x, vLineY + distance + lineWidth);
}
context.stroke();
}
}
<div id="ways" style="width:1000px;margin:0 auto;height:100%;">
<canvas id="canvas" width="1000" height="1000"></canvas>
</div>
Happy Helping!

Categories

Resources