How to create road lines using HTML5 canvas - javascript

I have created a road using canvas. There I wish to add lines in the middle. Also width, height and gap between lines must be increase accordingly.
<canvas id="myCanvas" width="578" height="500"></canvas>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var j = 0;
for(var i = canvas.height*.30; i< canvas.height; i=i+20){
context.beginPath();
context.rect(canvas.width*.50, i-j, 3+j, 10+(j*2));
context.fillStyle = '#000000';
context.fill();
j++;
}
But I couldn't make it by above code. Please help me to solve this.
jsfiddle

Updated : the following solution considers the skew in each line as well so it does not draw rectangles, instead polygons are used.
fiddle here : https://jsfiddle.net/tcdLf0xu/4/
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.clearRect(0,0,canvas.width,canvas.height);
var j = 0;
var y = 0;
for(var j = 1; y < canvas.height; j++){
context.beginPath();
spacing = 2.5
w = j+1;
h = 4*w;
x = canvas.width*.50 - w/2;
y = y + spacing*h;
context.rect(x,y ,w,h );
context.moveTo(x,y);
context.lineTo(x+w,y);
context.lineTo(x+w+1/spacing,y+h);
context.lineTo(x-1/spacing,y+h);
context.lineTo(x,y);
context.closePath();
context.fillStyle = '#000000';
context.fill();
}
Note that its important that you understand what each variable is doing in order to improve the design.
j is incremented linearly, is just a counter till your height is reached by y.
w, the width is increased linearly with each iteration of j.
h, the height is always 5 times the width (change that factor if you want)
x, the position is offset by half the width from the center.
y, would be a multiple of the height to accomodate white space efficiently, i took it as 2.5 but can adjust.

Related

Canvas 2d Only Displays Last Drawing in Series of Elements

I have a simple script that adds a new canvas to a div container for each clock that needs to be drawn based on the number of minutes given. The script will draw the canvas elements without fail and will draw the clock face in the last canvas element however it will not draw a clock face on any preceding canvas elements. Upon review of the console, the output is identical for the canvas elements both with and without the clock face. Not sure what is happening with this. Below is a JSFiddle with my code.
https://jsfiddle.net/1oxfgwkb/
The HTML
<html>
<body>
<div id="clockHolder"></div>
</body>
</html>
The JavaScript
var time = 115;
var holder = document.getElementById("clockHolder");
var clockNum = Math.ceil((time / 60));
for(var q = 1; q <= clockNum; q++) {
var clockFace = 'sample-'+q;
holder.innerHTML += '<canvas id="'+clockFace+'" width="35" height="35"></canvas>';
drawClock(clockFace);
}
function drawClock(clockFace) {
var c = document.getElementById(clockFace);
var ctx = c.getContext("2d");
var radius = (c.height / 2) * 0.9;
var midpoint = c.height / 2;
for(var i=1; i<=12; i++) {
var angle = (i*30) * Math.PI / 180;
ctx.save();
ctx.strokeStyle = 'rgba(100,100,100,0.75)';
ctx.beginPath();
ctx.translate(midpoint, midpoint);
ctx.rotate(angle);
ctx.translate(0, -radius*0.9);
ctx.moveTo(0,0);
ctx.lineTo(0,4);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
ctx.strokeStyle = '#555';
ctx.beginPath();
ctx.arc(midpoint, midpoint, radius*0.9, 0, 2 * Math.PI);
ctx.stroke();
}
Any help would be greatly appreciated.
It's drawing them both but setting the innerHTML of the parent is overwriting all but the last. Setting the innerHTML doesn't preserve existing elements, it makes new ones with identical attributes--but without whatever content you updated in the meantime.
Instead try:
for(var q = 1; q <= clockNum; q++) {
holder.innerHTML += '<canvas id="sample-'+q+'" width="35" height="35"></canvas>';
}
for(var q = 1; q <= clockNum; q++) {
drawClock('sample-'+q);
}
You could also use document.createElement and then holder.append.

How do I create a canvas circle with a triangle inside it?

I want to create a canvas with a circle, and inside the circle should be a triangle. I know how to draw a simple circle (below), but how do I put in the triangle?
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.beginPath();
context.arc(75,100,55,0,2 * Math.PI);
context.stroke();
Add these lines before calling stroke
context.moveTo(75,75);
context.lineTo(100, 100);
context.lineTo(25,150);
context.lineTo(75,75);
It is coming out of the cirle a little bit, but you get the idea.
In order to draw a triangle inside a circle you need to calculate the positions of the vertices. Supposing that your triangle is equilateral the angle between vertices is 120degs or 2*Math.PI/3:
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
let cw = canvas.width = 300;// the width of the canvas
let ch = canvas.height = 300;// the height of the canvas
let c={// the circle: coords of the center and the radius
x:75,y:100,r:55
}
let angle = (2*Math.PI)/3;// the angle between vertices
points = [];// the vertices array
for(let i = 0; i < 3; i++){
let o = {}
o.x = c.x + c.r*Math.cos(i*angle);
o.y = c.y + c.r*Math.sin(i*angle);
points.push(o);
}
// draw the circle
context.beginPath();
context.arc(c.x,c.y,c.r,0,2 * Math.PI);
context.stroke();
// draw the triangle
context.beginPath();
context.moveTo(points[0].x,points[0].y);
for(let i = 1; i < points.length; i++){
context.lineTo(points[i].x,points[i].y);
}
context.closePath();
context.stroke();
canvas{border:1px solid}
<canvas id="myCanvas"></canvas>

html5 canvas draw lines in a circle

I am having some trouble drawing lines in circle with html5 canvas.
I am trying to make the bars look something like this
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
var bars = 50;
var radius = 100;
for(var i = 0; i < bars; i++){
var x = radius*Math.cos(i);
var y = radius*Math.sin(i);
draw_rectangle(x+200,y+200,1,13,i, ctx );
}
function draw_rectangle(x,y,w,h,deg, ctx){
ctx.save();
ctx.translate(x, y);
ctx.rotate(degrees_to_radians(deg));
ctx.fillStyle = "yellow";
ctx.fillRect(-1*(w/2), -1*(h/2), w, h);
ctx.restore();
}
function degrees_to_radians(degrees){
return degrees * Math.PI / 180;
}
function radians_to_degrees(radians){
return radians * 180 / Math.PI;
};
for some reason my lines are all crooked and unaligned. I really need help on this one. https://codepen.io/anon/pen/PRBdYV
The easiest way to deal with such a visualization is to play with the transformation matrix of your context.
You need to understand it as if you were holding a sheet of paper in your hands.
Instead of trying to draw the lines at the correct angle, rotate the sheet of paper, and always draw your lines in the same direction.
This way all you need in your drawing method is the angle, and the height of each bar.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
// the position of the whole thing
var circleX = canvas.width / 2;
var circleY = canvas.height / 2;
//
var bars = 50;
var barWidth = 5;
// inner radius
var radius = 50;
ctx.fillStyle = "yellow";
// no need to use degrees, a full circle is just 2π
for(var i = 0; i < Math.PI*2; i+= (Math.PI*2 / bars)){
draw_rectangle(i, (Math.random()*30) + 10);
}
function draw_rectangle(rad, barHeight){
// reset and move to the center of our circle
ctx.setTransform(1,0,0,1, circleX, circleY);
// rotate the context so we face the correct angle
ctx.rotate(rad);
// move along y axis to reach the inner radius
ctx.translate(0, radius);
// draw the bar
ctx.fillRect(
-barWidth/2, // centered on x
0, // from the inner radius
barWidth,
barHeight // until its own height
);
}
canvas#canvas{
background:black;
}
<html>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
</body>
</html>
https://codepen.io/anon/pen/YajONR
Problems fixed: Math.cos wants radians, not degrees
We need to go from 0 to 360, so I adjusted the number of bars to make that a bit easier, and multiplied i by 6 (so the max value is 60*6==360)
If we don't add +90 when drawing the bars, we just get a circle
Check your codepen and figured out the problem lies in the degrees_to_radians
Here is the update link of you code.Link
PS I only looked at the shape of the circle not alignments of the bar :D

HTML canvas move all elements to event click coords

I have a bits raining effect made with canvas using this code script
var c = document.getElementById("c");
var ctx = c.getContext("2d");
//making the canvas full screen
c.height = window.innerHeight;
c.width = window.innerWidth;
//chinese characters - taken from the unicode charset
var chinese = "0 1 ";
//converting the string into an array of single characters
chinese = chinese.split("");
var font_size = 10;
var columns = c.width/font_size; //number of columns for the rain
//an array of drops - one per column
var drops = [];
//x below is the x coordinate
//1 = y co-ordinate of the drop(same for every drop initially)
for(var x = 0; x < columns; x++)
drops[x] = 1;
//drawing the characters
function draw()
{
//Black BG for the canvas
//translucent BG to show trail
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0, 0, c.width, c.height);
ctx.fillStyle = "#0F0"; //green text
ctx.font = font_size + "px arial";
//looping over drops
for(var i = 0; i < drops.length; i++)
{
//a random chinese character to print
var text = chinese[Math.floor(Math.random()*chinese.length)];
//x = i*font_size, y = value of drops[i]*font_size
ctx.fillText(text, i*font_size, drops[i]*font_size);
//sending the drop back to the top randomly after it has crossed the screen
//adding a randomness to the reset to make the drops scattered on the Y axis
if(drops[i]*font_size > c.height && Math.random() > 0.975)
drops[i] = 0;
//incrementing Y coordinate
drops[i]++;
}
}
setInterval(draw, 33);
and I am trying to make an effect when i click on A button, I want for all the bits to move to the button position and i tried the following code but it is not working properly. I tried to stop the bits raining and move all elements from the current position to the click event coords. Any ideas?
jsFiddle

Removing lines when drawing multiple arcs in a row in javascript

So I'm trying to draw 8 random circles (Or bubbles as I call them in this case) on the screen for a simple project I'm making. I want to make it so that I can show the bubbles, but there are lines connecting each bubble at its startAngle.
<!DOCTYPE html>
<html>
<head>
<title>Image</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var height = canvas.height;
var width = canvas.width;
ctx.strokeRect(0, 0, width, height);
var bubbles = [];
var Bubble = function () {
this.x = Math.floor(Math.random() * width);
this.y = Math.floor(Math.random() * height);
this.xspeed = 5;
this.yspeed = 5;
};
for (var i = 0; i < 8; i++) {
bubbles[i] = new Bubble();
};
Bubble.prototype.draw = function () {
for (var i = 0; i < 8; i++) {
ctx.fillStyle = "Black";
ctx.arc(bubbles[i].x, bubbles[i].y, 10, 0, Math.PI * 2, false);
}
};
setInterval(function () {
for (var i = 0; i < bubbles.length; i++) {
ctx.strokeStyle = "Black";
bubbles[i].draw();
ctx.stroke();
}
}, 30);
</script>
</body>
</html>
Basically, I've made 8 Bubble objects, then I've drawn an arc at their x and y (random) position, but it shows lines connecting them like so:
Output of code
When you run the code, it randomly generates 8 different locations and draws 8 arcs at their location, but it shows the lines that connect them. Is there a way to hide or get rid of these lines? I've tried to clear the canvas after each draw, but that hides the entire thing including the circle. I've been searching for most of the day and I couldn't find an answer to my specific problem. The answer is probably obvious, but I couldn't seem to find the solution due to my inexperience.
Call ctx.beginPath() before arc() to draw separate entities?
ctx.arc() creates an ctx.lineTo() between the last coordinates of the current path, and the first position of the arc.
So to avoid it, you can simply manually call moveTo() to lift the drawing pen to the first position of the arc.
This way, you can draw multiple arcs in the same Path and in the same stroke call (which becomes interesting when you draw a lot of arcs)
const ctx = c.getContext('2d'),
w = c.width,
h = c.height;
ctx.beginPath(); // call it once
for(let i = 0; i<100; i++){
let rad = Math.random()*20 + 5
let posX = rad + Math.random() * (w - rad *2);
let posY = rad + Math.random() * (h - rad *2);
// our arc will start at 3 o'clock
ctx.moveTo(posX + rad, posY); // so simply add 'rad' to the centerX
ctx.arc(posX, posY, rad, 0, Math.PI*2);
}
ctx.stroke(); // call it once
<canvas id="c" width="500"></canvas>

Categories

Resources