I'm trying to incrementally change my line width.
But the following code doesn't work:
var csMargin = 10; //Color select margin
var csSize = 15;
var csNumber = 4;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = (csMargin * 2 + csSize) * csNumber;
canvas.height = (csMargin * 2 + csSize) * csNumber;
document.body.appendChild(canvas);
function DrawCS(){
for(i = 0; i < csNumber; i++){
for(j=0; j< csNumber ;j++){
ctx.rect(csMargin*(i+1)+i*csSize,csMargin*(j+1)+j*csSize,csSize,csSize)
//the line width should increase as j increases!!
ctx.lineWidth=j*2;
ctx.stroke();
}
}
}
DrawCS();
I should be getting a line width that gets thicker every line but I get the same thickness from every square.
You forgot a ctx.beginPath(); before your ctx.rect(...).
Then to avoid that zero width use e.g.:
ctx.lineWidth=(j+1)*2;
<canvas id="canvas"></canvas>
<script>
var csMargin = 10; //Color select margin
var csSize = 15;
var csNumber = 4;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = (csMargin * 2 + csSize) * csNumber;
canvas.height = (csMargin * 2 + csSize) * csNumber;
document.body.appendChild(canvas);
function DrawCS(){
ctx.stroke();
for(i = 0; i < csNumber; i++){
for(j=0; j< csNumber ;j++){
ctx.beginPath();
ctx.rect(csMargin*(i+1)+i*csSize,csMargin*(j+1)+j*csSize,csSize,csSize);
ctx.lineWidth=(j+1)*2;
//the line width should increase as j increases!!
ctx.stroke();
}
}
}
DrawCS();
</script>
Related
I have multiple shapes(rects,arcs,...) and I want all of them to be around one specific circle(on border of some invisible circle).
consider center of this invisible circle is at the center of screen
(canvas.width/2,canvas.height/2) and its radius is 200
but shapes are generated inside some rectangle and I don't want this.
let canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let particlesNum = 100;
let particles = [];
let ctx = canvas.getContext('2d');
function Particle(x,y,r){
this.x = x ;
this.y = y ;
this.r = r ;
}
Particle.prototype.draw = function() {
ctx.beginPath();
ctx.fillStyle = 'red' ;
ctx.arc(this.x,this.y,this.r,0,2*Math.PI,false);
ctx.fill();
}
function generateParticels(){
let x,y,r ;
for(let i=0 ; i<particlesNum ; i++){
x = canvas.width/2+Math.cos(Math.random()*(2*Math.PI))*200;
y = canvas.height/2+Math.sin(Math.random()*(2*Math.PI))*200;
r = 1 ; //radius of each circle
particles.push(new Particle(x,y,r));
}
particles.forEach(particle=>particle.draw());
}
generateParticels();
*{
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,body{height: 100%;}
<canvas></canvas>
The problem is that you generate different random angle for X and Y separately. Use the same Random angle for both:
let canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let particlesNum = 100;
let particles = [];
let ctx = canvas.getContext('2d');
function Particle(x,y,r){
this.x = x ;
this.y = y ;
this.r = r ;
}
Particle.prototype.draw = function() {
ctx.beginPath();
ctx.fillStyle = 'red' ;
ctx.arc(this.x,this.y,this.r,0,2*Math.PI,false);
ctx.fill();
}
function generateParticels(){
let x, y, r, randomAngle ;
for(let i=0 ; i<particlesNum ; i++){
randomAngle = Math.random() * 2 * Math.PI;
x = canvas.width / 2 + Math.cos(randomAngle) * 200;
y = canvas.height / 2 + Math.sin(randomAngle) * 200;
r = 1 ; //radius of each circle
particles.push(new Particle(x,y,r));
}
particles.forEach(particle=>particle.draw());
}
generateParticels();
*{
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,body{height: 100%;}
<canvas></canvas>
I'm just starting with js and need little help! I got these two functions, to draw circles and splattered circles, I need to create a for loop to draw 10 random coloured circles and 10 random splattered circles! how can i do it? thanks
<canvas id="myCanvas" width="550" height="400"></canvas>
<script>
var randomColour;
var randomSize;
var xPos;
var yPos;
var i;
var j;
randomColour = '#' + Math.random().toString(16).substring(4); // random colour
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
function drawFilledCircle(size,xPos,Ypos,colour){ //draw circle
ctx.beginPath();
ctx.arc(xPos,yPos,size,0,2*Math.PI);
ctx.fillStyle = colour;
ctx.fill();
}
function drawSplatter(size,xPos,yPos,colour){ // draw splattered circle
for(j=0;j<10;j++){
var splatSize = size / Math.round(Math.random()*30);
drawFilledCircle(splatSize,xPos + Math.round(Math.random()*50),yPos + Math.round(Math.random()*50),colour);
}
}
</script>
var randomColour;
var randomSize;
var xPos;
var yPos;
var i;
var j;
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
function drawFilledCircle(size, xPos, yPos, colour) { //draw circle
ctx.beginPath();
ctx.arc(xPos, yPos, size, 0, 2 * Math.PI);
ctx.fillStyle = colour;
ctx.fill();
}
function drawSplatter(size, xPos, yPos, colour) { // draw splattered circle
for (j = 0; j < 10; j++) {
var splatSize = size / Math.round(Math.random() * 30);
drawFilledCircle(splatSize, xPos + Math.round(Math.random() * 50), yPos + Math.round(Math.random() * 50), colour);
}
}
var maxSize = 30;
var minSize = 10;
var maxX = c.width;
var maxY = c.height;
function randoms() {
var size = Math.ceil(Math.random() * maxSize);
size = Math.max(size, minSize);
var x = Math.floor(Math.random() * maxX);
var y = Math.floor(Math.random() * maxY);
var colour = '#' + Math.random().toString(16).substr(2,6);
return {size:size, x:x, y:y, colour:colour};
}
for (var i = 0; i < 10; i++) {
var r = randoms();
drawFilledCircle(r.size, r.x, r.y, r.colour);
r = randoms();
drawSplatter(r.size, r.x, r.y, r.colour);
}
body {
background-color:#222222;
}
<canvas id="myCanvas" width="550" height="400"></canvas>
I'm still very new to the canvas element and I'm trying to draw random polygon shapes (triangular shapes) in random places on the canvas element. But I have trouble getting my head around it.
I have this so far, which draws a ploygon nicely, but how to add the randomness and positioning completely eludes me
var c = document.getElementById('c');
if (c.getContext) {
c2 = c.getContext('2d');
var width = c2.width;
var height = c2.height;
var maxAmount = 20;
for (i = 0; i < maxAmount; i++) {
var polySize = 50;
var posx = (Math.random() * (width - polySize)).toFixed();
var posy = (Math.random() * (height - polySize)).toFixed();
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(posx, posy);
c2.lineTo(100, 50);
c2.lineTo(50, 100);
c2.lineTo(0, 90);
c2.closePath();
c2.fill();
}
}
<canvas id="c" \>
You are trying to get the width and height properties of the Context2D property of your canvas, which both returned undefined.
What you need instead is the canvas element's width and height properties.
Now, since your comment to the other answer, if you need to move the whole shape, just use the first point you saved in posx and posy variables and then adjust the other points positions :
var c = document.getElementById('c');
c.width =500;
c.height= 500;
if (c.getContext) {
var c2 = c.getContext('2d');
var width = c.width;
var height = c.height;
var maxAmount = 20;
for (var i = 0; i < maxAmount; i++) {
var polySize = 50;
var posx = (Math.random() * (width - polySize));
var posy = (Math.random() * (height - polySize));
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(posx, posy);
c2.lineTo(posx+100, posy+50);
c2.lineTo(posx+50,posy+100);
c2.lineTo(posx+0, posy+90);
c2.closePath();
c2.stroke();
c2.fill();
}
}
<canvas id="c"><\canvas>
Here canvas width and height properties are not set. so when invoke code following line of code, it returns NaN
var width = c2.width;
var height = c2.height;
To get random position try following code base
<canvas id="c" width="250" height="250" \>
var c = document.getElementById('c');
if (c.getContext)
{
c2 = c.getContext('2d');
var width = c.width;
var height = c.height;
var maxAmount = 5;
for (i = 0; i < maxAmount; i++) {
var polySize = 50;
var posx = (Math.random() * (width - polySize)).toFixed();
var posy = (Math.random() * (height - polySize)).toFixed();
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(posx, posy);
c2.lineTo(100, 50);
c2.lineTo(50, 100);
c2.lineTo(0, 90);
c2.closePath();
c2.fill();
}
}
I am making a pie chart with canvas but I am unable to put labels into the canvas. I tried so many things... Can you help me?
HTML
<canvas id="can" width="200" height="200" />
JS
var D1 = 15;
var D2 = 15;
var D3 = 45;
var D4 = 25;
var canvas = document.getElementById("can");
var ctx = canvas.getContext("2d");
var lastend = 0;
var data = [D1,D2,D3,D4]; // If you add more data values make sure you add more colors
var myTotal = 0; // Automatically calculated so don't touch
var myColor = ["#ECD078","#D95B43","#C02942","#542437"];
var labels = ["25%","25%","25%","25%"];
for (var e = 0; e < data.length; e++) {
myTotal += data[e];
ctx.font = 'bold 15pt Calibri';
ctx.fillText(labels[e],15,15);
}
for (var i = 0; i < data.length; i++) {
ctx.fillStyle = myColor[i];
ctx.beginPath();
ctx.moveTo(canvas.width / 2, canvas.height / 2);
// Arc Parameters: x, y, radius, startingAngle (radians), endingAngle (radians), antiClockwise (boolean)
ctx.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 * (data[i] / myTotal)), false);
ctx.lineTo(canvas.width / 2, canvas.height / 2);
ctx.fill();
lastend += Math.PI * 2 * (data[i] / myTotal);
}
My intention is to put the labels[] number in order, inside the pie chart.
If its not too late, you may try this:
https://jsfiddle.net/rradik/kuqdwuyd/
<canvas id="canvas" width="200" height="200" />
var canvas;
var ctx;
var lastend = 0;
var pieColor = ["#ECD078","#D95B43","#C02942","#542437","#53777A"];
var pieData = [10,30,20,60,40];
var pieTotal = 10 + 30 + 20 + 60 + 40; // done manually for demo
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
var hwidth = ctx.canvas.width/2;
var hheight = ctx.canvas.height/2;
for (var i = 0; i < pieData.length; i++) {
ctx.fillStyle = pieColor[i];
ctx.beginPath();
ctx.moveTo(hwidth,hheight);
ctx.arc(hwidth,hheight,hheight,lastend,lastend+
(Math.PI*2*(pieData[i]/pieTotal)),false);
ctx.lineTo(hwidth,hheight);
ctx.fill();
//Labels on pie slices (fully transparent circle within outer pie circle, to get middle of pie slice)
//ctx.fillStyle = "rgba(255, 255, 255, 0.5)"; //uncomment for debugging
// ctx.beginPath();
// ctx.moveTo(hwidth,hheight);
// ctx.arc(hwidth,hheight,hheight/1.25,lastend,lastend+
// (Math.PI*(pieData[i]/pieTotal)),false); //uncomment for debugging
var radius = hheight/1.5; //use suitable radius
var endAngle = lastend + (Math.PI*(pieData[i]/pieTotal));
var setX = hwidth + Math.cos(endAngle) * radius;
var setY = hheight + Math.sin(endAngle) * radius;
ctx.fillStyle = "#ffffff";
ctx.font = '14px Calibri';
ctx.fillText(pieData[i],setX,setY);
// ctx.lineTo(hwidth,hheight);
//ctx.fill(); //uncomment for debugging
lastend += Math.PI*2*(pieData[i]/pieTotal);
}
May not be perfect and very efficient one, but does the job nevertheless
The problem was that all your text was overlapping.
I simply changed the order of execution. The text is now drawn after the pie chart. One more thing, I added an offset to the text, each time the loop runs I offset by 50.
Working Example
var offset = 50;
for (var e = 0; e < data.length; e++) {
ctx.font = 'bold 15pt Calibri';
ctx.fillText(labels[e],offset*e,180);
}
I'm trying to make each rectangle in this fiddle to move up and down so it looks like a music equalizer. I wants the bars to animate up and down, and have absolutely no idea how to do animations. Fiddles would really help :)
http://jsfiddle.net/kiransh/1jqhznt6/
HTML
<canvas id="myCanvas" height="100"> </canvas>
JavaScript
var width = 8;
var distance = 3;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.canvas.width = window.innerWidth;
var total = ctx.canvas.width;
var max = total/2+52;
var min = total/2-60;
ctx.fillStyle = "black";
ctx.globalAlpha=0.3;
for(var x = 0; x<total; x+=12)
{
if(x<= max && x>=min)
{
var height= Math.floor(Math.random()*40)+5;
}
else
{
var height= Math.floor(Math.random()*100)+5;
}
ctx.fillRect(x,100-height,width,height);
}
I don't know if this is the effect you need, but it should help you to start.
requestAnimationFrame is used to execute draw() at each frame. Each bar is re-defined after the specified delay, and then goes down.
var width = 8;
var distance = 3;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.canvas.width = window.innerWidth;
var total = ctx.canvas.width;
var max = total/2+52;
var min = total/2-60;
ctx.fillStyle = "black";
ctx.globalAlpha=0.3;
var bars = [];
var barsCount = Math.floor(total / 12);
var barsLastRefreshTime = null;
var barsRefreshInterval = 500;
setInterval(function() {
for(var i = 0; i<barsCount; i++) {
var x = i * 12;
if(x<= max && x>=min) {
var height= Math.floor(Math.random()*40)+5;
} else {
var height= Math.floor(Math.random()*100)+5;
}
bars[i] = height;
}
barsLastRefreshTime = (new Date()).getTime();
}, barsRefreshInterval);
function draw() {
var currentTime = (new Date()).getTime();
var timePassedRate = (barsRefreshInterval - (currentTime - barsLastRefreshTime)) / barsRefreshInterval;
ctx.clearRect(0,0,c.width,c.height);
for(var i = 0; i<bars.length; i++) {
var x = i * 12;
var height = bars[i] * timePassedRate;
ctx.fillRect(x,100-height,width,height);
}
requestAnimationFrame(draw);
}
draw();
(I can't find a way to save the fiddle ?!?)
You need to use a tick function to update your canvas. You can use requestAnimationFrame() and choose a time interval you'd like to animate on (you can determine this using Date.now()).
Then, keep a list of your bars and change their height. Then re-render it to your canvas.
Here is some quick hacky code...
var width = 8;
var distance = 3;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.canvas.width = window.innerWidth;
var total = ctx.canvas.width;
var max = total / 2 + 52;
var min = total / 2 - 60;
ctx.fillStyle = "black";
ctx.globalAlpha = 0.3;
var lastDrawTime = Date.now();
var draw = function () {
if (Date.now() - lastDrawTime < 60) {
return webkitRequestAnimationFrame(draw);
}
ctx.clearRect(0, 0, c.width, c.height);
for (var x = 0; x < total; x += 12) {
if (x <= max && x >= min) {
var height = Math.floor(Math.random() * 40) + 5;
} else {
var height = Math.floor(Math.random() * 100) + 5;
}
ctx.fillRect(x, 100 - height, width, height);
}
lastDrawTime = Date.now();
webkitRequestAnimationFrame(draw);
};
draw();
To do animation you have to clear the canvas and redraw the rectangles in their new position at each frame, using either setInterval() or setTimeout() or requestAnimationFrame().
The best is to use requestAnimationFrame() for adapation of frames per second.