Reducing JavaScript Markup when drawing objects in HTML5 - javascript

I'm trying to draw a few circles that will all have the same properties, but a different endingAngle, I don't want to write the entire circle code 5 times, is there a way to either assign most of the code to a class, and just change one variable for 5 different ID's?
Here are two of the circles
var canvas = document.getElementById('firefox');
var context = canvas.getContext('2d');
context.beginPath();
context.arc(64, 64, 60, 1.5*Math.PI, .3*Math.PI, true);
context.lineWidth = 8;
context.lineCap = "round";
context.strokeStyle = '#c5731e';
context.stroke();
var canvas = document.getElementById('chrome');
var context = canvas.getContext('2d');
context.beginPath();
context.arc(64, 64, 60, 1.5*Math.PI, .9*Math.PI, true);
context.lineWidth = 8;
context.lineCap = "round";
context.strokeStyle = '#c5731e';
context.stroke();
.3*Math.PI and .9*Math.PI are the only things that are going to change between circles, any way I can write the above so I don't have to write all of it 5 times?

You don't have to change your markup, you can do this :
['firefox','chrome'].forEach(function(id, index){
var canvas = document.getElementById(id);
var context = canvas.getContext('2d');
context.beginPath();
context.arc(64, 64, 60, 1.5*Math.PI, (index+1)*0.3*Math.PI, true);
context.lineWidth = 8;
context.lineCap = "round";
context.strokeStyle = '#c5731e';
context.stroke();
});
You don't have to duplicate the code or to call a function, you just have to add elements in the array.
If you can't infer the angle from the index, then,
either you want to "hardcode" the data, then use a function (see other answer)
or you want to manage the data as data.
In the latter case, you can do something like this :
var data = [
{id:'firefox', angle:33},
{id:'chrome', angle:43}
];
data.forEach(function(e){
var canvas = document.getElementById(e.id);
var context = canvas.getContext('2d');
context.beginPath();
context.arc(64, 64, 60, 1.5*Math.PI, e.angle, true);
context.lineWidth = 8;
context.lineCap = "round";
context.strokeStyle = '#c5731e';
context.stroke();
});

Create a function e.g.;
function drawCanvas(size1, size2, id)
{
var canvas = document.getElementById(id);
var context = canvas.getContext('2d');
context.beginPath();
context.arc(64, 64, 60, size1*Math.PI, size2*Math.PI, true);
context.lineWidth = 8;
context.lineCap = "round";
context.strokeStyle = '#c5731e';
context.stroke();
}
call it five times

Related

How to put a picture on Canvas

I have been trying to get an image to appear on my canvas that I have drawn shapes onto but I haven't been able to get it to work. There was a similar question on here but I tried doing it that way and it didn't work for me. I don't really care where on the canvas the picture appears as long as I can actually get it to. Also when I tried to get the image on the canvas, it turned the whole canvas yellow? I'm not sure why but the pedals on my flowers are yellow and I did nothing to change that part of my code.
window.onload = function() {
drawStar(100,100,5,30,15);
TruckParts();
Flower();
colorDrop();
Test1();
};
function drawStar(cx,cy,spikes,outerRadius,innerRadius){
// Get referene to canvas object
var canvas = document.getElementById("myCanvas");
// Get reference to canvas drawing context
var context = canvas.getContext("2d");
var rot=Math.PI/2*3;
var x=cx;
var y=cy;
var step=Math.PI/spikes;
context.beginPath();
context.moveTo(cx,cy-outerRadius)
for(i=0;i<spikes;i++){
x=cx+Math.cos(rot)*outerRadius;
y=cy+Math.sin(rot)*outerRadius;
context.lineTo(x,y)
rot+=step
x=cx+Math.cos(rot)*innerRadius;
y=cy+Math.sin(rot)*innerRadius;
context.lineTo(x,y)
rot+=step
}
context.lineTo(cx,cy-outerRadius);
context.closePath();
context.lineWidth=5;
context.strokeStyle='lightblue';
context.stroke();
context.fillStyle='grey';
context.fill();
}
function TruckParts(){
// Get referene to canvas object
var canvas = document.getElementById("myCanvas");
// Get reference to canvas drawing context
var context = canvas.getContext("2d");
// Draw truck body
context.beginPath();
context.moveTo(125, 450);
context.lineTo(200, 450);
context.lineTo(250, 500);
context.lineTo(290, 500);
context.lineTo(290, 550);
context.lineTo(25, 550);
context.lineTo(25, 500);
context.lineTo(250, 500);
context.lineTo(110, 550);
context.lineTo(200, 500);
context.lineTo(125, 500);
context.closePath();
context.strokeStyle = "darkred";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "red";
context.fill();
//Draw truck tire1
context.beginPath();
context.arc(100,560,30,0,2*Math.PI);
context.strokeStyle = "white";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "black";
context.fill();
//Draw truck tire 2
context.beginPath();
context.arc(230,560,30,0,2*Math.PI);
context.strokeStyle = "white";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "black";
context.fill();
};
//Draw Flower
function Flower(){
// Get referene to canvas object
var canvas = document.getElementById("myCanvas");
// Get reference to canvas drawing context
var context = canvas.getContext("2d");
//stem
context.beginPath();
context.moveTo(449, 500);
context.lineTo(449, 590);
context.lineTo(453, 590);
context.closePath();
context.fillStyle = "green";
context.fill();
//top left pedal
context.beginPath();
context.arc(436,490,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//bottom right pedal
context.beginPath();
context.arc(465,512,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//top right pedal
context.beginPath();
context.arc(465,490,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//bottom left pedal
context.beginPath();
context.arc(436,512,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//center
context.beginPath();
context.arc(450,500,17,0,2*Math.PI);
context.strokeStyle = "yellow";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "pink";
context.fill();
};
//colors array
let colors = [
{colorname: "Red", color: "red" },
{colorname: "Blue", color: "blue"},
{colorname: "Green", color: "green"},
{colorname: "Purple", color: "purple"},
{colorname: "Pink", color: "pink"},
];
function colorDrop () {
let locaRef = document.querySelector("#colorDrop");
let option1 = document.createElement("option");
option1.value = 0;
option1.text = colors[0].colorname;
let option2 = document.createElement("option");
option2.value = 1;
option2.text = colors[1].colorname;
let option3 = document.createElement("option");
option3.value = 2;
option3.text = colors[2].colorname;
let option4 = document.createElement("option");
option4.value = 3;
option4.text = colors[3].colorname;
let option5 = document.createElement("option");
option5.value = 4;
option5.text = colors[4].colorname;
locaRef.appendChild(option1);
locaRef.appendChild(option2);
locaRef.appendChild(option3);
locaRef.appendChild(option4);
locaRef.appendChild(option5);
}
function handleDropdown(){
//convert index to number
let index = document.getElementById("colorDrop").value;
let setColor = colors[index].color;
};
//similar function that does not work for me
function Test1() {
let context = document.getElementById('test1');
if (context.getContext) {
context = context.getContext('2d');
//Loading of the home test image - img1
let img1 = new Image();
//drawing of the test image - img1
img1.onload = function () {
//draw background image
context.drawImage(img1, 0, 0);
//draw a box over the top
context.fillStyle = "rgba(200, 0, 0, 0.5)";
context.fillRect(0, 0, 500, 500);
};
img1.src = "puppy.jpg";
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel= 'stylesheet' href="p3.css">
<script src="p3.js"> </script>
<style>canvas { border: 1px solid black; }</style>
</header>
<body>
<canvas width= "1000" height= "600" id= "myCanvas">
</canvas>
</body>
</html>
<header>
</header>
<nav>
</nav>
<main>
Enter text:
<input type="text">
<button type= "button">Press Button</button>
<select id="colorDrop" onchange="handleDropdown()">
<option value="">Select a Color</option>
</select>
</main>
<footer>
</footer>
</body>
</html>
The following line in the Test1 function is preventing your code from working...
let context = document.getElementById('test1');
Needs to be changed of course to...
let context = document.getElementById('myCanvas');
When I make this change your code works, the image I specify for img1.src is displayed top-left of the canvas, and a filled rectangle of 50% alpha also appears.

How to make line width for custom line in html5 canvas

I want to change a line width but why all lines width in canvas is also changed?
Bellow is my code snippet
let c_canvas = document.getElementById("c");
let context = c_canvas.getContext("2d");
let gradientFill = context.createLinearGradient(400, 0, 95, 305);
gradientFill.addColorStop(0, "rgba(195, 42, 28, 1.000)");
gradientFill.addColorStop(0.6, "rgba(252, 239, 55, 1.000)");
gradientFill.addColorStop(1, "rgba(12, 151, 206, 1.000)");
context.fillStyle = gradientFill;
context.fillRect(0, 0, 500, 500);
context.beginPath();
for (let x = 0.5; x <= 501; x += 100) {
context.moveTo(x, 0);
context.lineTo(x, 500);
}
for (let y = 0.5; y <= 501; y += 100) {
context.moveTo(0, y);
context.lineTo(500, y);
}
context.lineWidth = 1;
context.stroke(); // Draw it
let frectx = 100;
let frecty = 450;
let lrectx = 250;
let lrecty = 340;
let radius = 15; // for example
let font = "bold " + radius + "px serif";
let text = "1";
let rand =[];
for(let i=0; i<5; i++)
{
rand[i] = Math.floor((Math.random() * 6) + 1);
}
rand.forEach(function(entry,i) {
text = i+1;
frectx = entry*70;
frecty = Math.floor((Math.random() * 9) + 1)*50;
context.moveTo(frectx, frecty);
context.lineTo(lrectx, lrecty);
context.lineWidth = 8;
context.strokeStyle = "#ddd";
context.stroke();
context.fillStyle = "white";
context.beginPath();
context.arc(frectx, frecty, 10, 0, 2 * Math.PI);
context.stroke();
context.closePath();
context.fill();
context.fillStyle = "black"; // font color to write the text with
context.font = font;
context.textBaseline = "top";
context.fillText(text, frectx - radius / 4, frecty - radius / 2);
context.fillStyle = "white";
context.beginPath();
context.arc(lrectx, lrecty, 10, 0, 2 * Math.PI);
context.stroke();
context.closePath();
context.fill();
context.fillStyle = "black"; // font color to write the text with
context.font = font;
context.textBaseline = "top";
context.fillText(text, lrectx - radius / 4, lrecty - radius / 2);
})
<canvas id="c" width="501px" height="501px"></canvas>
or you can see in jsfiddle:
https://jsfiddle.net/dyaskur/t4fgLs73/
How to only change width in that lines inside the box?
My second question is how to make my line and circle transform to glow/change color when i hover on it?
A context.beginPath() is missing between
context.lineWidth = 1;
context.stroke(); // Draw it
and
context.lineTo(lrectx, lrecty);
context.lineWidth = 8;
context.strokeStyle = "#ddd";
context.stroke();
Without the beginPath call you are simply re-stroking all or the paths and subpaths already defined with the new stroke style and width.
The general answer to the second part of your question is that you don't get to do this.
Painting a canvas is equivalent to drawing an image. You can work out where the mouse is over the image, but you would then need to work out (in your program) if the mouse is over some pixels you want to change and redraw the canvas if it is.
If you want to use CSS :hover pseudo classes to change presentation you will need to construct the source code of an SVG element for the graphic, create the element from the source code generated, and supply appropriate CSS for the SVG element's child nodes that will be affected by mouse position.

Changing color randomly Javascript

Heys guys,
I am testing some stuff out with the native accelometer on my android phone, I want to draw rectangles, which works but I want them to be a different color everytime one is drawn.
Thank you in advance :)
function onSuccess(acceleration) {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.width = window.innerWidth;
context.height = window.innerHeight;
context.save();
context.beginPath();
context.rect(acceleration.x*10+150, acceleration.y*10+100, acceleration.z*10, acceleration.y*10);
context.fillStyle = '#FF0000';
context.fill();
context.lineWidth = 3;
context.strokeStyle = 'black';
context.stroke();
context.restore();
}
function onError() {
alert('onError!');
}
fillStyle should have random color instead of '#FF0000'
You can use random color by Paul Irish
function onSuccess(acceleration) {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.width = window.innerWidth;
context.height = window.innerHeight;
context.save();
context.beginPath();
context.rect(acceleration.x * 10 + 150, acceleration.y * 10 + 100, acceleration.z * 10, acceleration.y * 10);
context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
context.fill();
context.lineWidth = 3;
context.strokeStyle = 'black';
context.stroke();
context.restore();
}
function onError() {
alert('onError!');
}
Edit: As suggested by Morten Olsen, provided approach may fail sometimes, You can refer this SO answer
Just take a function for it.
function randomColor() {
var c = "#";
for (var i = 0; i < 6; i++) {
c += (Math.random() * 16 | 0).toString(16);
}
return c;
}
var a = document.getElementById("id1").style;
a.color = randomColor();
<h1 id="id1">stackoverflow</h1>
Assign a random color to fillStyle.
context.fillStyle = "#"+((1<<24)*Math.random()|0).toString(16);
From this post
Use this:
'#'+Math.floor(Math.random()*16777215).toString(16);
For more information: http://www.paulirish.com/2009/random-hex-color-code-snippets/

Trying to make every other house's door green

What my task is, is to draw a house then use a loop (at the bottom) to fill the canvas with the houses instead of manually placing each one.
Well I'm trying to work how to make every other house's door green. I've been trying to hack away at code for awhile now but I cannot figure it out.
I know all my house pieces should be in functions and what not but that is a later task for the work I am doing! Here's my code:
//Check to see if the browser supports
//the addEventListener function
if(window.addEventListener)
{
window.addEventListener
(
'load', //this is the load event
onLoad, //this is the evemnt handler we going to write
false //useCapture boolen value
);
}
//the window load event handler
function onLoad()
{
var canvas;
var context;
//this function will intialise our variables
function initialise()
{
// Fune the canvas element using its id attribute.
canvas = document.getElementById('canvas');
//if it couldn't be found
if (!canvas)
{
//make a message bok appear with an error message
alert('Error: i cannot find this "canvas" of which you speak. Please re-evaluate your life choices.');
return;
}
//check if there is any getContext function
if(!canvas.getContext)
{
alert('Error no cavnas.getContext could be found');
return;
}
//get the 2D canvas context.
context = canvas.getContext('2d');
if(!context)
{
alert('Error failed to getCOntext');
return;
}
canvas.addEventListener("mousedown", getPosition, false);
}
// this is a little help tool for me as i'm awful at working out co-ordinates
function getPosition(e)
{
var x = e.x;
var y = e.y;
x -=canvas.offsetLeft;
y -=canvas.offsetTop;
alert("x:" +x+ "y:"+y);
}
//this function will draw on the canvas for me!
function draw()
{
context.fillStyle = 'grey';
context.fillRect(0, 0, canvas.width, canvas.height);
}
// pX and pY are the parameters are going to be used so that the inside of the house body becomes the drawing canvas.
function drawHouse(pX ,pY)
{
//body
context.beginPath();
context.fillStyle = '#ffffff';
context.strokeStyle = "black";
context.lineWidth = "5";
context.rect(pX,pY, 160,110);
context.closePath();
context.fill();
context.stroke();
//roof
context.beginPath();
context.fillStyle = "red";
context.moveTo(pX,pY-1);;
context.lineTo(pX+80, pY-95);
context.lineTo(pX+160, pY-1);
context.closePath();
context.fill();
context.stroke();
//door
context.beginPath();
context.fillStyle = "green";
context.fillSStyle = "red";
context.strokeStyle = "black";
context.rect(pX+55,pY+30, 50, 80);
context.fill();
context.stroke();
//handle
var radius = 5;
context.beginPath();
context.arc(pX+93, pY+75, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'purple';
context.fill();
context.lineWidth = 3;
context.strokeStyle = 'black';
context.stroke();
//window Left
context.beginPath();
context.fillStyle = 'blue';
context.strokeStyle = "black";
context.rect(pX+12,pY+30, 30, 60);
context.fill();
context.stroke();
//window Filler left vertically
context.beginPath();
context.moveTo(pX+26.5,pY+30);
context.lineTo(pX+26.5, pY+90);
context.fill();
context.stroke();
//Window filler left horizontally
context.beginPath();
context.moveTo(pX+41, pY+60);
context.lineTo(pX+11,pY+60);
context.fill();
context.stroke();
//Window Right
context.beginPath();
context.fillStyle = 'blue';
context.strokeStyle = "black";
context.rect(pX+117,pY+30, 30, 60);
context.fill();
context.stroke();
//window filler right vertically
context.beginPath();
context.moveTo(pX+131.5,pY+30);
context.lineTo(pX+131.5, pY+90);
context.fill();
context.stroke();
//window Filler right horizontally
context.beginPath();
context.moveTo(pX+147, pY+60);
context.lineTo(pX+117,pY+60);
context.fill();
context.stroke();
}
initialise();
draw();
for(var i=0; i < 5; i++)
{
var pX=0+160*i;
for(var b=0; b < 5; b++)
{
var pY=100+210*b;
drawHouse(pX,pY);
}
}
}
Add a parameter to drawHouse:
function drawHouse(pX, pY, drawGreen) {
// ...
if (drawGreen)
context.fillStyle = "green";
else
context.fillSStyle = "red";
// ...
}
And then, pass it accordingly. For example:
// before your loop
var paintGreen = false;
// In the inner for
var pY=100+210*b;
drawHouse(pX,pY,paintGreen);
paintGreen = !paintGreen; // alternate

Is there a way to tile a background image over a canvas path?

For example, I have a canvas in a page with some kind of a path. It is created by javascript this way:
var context = $('#some_canvas').getContext('2d');
context.beginPath();
context.lineWidth = 5;
context.strokeStyle = '#000000';
context.moveTo(0, 0);
context.lineTo(100, 100);
context.stroke();
Is there a way to make the path that appears after this command to have some tiled background image?
I believe you're looking for the createPattern() method:
var pattern = new Image;
pattern.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAARCAIAAABbzbuTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAZtJREFUeNqMUs+rAVEUvjNG2MhClOUsppSEjbWFpOwtMIv5B2ZhZqkkZKkpe+XPYKtsbSxsZIGaQpgi4r3Pu5p3eV45dW/nnPt959zzg5RKpU6n8/WxkHq9LghCs9n8lICjKAohpFwuf0LgcCzLSqfTo9FIVVVd10He7XbX6/V8Pu/3e47jcB+Px0AgkEqlCOXNZjNJkgB1/wg+6XA4ACXPomkasXM1Gg3yj4AZi8WAHgwGgu1dLpcvOKRKJBLZbDaTyYDgdDrvXjtDLpd7yT6dTv8WzdNnaPP53A6Mezgc+v3+N/+jvO12GwwGqQfFYJRQksnker1+MwfIZDLxeDwA+Xy+xWIBT6VSgYk+Hg4HlvAoerVaodNQ8vl8KBSCUqvVAG2326g4EolsNhuYGNQjQ6/XAwh9GI/HbDxZltn/o2OPDBgctaPRKIsQRZEqWJxisXg3aaRCoQBvv99nw59Op3A4DH+1Wu12u09FYwh4w/6wBGwUOhuPx6FfLpfb7fZbtGEYpmnyPM/+x+v1tlotl8sFHdtFnd8CDACAg6Y2weEZQQAAAABJRU5ErkJggg==";
pattern.onload = function () {
var context = $('#some_canvas').getContext('2d');
context.beginPath();
context.lineWidth = 16;
context.strokeStyle = context.createPattern(pattern, 'repeat');
context.moveTo(0, 0);
context.lineTo(150, 150);
context.stroke();
};

Categories