For a javascript animation, I am trying to create buttons with the numbers 1-9 on them. Right now my javascript for the number 1 looks like:
that1 = { thisx : 120, thisy: H-400, thisnumber= "1",
draw: function() {
var keywidth = 100;
var keyheight = 150 ;
var x = this.thisx;
var y = this.thisy;
var cornercut = 5;
ctx.beginPath();
//drawing the key
ctx.moveTo(x, y+cornercut);
ctx.quadraticCurveTo(x,y, x+cornercut, y);
ctx.lineTo(x+keywidth-cornercut, y);
ctx.quadraticCurveTo(x+keywidth, y, x+keywidth, y+cornercut);
ctx.lineTo(x+keywidth, y+keyheight-cornercut);
ctx.quadraticCurveTo(x+keywidth, y+keyheight, x+keywidth-cornercut, y+keyheight);
ctx.lineTo(x+cornercut, y+keyheight);
ctx.quadraticCurveTo(x, y+keyheight, x, y+keyheight-cornercut);
ctx.lineTo(x, y+cornercut);
ctx.closePath();
ctx.stroke();
ctx.fillText(this.thisnumber, x+.5*keywidth,y+.8*keyheight);
},
highlight: function() {
ctx.fillStyle="red";
ctx.fill();
}
} ;
I could just copy this to create this2, this3, this4, this5, etc., but I feel like there is an easier way. Can anyone help? I am using JS because I believe it will be the easiest way to control these objects using animation, but please let me know if you have another suggestion.
You could change the values of thisx and thisy and simply call the draw function again, but the code would probably be more elegant if you simply passed in the values as arguments to a draw function.
Related
I'm trying to draw a circle in the canvas in javascript but it's not working and I'm not getting an error. I've done it before and it usually works, but for some reason now it isn't. Any help would be highly appreciated.
// VARIABLES
var x = 100 ;
var y = 100;
var r = 50;
var c = 272;
var a = 0.9;
// EXECUTABLE CODE
circle();
// FUNCTION
function circle(x,y,r,c,a){
ctx.beginPath();
ctx.arc(x,y,r,0,Math.PI*2);
ctx.fillStyle = "hsl("+c+", 100%, 50%,"+a+")";
ctx.fill();
}
The reason why it is not working is because you did not pass in the arguments x,y,r,c,a when invoking the circle function. So, do this circle(x,y,r,c,a) and it should work for you.
so I am trying to make thisgame called GO and I need to place circles in the edges like this. I've made the grid and now need to place the circles in there. I 'v tried different things like using the arc in canvas with mouse position and placing it but it isn't working something else I tried is to make an array that checks where the lines cross but it still didn't do anything. but i may have done it wrong. I'm not sure what's wrong so hope you guys could help me find a way to place the circles on the board every time I click the mouse. I've deleted the things that didn't work and this is my code now:
const canvas = document.getElementById("myCanvas")
const ctx = canvas.getContext("2d")
//canvas.style.border = "1px solid black"
let w = ctx.canvas.width
let h = ctx.canvas.height
goBoard = []
goCheckBoard = []
function drawGrid(w, h) {
for (x = 0; x <= w; x += 40) {
for (y = 0; y <= h; y += 40) {
ctx.moveTo(x, 0);
ctx.lineTo(x, h);
ctx.stroke();
ctx.moveTo(0, y);
ctx.lineTo(w, y);
ctx.stroke();
}
}
}
drawGrid(400, 400)
this just makes the grid
one example i've tried is this:
mouseClicked = function () {
ctx.beginPath()
ctx.strokeStyle = "black"
ctx.ellipse(mouseX, mouseY, 20, 20);
ctx.stroke()
};
another:
function rtn(n, r){
return Math.round(n/r)*r;
}
canvas.onclick = function(event){
ellipse(rtn(event.clientX, 40), rtn(event.clientY, 40), 180, 180);
};
im not sure if that is the correct way to do it
maybe make an array of all the possible places to place the circle but im not sure how
here is a fiddle if you want to test it out https://jsfiddle.net/pwe0vx7o/
you first need to change the ellipse(...) to ctx.ellipse(...), because ellipse isn't a global function, but a metod of the CanvasRenderingContext2D.
Through the docs I also found that this function takes 7 arguments so added ones for radiusX, radiusY, rotation, startAngle, endAngle.
Here is also a fiddle for the finished result: https://jsfiddle.net/c6udn9gf/8/
This will get you close, but you need to figure out something with your rounding function.
canvas.onclick = function (event) {
ctx.beginPath();
const x = rtn(event.clientX, 40);
const y = rtn(event.clientY, 40);
ctx.ellipse(x - 20, y - 20, 10, 10, 0, 0, 360);
ctx.fill();
};
I'm trying to execute a function 'draw' when a button is clicked (button id is also draw). When clicking the button the function runs successfully, however the repeated iterations do not run. I've therefore narrowed the issue to the setTimeout. I get the following message "draw is not a function". This is confusing because it definitely IS a function. Any help is appreciated. Thanks.
var draw1 = document.getElementById('draw');
draw1.addEventListener('click',draw);
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 0;
var y = 0;
function draw(aaa,bbb){
ctx.save();//save the cavas state if required
ctx.clearRect(0,0,100,100)//clear canvas for redrawing
ctx.fillStyle = 'rgba(0,200,0,1)';//style a green box
ctx.fillRect (x, 20, 50, 50);//draw the rectangle
ctx.restore();//restore the canvas state if saved
x += 5;//increment the x position by some numeric value
console.log(x);
console.log(y);
var loopTimer = setTimeout('draw(' + x +','+ 0 +')',200);
}
Don't use strings for function call. It is a really bad practice.
Change it to an anonymous function:
var loopTimer = setTimeout(function() {
draw(x, 0);
}, 200);
As long as your x and y are global and you don't use arguments, you can remove them from your draw method and call it even simpler, without closures:
function draw(){
ctx.save();//save the cavas state if required
ctx.clearRect(0,0,100,100)//clear canvas for redrawing
ctx.fillStyle = 'rgba(0,200,0,1)';//style a green box
ctx.fillRect (x, 20, 50, 50);//draw the rectangle
ctx.restore();//restore the canvas state if saved
x += 5;//increment the x position by some numeric value
console.log(x);
console.log(y);
var loopTimer = setTimeout(draw, 200);
}
I have this jsfiddle which creates a pattern of 4 points.
What I want is for it to continuously draw the projected line until the user click for point B, then point C and D.
function draw(){
//
ctx.clearRect(0,0,cw,ch);
// draw connecting lines
for(var i=0;i<connectors.length;i++){
var c=connectors[i];
var s=anchors[c.start];
var e=anchors[c.end];
ctx.beginPath();
ctx.moveTo(s.x,s.y);
ctx.lineTo(e.x,e.y);
ctx.stroke();
}
// draw circles
for(var i=0;i<anchors.length;i++){
ctx.beginPath();
ctx.arc(anchors[i].x,anchors[i].y,radius,0,Math.PI*2);
ctx.fill();
ctx.fillText(anchors[i].label,anchors[i].x-5,anchors[i].y-15);
}
}
Ok so, basically you need your connector adding function to be slightly smarter, so we can make this work like in this fiddle
(You were adding way to many connectors, and it stopped at length over 7, this fixes both those)
if(draggingIndex==-1 && fullDrag == null){
addAnchor(startX,startY);
var al = anchors.length-1;
var almod4 = al%4;
if(almod4==1){
connectors.push({start:al-1,end:al});
}
if(almod4==2){
connectors.push({start:al-2,end:al});
connectors.push({start:al-1,end:al});
}
if(almod4==3){
connectors.push({start:al-2,end:al});
connectors.push({start:al-1,end:al});
}
draw();
}
As you can see, based on the value of anchors.length-1 modular 4, we know if we need to draw 1 or 2 lines. In our draw function we can then add:
if (anchors.length>0 && anchors.length%4>0){
ctx.strokeStyle='gray';
var al = anchors.length-1;
var almod4 = al%4;
if (almod4==1 || almod4==2){
//draw extra line
ctx.beginPath();
ctx.moveTo(anchors[al-1].x,anchors[al-1].y);
ctx.lineTo(mouseX,mouseY);
ctx.stroke();
}
ctx.beginPath();
ctx.moveTo(anchors[al].x,anchors[al].y);
ctx.lineTo(mouseX,mouseY);
ctx.stroke();
}
Note that instead of checking for almod4 being 2 or 3, we check for 1 and 2, because that means we're in the process of adding 2 or 3.
Now all you need to do is tell it to draw at every mouseover, and voila, preview lines.
I want to be able to draw an array of balls, I can push the balls into the array (when clicking the canvas).
I can draw 1 of the balls on the canvas if I create it with ball = new Ball, but as soon as I try to draw from inside the array it breaks.
I draw inside a for loop with balls[i].draw
Here's a jsFiddle.
And here's the relevant code:
function init(){
defaultBall();
for(i=0;i<balls.length;i++){
balls[i].draw;
}
ball.draw();
}
function Ball(X, Y, Radius, Color){
this.X = X || 0;
this.Y = Y || 0;
this.radius = 5;
this.color = Color;
}
Ball.prototype.draw = function(){
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.X, this.Y, this.radius, 10, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
var balls = [];
function defaultBall(){
addBall(new Ball(50, 50, 5, '#6B7E00'));
addBall(new Ball(150, 50, 5, '#6B7E00'));
}
function addBall(ball){
balls.push(ball);
}
var ball = new Ball(50, 50, 5, '#6B7E00');
How should I formulate the loop to be able to draw the balls?
Help appriciated.
Maybe
balls[i].draw;
should be
balls[i].draw();
on line 4
Your init method isn't getting called again. If you change
function addBall(ball){
balls.push(ball);
ball.draw();
}
to
function addBall(ball){
balls.push(ball);
}
you'll see the new balls. You need to have some sort of mechanism that calls init (aka draw) again.
And as Frits pointed out you will need to use draw() instead of draw.
Your code runs just fine, it is just that there is a small error with your balls loop.
defaultBall();
for(i=0;i<balls.length;i++){
balls[i].draw;
}
ball.draw();
You forgot to use the parenthesis to call the draw method when looping through your balls. The fix is simple:
defaultBall();
for(i=0;i<balls.length;i++){
balls[i].draw();
}
ball.draw();
Note that now your balls will show up as intended. When the fiddle is edited with this new fix for looping through the balls you can see two green balls show up.