I have a <canvas/>, and a shape rendering on it. I am trying to change the shape's coordinates on keypress, but am having no luck.
Here's my source:
var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var radius = 35;
var xPos = 0;
context.beginPath();
context.arc(xPos, 0, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
$(document).keypress(function(event) {
if (event.which == 100) {
xPos++;
}
});
Another issue I am having is figuring out what keys are what number? Is there a chart somewhere? I saw two conflicting values on different sites.
The following article http://atomicrobotdesign.com/blog/htmlcss/move-objects-around-the-canvas-using-the-keyboard-and-jquery/ goes into great detail using jQuery to reference a Canvas object and then manipulate that object.
It also examines how to adjust the position of that Canvas object in response to keystrokes entered by the user.
Hope that helps.
Related
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've created a grid of several distorted rectangles made with Bezier curves. Each rectangle has its own color on the picture.
Let's say, I want to add hover effect for each of these rectangles, therefore I need to know its dimensions. Since I can fill or stroke the figure I assume that there is some way to get them, but I'm not sure.
Here is the example of the rectangles:
So the question is, is there some method in the canvas API with which I can achieve the desired effect?
Yes you can use isPointInPath(Path2D, x, y) method.
Note that if you don't use the Path2D object, you can also call it just with isPointInPath(x, y), but then it will check on the currently being drawn path (declared with beginPath()).
var ctx = canvas.getContext('2d');
var myPath = new Path2D();
myPath.bezierCurveTo(50, 100, 180, 10, 20, 10);
myPath.lineTo(50, 100);
function draw(hover) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = hover ? 'red' : 'green';
ctx.fill(myPath);
}
canvas.onmousemove = function(e) {
var x = e.clientX - canvas.offsetLeft,
y = e.clientY - canvas.offsetTop;
var hover = ctx.isPointInPath(myPath, x, y)
draw(hover)
};
draw();
<canvas id="canvas"></canvas>
How to draw outer and inner border around any canvas shape?
I'm drawing several stroke-only shapes on an html canvas, and I would like to draw an inner and outer border around them.
draft example:
Is there a generic why to do it for any shape (assuming it's a closed stroke-only shape)?
Two methods
There is no inbuilt way to do this and there are two programmatic ways that I use. The first is complicated and involves expanding and contracting the path then drawing along that path. This works for most situations but will fail in complex situation, and the solution has many variables and options to account for these complications and how to handle them.
The better of the two
The second and easiest way that I present below is by using the ctx.globalCompositeOperation setting to mask out what you want drawn or not. As the stroke is drawn along the center and the fill fills up to the center you can draw the stroke at twice the desired width and then either mask in or mask out the inner or outer part.
This does become problematic when you start to create very complex images as the masking (Global Composite Operation) will interfere with what has already been drawn.
To simplify the process you can create a second canvas the same size as the original as a scratch space. You can then draw the shape on he scratch canvas do the masking and then draw the scratch canvas onto the working one.
Though this method is not as fast as computing the expanded or shrunk path, it does not suffer from the ambiguities faced by moving points in the path. Nor does this method create the lines with the correct line join or mitering for the inside or outside edges, for that you must use a the other method. For most purposes the masking it is a good solution.
Below is a demo of the masking method to draw an inner or outer path. If you modify the mask by including drawing a stroke along with the fill you can also set an offset so that the outline or inline will be offset by a number of pixels. I have left that for you. (hint add stroke and set the line width to twice the offset distance when drawing the mask).
var demo = function(){
/** fullScreenCanvas.js begin **/
var canvas = ( function () {
canvas = document.getElementById("canv");
if(canvas !== null){
document.body.removeChild(canvas);
}
// creates a blank image with 2d context
canvas = document.createElement("canvas");
canvas.id = "canv";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
canvas.style.zIndex = 1000;
canvas.ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
return canvas;
})();
var ctx = canvas.ctx;
/** fullScreenCanvas.js end **/
/** CreateImage.js begin **/
// creates a blank image with 2d context
var createImage = function(w,h){
var image = document.createElement("canvas");
image.width = w;
image.height =h;
image.ctx = image.getContext("2d");
return image;
}
/** CreateImage.js end **/
// define a shape for demo
var shape = [0.1,0.1,0.9,0.1,0.5,0.5,0.8,0.9,0.1,0.9];
// draws the shape as a stroke
var strokeShape = function (ctx) {
var w, h, i;
w = canvas.width;
h = canvas.height;
ctx.beginPath();
ctx.moveTo(shape[0] *w, shape[1] *h)
for (i = 2; i < shape.length; i += 2) {
ctx.lineTo(shape[i] * w, shape[i + 1] * h);
}
ctx.closePath();
ctx.stroke();
}
// draws the shape as filled
var fillShape = function (ctx) {
var w, h, i;
w = canvas.width;
h = canvas.height;
ctx.beginPath();
ctx.moveTo(shape[0] * w,shape[1] * h)
for (i = 2; i < shape.length; i += 2) {
ctx.lineTo(shape[i]*w,shape[i+1]*h);
}
ctx.closePath();
ctx.fill();
}
var drawInOutStroke = function(width,style,where){
// clear the workspace
workCtx.ctx.globalCompositeOperation ="source-over";
workCtx.ctx.clearRect(0, 0, workCtx.width, workCtx.height);
// set the width to double
workCtx.ctx.lineWidth = width*2;
workCtx.ctx.strokeStyle = style;
// fill colour does not matter here as its not seen
workCtx.ctx.fillStyle = "white";
// can use any join type
workCtx.ctx.lineJoin = "round";
// draw the shape outline at double width
strokeShape(workCtx.ctx);
// set comp to in.
// in means leave only pixel that are both in the source and destination
if (where.toLowerCase() === "in") {
workCtx.ctx.globalCompositeOperation ="destination-in";
} else {
// out means only pixels on the destination that are not part of the source
workCtx.ctx.globalCompositeOperation ="destination-out";
}
fillShape(workCtx.ctx);
ctx.drawImage(workCtx, 0, 0);
}
// clear in case of resize
ctx.globalCompositeOperation ="source-over";
ctx.clearRect(0,0,canvas.width,canvas.height);
// create the workspace canvas
var workCtx = createImage(canvas.width, canvas.height);
// draw the outer stroke
drawInOutStroke((canvas.width + canvas.height) / 45, "black", "out");
// draw the inner stroke
drawInOutStroke((canvas.width + canvas.height) / 45, "red", "in");
// draw the shape outline just to highlight the effect
ctx.strokeStyle = "white";
ctx.lineJoin = "round";
ctx.lineWidth = (canvas.width + canvas.height) / 140;
strokeShape(ctx);
};
// run the demo
demo();
// incase fullscreen redraw it all
window.addEventListener("resize",demo)
Hi i have a ball dropping in a html5 canvas, i would like to have a counter that displays how far the ball is dropping.
var ball = new Kinetic.Shape(function(){
var context = this.getContext();
context.beginPath();
context.arc(0, 0, radius, 0, 2 * Math.PI, false);
context.fillStyle = "black";
context.fill();
});
Someone any idea how to do this ?
Your shape has a position on the canvas, you should clearly define it just to be sure.
But if you want to count how your object moves on the screen you can just do:
ball.getPosition();
This will return you a point in the form of
{x: number, y: number}
you can save the individual x,y values like so:
var xPosition = ball.getPosition().x;
var yPosition = ball.getPosition().y;
you can save those positions in your animation and do a sum of how much the ball moved.
I am working on a HTML5 Project.There is a drawing graphics API to draw Rectangle (fillRectStrokeRect).But how can i draw a SQUARE. I have tried the following way to draw it
CODE
getMouse(e);
x2=mx; y2=my;
var width=endX-startX;
var height=endY-startY;
annCanvasContext.beginPath();
annCanvasContext.lineWidth=borderWidth;
var centerX=width/2;
var centerY=width/2;
var radius=width/2;
annCanvasContext.arc(centerX+5, centerY+5, radius, 0, 2 * Math.PI, false);
annCanvasContext.stroke();
Use fillRect or strokeRect with the width and height being equal.
var x = 0, y = 0,
side = 10;
ctx.fillRect(x, y, side, side);
Demo
As you say in the comments, if you want to fit the largest square in a circle, it's more Math related than about code. I'll trying explaining it to you, but you'll probably find better, more visual explanations elsewhere on the Internet.
Draw the diameter of the circle in a way that it divides your square into two equal parts. Now one part is a right angled triangle, which has two of its sides equal. We know the diameter. Using the Pythogorean theorem, you get this equation:
side^2 + side^2 = diameter^2.
Let's find the side now.
2(side^2) = diameter^2
side^2 = (diameter^2)/2
side = Math.sqrt( (diameter^2)/2 )
Now, to turn this into code.
var ctx = document.getElementById('canvas').getContext('2d'),
radius = 20;
ctx.canvas.addEventListener('click', function (e){
ctx.fillStyle = 'black';
ctx.arc(e.pageX, e.pageY, radius, 0, Math.PI*2, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'red';
var diameter = radius * 2;
var side = Math.sqrt( (diameter * diameter)/2 );
ctx.fillRect(e.pageX - side/2, e.pageY - side/2, side, side);
ctx.closePath();
}, false);
This would draw a square inside a circle wherever you click on the canvas.
Demo