I've got this piece of code that draws a ball and i want to continuously pass in different cooridinates in order to make it move around but when the refresh rate gets way too high, canvas stops updating. How do i force canvas to update and redraw everything with the arguments passed in?
var c = document.getElementById("circle");
var ctx = c.getContext("2d");
var x = Math.floor(Math.random() * 50);
var y = Math.floor(Math.random() * 50);
function determinePosition(x, y) {
var trueX = x + 120;
var trueY = y + 80;
ctx.beginPath();
ctx.arc(trueX, trueY, 10, 0, 2 * Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.strokeStyle = "black";
ctx.stroke();
}
while(true){
determinePosition(x, y);
}
<div class="gcircle">
<canvas id="circle" width="240px" height="160"></canvas>
</div>
var c = document.getElementById("circle");
var ctx = c.getContext("2d");
function determinePosition(x, y) {
//clear the canvas
ctx.clearRect(0, 0, c.width, c.height);
var trueX = x + 120;
var trueY = y + 80;
ctx.beginPath();
ctx.arc(trueX, trueY, 10, 0, 2 * Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.strokeStyle = "black";
ctx.stroke();
}
//set random location for each 0.5 sec
setInterval(function() {
var x = Math.floor(Math.random() * 50);
var y = Math.floor(Math.random() * 50);
determinePosition(x, y);
}, 500)
<div class="gcircle">
<canvas id="circle" width="240px" height="160"></canvas>
</div>
`
Drawing should always happen in a requestAnimationFrame loop. requestAnimationFrame runs at your monitor's refresh rate, so it's the fastest any animation can run. You can set it up like this:
var c = document.getElementById("circle");
var ctx = c.getContext("2d");
var x = Math.floor(Math.random() * 50);
var y = Math.floor(Math.random() * 50);
var trueX = 0;
var trueY = 0;
function determinePosition(x, y) {
trueX = x + 120;
trueY = y + 80;
}
requestAnimationFrame(function draw() {
ctx.clearRect(0, 0, c.width, c.height);
ctx.beginPath();
ctx.arc(trueX, trueY, 10, 0, 2 * Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.strokeStyle = "black";
ctx.stroke();
requestAnimationFrame(draw);
})
determinePosition(x, y);
Related
I am trying to get this snowflake design to be "drawn out" using a "timer" on javascript. In one of the examples, this is how a circle is drawn:
http://jsfiddle.net/avanhout13/9opengv7/1/
var t = 0;
var c = document.getElementById("myCanvas");
var R = c.width/2;
var ctx = c.getContext("2d");
function doDrawing() {
t = 0;
// Clear the Canvas
ctx.clear();
// Create a random color
var timesRun = 0;
var color = '#'+Math.floor(Math.random()*16777215).toString(16);
// Initial x and y
var x = R+R*Math.cos(0);
var y = R+R*Math.sin(0);
// Start the Drawing
ctx.beginPath();
ctx.strokeStyle = color;
ctx.moveTo(x,y);
//Use the timer to create drawing
var interval = setInterval(function(){
timesRun += 1;
if(timesRun === 65){
clearInterval(interval); }
drawCircle();}, 20);
}
function drawCircle()
{
t += 0.1;
x = Math.floor(R+R*Math.cos(t));
y = Math.floor(R+R*Math.sin(t));
ctx.lineTo(x,y);
ctx.stroke();
}
CanvasRenderingContext2D.prototype.clear =
CanvasRenderingContext2D.prototype.clear || function (preserveTransform) {
if (preserveTransform) {
this.save();
this.setTransform(1, 0, 0, 1, 0, 0);
}
this.clearRect(0, 0, this.canvas.width, this.canvas.height);
if (preserveTransform) {
this.restore();
}
};
This is the snowflake design. I want to do a similar drawing technique but cannot seem to figure out how to get it to actively be drawn when the "draw" button is clicked.
https://jsfiddle.net/avanhout13/g8xs9Ljf/
let canvas = document.getElementById('snowflake'),
ctx = canvas.getContext('2d'),
maxLevel = 2,
branches = 7;
canvas.width = 1000;
canvas.height = 1000;
ctx.translate(canvas.width / 2, canvas.height / 2);
let angle = Math.PI * 2 + Math.random();
for (let i = 0; i < 6; i++) {
drawLine(0);
ctx.rotate(Math.PI * 2 / 6);
}
function drawLine(level) {
if (level > maxLevel) return;
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(200, 0);
ctx.stroke();
for (let i = 1; i < branches + 1; i++) {
ctx.save();
ctx.translate(200 * i / (branches + 1), 0);
ctx.save();
ctx.rotate(angle);
drawLine(level + 1);
ctx.restore();
ctx.save();
ctx.rotate(-angle);
drawLine(level + 1);
ctx.restore();
ctx.restore();
}
}
Any idea of how to get this to draw? Thank you.
Make sure that your js code isn't loaded in file type, otherwise you can not use the function by input it's name in the html tag directly.
In JSFiddle, it could be change by the select label on the top left corner of your js window.
Hope this could be help.
<html lane='en'>
<head>
<meta charset='utf-8'>
<title> Snowflake Spirograph</title>
</head>
<body>
<button onclick="draw()">Start Drawing</button>
<canvas id="snowflake" width="1000" height="1000"></canvas>
</body>
</html>
const canvas = document.getElementById('snowflake');
const ctx = canvas.getContext('2d');
const maxLevel = 2;
const branches = 7;
ctx.translate(canvas.width / 2, canvas.height / 2);
let angle = Math.PI * 2 + Math.random();
function draw() {
for (let i = 0; i < 6; i++) {
drawLine(1);
ctx.rotate(Math.PI * 2 / 6);
}
}
function drawLine(level) {
if (level > maxLevel) return;
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(200, 0);
ctx.stroke();
for (let i = 1; i < branches + 1; i++) {
ctx.save();
ctx.translate(200 * i / (branches + 1), 0);
ctx.save();
ctx.rotate(angle);
drawLine(level + 1);
ctx.restore();
ctx.save();
ctx.rotate(-angle);
drawLine(level + 1);
ctx.restore();
ctx.restore();
}
}
I want to implement a ripple effect in JavaScript for that I am using a canvas element of HTML 5.
I have created 4 circles in order to implement ripple effect I am thinking of showing only one circle at a time here is my code
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = window.innerWidth/4;
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth/2;
canvas.height = window.innerWidth/2;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(i, i, i-i/1.5, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(i, i, i-i/2.5, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(i, i, i-i/5, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(i, i, i, 0, 2 * Math.PI);
ctx.stroke();
output
how can I remove a specific circle here
there is a function ctx.clearRect(x, y, width, height); but it works only on rectangle.
also, let me know whether it's a good approach to create a ripple effect in canvas
If you are looking for something like this, you can do it simply by resetting the canvas after some time.
Also you can trigger the elements to be created at a certain time to make that effect of showing them one by one.
Here is a sample
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = window.innerWidth/4;
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth/2;
canvas.height = window.innerWidth/2;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(i, i, i-i/1.5, 0, 2 * Math.PI);
ctx.stroke();
window.setTimeout(() => {
ctx.beginPath();
ctx.arc(i, i, i-i/2.5, 0, 2 * Math.PI);
ctx.stroke();
}, 200*1)
window.setTimeout(() => {
ctx.beginPath();
ctx.arc(i, i, i-i/5, 0, 2 * Math.PI);
ctx.stroke();
}, 200*2)
window.setTimeout(() => {
ctx.beginPath();
ctx.arc(i, i, i, 0, 2 * Math.PI);
ctx.stroke();
}, 200*3)
window.setTimeout(() => {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = window.innerWidth/4;
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth/2;
canvas.height = window.innerWidth/2;
}, 200*6)
<canvas id="myCanvas"></canvas>
Here's a much much better and smoother ripple effect than the one you seek:
NOTE: run it on CodePen because for some reason it's not fully functional on stack overflow, but works fine in an HTML document or on CodePen
CodePen: https://codepen.io/Undefined_Variable/pen/dqZpzE
Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>canvas</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
var canvas = document.body.querySelector("#myCanvas");
var ctx = canvas.getContext("2d");
canvas.width = window.innerWidth * 0.98;
canvas.height = window.innerHeight * 0.97;
var shapeArr = [];
window.addEventListener('resize', function () {
canvas.width = window.innerWidth * 0.98;
canvas.height = window.innerHeight * 0.98;
CW = canvas.width;
CH = canvas.height;
})
var CW = canvas.width;
var CH = canvas.height;
class circle {
constructor(centerX, centerY, radius) {
this.centerX = centerX;
this.centerY = centerY;
this.radius = radius;
this.opacity = 1;
this.strokeStyle = "rgba(0, 0, 0, " + this.opacity + ")";
}
expandCircle() {
this.radius += 3;
this.opacity -= 0.015;
this.strokeStyle = "rgba(0, 0, 0, " + this.opacity + ")";
if (this.radius > window.innerWidth/4) {
this.radius = 0;
this.opacity = 1;
}
}
}
function createCircle(centerX, centerY, radius) {
shapeArr.push(new circle(centerX, centerY, radius));
}
function drawCircle(centerX, centerY, radius, strokeClr) {
ctx.strokeStyle = strokeClr;
ctx.save();
ctx.translate(centerX, centerY);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2);
ctx.closePath();
ctx.stroke();
ctx.restore()
}
createCircle(CW / 2, CH / 2, 0);
createCircle(CW / 2, CH / 2, 0);
createCircle(CW / 2, CH / 2, 0);
function firstWave() {
ctx.clearRect(0, 0, CW, CH);
drawCircle(shapeArr[0].centerX, shapeArr[0].centerY, shapeArr[0].radius, shapeArr[0].strokeStyle);
shapeArr[0].expandCircle();
requestAnimationFrame(firstWave);
};
firstWave();
setTimeout(function secondWave() {
drawCircle(shapeArr[1].centerX, shapeArr[1].centerY, shapeArr[1].radius, shapeArr[1].strokeStyle);
shapeArr[1].expandCircle();
requestAnimationFrame(secondWave);
}, 250);
setTimeout(function thirdWave() {
drawCircle(shapeArr[2].centerX, shapeArr[2].centerY, shapeArr[2].radius, shapeArr[2].strokeStyle);
shapeArr[2].expandCircle();
requestAnimationFrame(thirdWave);
}, 500)
</script>
</body>
</html>
I'm trying to make circular chart on html5 canvas el.
(function () {
var ctx = document.getElementById('canvas').getContext('2d');
var counter = 0;
var start = 4.72;
var cW = ctx.canvas.width;
var cH = ctx.canvas.height;
var diff;
var maxVal = 44;
function progressChart(){
diff = ((counter / 100) * Math.PI*2*10).toFixed(2);
ctx.clearRect(0, 0, cW, cH);
ctx.lineWidth = 15;
ctx.fillStyle = '#ff883c';
ctx.strokeStyle = '#ff883c';
ctx.textAlign = 'center';
ctx.font = '25px Arial';
ctx.fillText(counter+'%', cW*.5, cH*.55, cW);
ctx.beginPath();
ctx.arc(70, 70, 60, start, diff/10+start, false);
ctx.stroke();
if(counter >= maxVal){
clearTimeout(drawChart);
}
counter++;
}
var drawChart = setInterval(progressChart, 20);
})();
<canvas id="canvas" width="140" height="140"></canvas>
I want to add doughnut background before browser start drawing fill chart. Unfortunately, I need to use ctx.clearRect() because I've got strange visual effect. Is any way to combine this two rings?
Yes, there is a way and that is, drawing another arc for doughnut background, before drawing fill chart.
Also, you should use requestAnimationFrame() instead of setInterval(), for better efficiency.
var ctx = document.getElementById('canvas').getContext('2d');
var counter = 0;
var start = 4.72;
var cW = ctx.canvas.width;
var cH = ctx.canvas.height;
var diff;
var maxVal = 44;
var rAF;
function progressChart() {
diff = ((counter / 100) * Math.PI * 2 * 10).toFixed(2);
ctx.clearRect(0, 0, cW, cH);
ctx.lineWidth = 15;
ctx.fillStyle = '#ff883c';
ctx.textAlign = 'center';
ctx.font = '25px Arial';
ctx.fillText(counter + '%', cW * .5, cH * .55, cW);
// doughnut background
ctx.beginPath();
ctx.arc(70, 70, 60, 0, Math.PI * 2, false);
ctx.strokeStyle = '#ddd';
ctx.stroke();
// fill chart
ctx.beginPath();
ctx.arc(70, 70, 60, start, diff / 10 + start, false);
ctx.strokeStyle = '#ff883c';
ctx.stroke();
if (counter >= maxVal) {
cancelAnimationFrame(rAF);
return;
}
counter++;
rAF = requestAnimationFrame(progressChart);
}
progressChart();
<canvas id="canvas" width="140" height="140"></canvas>
I am trying to change the size of my canvas element.
var canvas = document.getElementById('timer'),
ctx = canvas.getContext('2d'),
sec = this.length,
countdown = sec;
ctx.lineWidth = 10;
ctx.strokeStyle = "#F60017";
ctx.strokeStyle = "#000000";
var startAngle = 0,
time = 0,
intv = setInterval(function () {
ctx.clearRect(0, 0, 200, 200);
var endAngle = (Math.PI * time * 2 / sec);
ctx.arc(65, 35, 30, startAngle, endAngle, false);
startAngle = endAngle;
ctx.stroke();
countdown--;
if (++time > sec, countdown == 0) {
clearInterval(intv), $("#timer, #counter").show();
}
}, 10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<canvas id="timer"></canvas>
If I change ctx.clearRect(0, 0, 200, 200); it still remains 200x200
The clearRect() is used to remove the previous drawing before a new one is drawn. I added new variables: x, y and size. Along with ctx.lineWidth, this should be enough to change the appearance.
var canvas = document.getElementById('timer'),
ctx = canvas.getContext('2d'),
sec = 100,
countdown = sec;
var x = 60,
y = 60
size = 30; // change me
ctx.lineWidth = 25;
ctx.strokeStyle = "#F60017";
ctx.strokeStyle = "#000000";
var startAngle = 0,
time = 0,
intv = setInterval(function () {
console.log('interval');
ctx.clearRect(0, 0, 200, 200);
var endAngle = (Math.PI * time * 2 / sec);
ctx.arc(x, y, size, startAngle, endAngle, false);
startAngle = endAngle;
ctx.stroke();
countdown--;
if (++time > sec && countdown <0) {
clearInterval(intv), $("#timer, #counter").show();
}
}, 10);
<canvas id="timer"></canvas>
On an HTML5 canvas I can't find a method to make colored circles. I've been consulting this as a reference.
Here is my current attempt
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillRect(20, 20, 100, 100);
ctx.lineJoin = "round";
ctx.lineWidth = "cornerRadius";
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
(Also on jsFiddle: http://jsfiddle.net/kvnm21r1/1/)
I've tried using the canvas arc method, which creates a circle, but doesn't color it.
I can't use the border-radius property, because ctx is not an element.
Is there any way, I can transform my squares into circles?
Thanks in advance.
You can use quadratic curves to "round-out" the straight lines of your square until they form a circle.
// change sideCount to the # of poly sides desired
//
var sideCount = 4;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth = 2;
ctx.fillStyle = randomColor();
var PI2 = Math.PI * 2;
var cx = 150;
var cy = 150;
var radius = 100;
var xx = function (a) {
return (cx + radius * Math.cos(a));
}
var yy = function (a) {
return (cy + radius * Math.sin(a));
}
var lerp = function (a, b, x) {
return (a + x * (b - a));
}
var sides = [];
for (var i = 0; i < sideCount; i++) {
sides.push(makeSide(i, sideCount));
}
var percent = 0;
var percentDirection = 0.50;
$("#toShape").click(function () {
percentDirection = -0.50;
})
$("#toCircle").click(function () {
percentDirection = 0.50;
})
animate();
// functions
function animate() {
requestAnimationFrame(animate);
drawSides(percent);
percent += percentDirection;
if (percent > 100) {
percent = 100;
}
if (percent < 0) {
percent = 0;
}
}
function drawSides(pct, color) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (pct == 100) {
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, PI2);
ctx.closePath();
ctx.fill();
} else {
ctx.beginPath();
ctx.moveTo(sides[0].x0, sides[0].y0);
for (var i = 0; i < sideCount; i++) {
var side = sides[i];
var cpx = lerp(side.midX, side.cpX, pct / 100);
var cpy = lerp(side.midY, side.cpY, pct / 100);
ctx.quadraticCurveTo(cpx, cpy, side.x2, side.y2);
}
ctx.fill();
}
}
function makeSide(n, sideCount) {
var sweep = PI2 / sideCount;
var sAngle = sweep * (n - 1);
var eAngle = sweep * n;
var x0 = xx(sAngle);
var y0 = yy(sAngle);
var x1 = xx((eAngle + sAngle) / 2);
var y1 = yy((eAngle + sAngle) / 2);
var x2 = xx(eAngle);
var y2 = yy(eAngle);
var dx = x2 - x1;
var dy = y2 - y1;
var a = Math.atan2(dy, dx);
var midX = lerp(x0, x2, 0.50);
var midY = lerp(y0, y2, 0.50);
var cpX = 2 * x1 - x0 / 2 - x2 / 2;
var cpY = 2 * y1 - y0 / 2 - y2 / 2;
return ({
x0: x0,
y0: y0,
x2: x2,
y2: y2,
midX: midX,
midY: midY,
cpX: cpX,
cpY: cpY,
color: randomColor()
});
}
function randomColor() {
return ('#' + Math.floor(Math.random() * 16777215).toString(16));
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id="toShape">Animate to Shape</button>
<button id="toCircle">Animate to Circle</button><br>
<canvas id="canvas" width=300 height=300></canvas>
JSfiddle with a circle
To draw a circle you'll need to draw an arc and have a starting angle and an ending angle. So you'll have to use Pi and define a radius.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
Avoid w3schools.com whenever possible. Refer to sites like MDN instead.
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
ctx.beginPath();
var radius = 50; // Arc radius
var startAngle = 0; // Starting point on circle
var endAngle = Math.PI*2; // End point on circle
ctx.arc(150, 75, radius, startAngle, endAngle, true);
ctx.fill();
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">