I want to set background image to my rectangle in the canvas.
So far i've done this.
var img = new Image()
img.src = //Source of an image.
var newPattern = ctx.createPattern(img, "no-repeat");
ctx.fillStyle = newPattern;
And it works, but the problem is, that it applies the image to the canvas, not to the rectangle.
And whenever I change the position of the rectangle, the image remains in the same position.
Can anybody suggest how to fix this, so the image'd be attached to the rectangle.
If you want to only draw the image within a specified rectangle you can do something like this.
context.rect(x, y, width, height);
context.clip();
context.drawImage(img, 0, 0);
This creates a rectangle at (x, y) with size (width, height) which is used for all future calls to the context. If you want to stop the clipping you will need to add a
context.save();
before the code above and then a
context.restore();
after you have drawn the image.
JSFiddle
Edit: updated to rect
Related
Say I have drawn a circle on a canvas that has something else drawn on it that stops me from clearing the canvas - due to the other element being randomly generated
var circleX = 50;
var circleY = 10;
var moveCircX = 2;
var moveCircY = 3;
function createCirc(){
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(circleX, circleY, 10, 0, Math.PI*2, true);
ctx.fill();
}
function circMove(){
circleY = (circleY + circMoveY)
//then validation to stop it from being drawn of the canvas
So what I'm trying to do is move the circle but clear the previous drawn circle from the canvas. So is there a solution to clearing the circle or would it be easier to create a sprite that replicates the circle?
Since your background isn't changing, the simplest strategy is to copy the background before you first draw your circle, then draw your circle. When you're moving, redraw that part of the background from the copy you kept, then draw your circle in the new place.
An efficient way to do that is to use getImageData and putImageData.
So, (my javascript is rusty, so this may not be perfect. Feel free to correct any mistakes), before the first time you createCirc, simply do:
imageData = ctx.getImageData(0,0, ctx.canvas.width, ctx.canvas.height)
And, in your circMove function, before you move and redraw the circle, you want:
ctx.putImageData(imageData, circleX, circleY, circleX, circleY, 2*circle_radius, 2*circle_radius)
(You don't define circle_radius, but I'm sure you must have a similar value. I'm using 2x the radius to presumably be the size of the image that is drawn.)
I am trying to make a 2d top-down game in Javascript at the moment. I've currently got a day/night system working where a black rectangle gradually becomes more opaque (as the day goes on) before it finally is fully opaque, simulating the peak of the night where the player can not see.
I want to implement an artificial light system, where the player could use a torch that will illuminate a small area in-front of them. However, my problem is that I don't seem to be able to find a way to 'cut out' a shape from my opaque rectangle. By cutting out a shape, it would look like the player has a torch.
Please find an example mock-up image I made below to show what I mean.
http://i.imgur.com/VqnTwoR.png
Obviously the shape shouldn't be as roughly drawn as that :)
Thanks for your time,
Cam
EDIT: The code used to draw the rectangle is as follows:
context.fillStyle = "#000033";
context.globalAlpha = checkLight(gameData.worldData.time);
context.fillRect(0, 0, 512, 480);
//This is where you have to add the cut out triangles for light!
context.stroke();
Instead of drawing a rectangle over the scene to darken it when the "light" is on, instead draw an image with the "lit" area completely transparent and the rest of the "dark" area more opaque.
One way is to use declare a triangular clipping area and draw your revealed scene. The scene would display only inside the defined clipping area.
Example code and a Demo:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var offset = 50;
var img = new Image();
img.onload = function() {
knockoutAndRefill(50,100,300,50,75,350);
};
img.src = 'http://guideimg.alibaba.com/images/trip/1/03/18/7/landscape-arch_68367.jpg';
function knockoutAndRefill(x0,y0,x1,y1,x2,y2){
context.save();
context.fillStyle='black';
context.fillRect(0,0,canvas.width,canvas.height);
context.beginPath();
context.moveTo(x0,y0);
context.lineTo(x1,y1);
context.lineTo(x2,y2);
context.closePath();
context.clip();
context.drawImage(img,0,0);
context.restore();
}
<canvas id=myCanvas width=500 height=400>
after trying a few ways to preserve a background under a canvas drawing a moving rectangle (animation code not reproduced), here is my best try :
canvas {background-image:url('background.png');}
var x,y, pixels;
function draw() {
if(pixels) {
context.putImageData(pixels,x,y);
}
x = //calculate new X
y = //calculate new Y
pixels = context.getImageData(x, y, 10, 10);
context.fillStyle = 'red';
context.fillRect(x, y, 10, 10);
}
My first question is : why won't replacing the first two lines of draw() with :
context.fillStyle = 'rgba(10,10,10,0)';
context.fillRect(x,y,10,10);
work to clear the previously drawn pixels?
And my second question is : is there really no better way than get and putImageData(), which are very labor-intensive?
EDIT: in particular is there a div containing the background image trick that would maybe work without the get and putImageData calls?
Thanks!
By default, whatever you draw gets drawn on top of each other, instead of being replaced.
Use context.clearRect(x,y,10,10); instead.
There is also the context.globalCompositeOperation property, which could be set to "destination-out" before using fillRect .. but you're better off with clearRect.
I'm trying to draw a circle and then have an image follow the circle around. Later I want to rotate and move the image around with respect to the circle drawn. The problem I'm facing is that when I try to rotate the image it won't rotate. It also doesn't show me an error in the console. I have functions allowing me to move the circle around and the image moves with it, I just can't seem to rotate the image.
Here is the code:
draw: function(){
//draw self on canvas;
//intended only to be called from update, should never
//need to be deliberately called
ctx = this.context;
ctx.save();
ctx.fillStyle="#000000";
ctx.beginPath();
//void arc(double x, double y,
// double radius, double startAngle, double endAngle,
// optional boolean anticlockwise = false);
ctx.arc(this.x,this.y,this.size,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
//ctx.translate(this.x, this.y);
ctx.rotate(this.imgAngle);
//draw the hammer
ctx.drawImage(this.hammer,this.hammerX,this.hammerY,100,100)
ctx.rotate(Math.PI/2);
ctx.restore();
},
Live Demo
Try changing your code to the following. You need to perform the rotation before drawing. You can translate the canvas to the entities position and then draw the image at x:0,y:0 to get the effect you desire. Note I did 0-50,0-50 because that puts the point of origin in the center since the width and height are 100. Meaning your image will rotate around its center rather than around its corner.
//draw the hammer
ctx.translate(this.hammerX, this.hammerY);
ctx.rotate(this.imgAngle);
ctx.drawImage(this.hammer,0-50,0-50,100,100);
The rotation will only affect drawings made AFTER the rotation is done.
You could try moving the rotate calls to just before the object that needs to be rotated?
I've got a canvas that includes images, I'm re-drawing 1 pixel lower each time to give the effect of falling. I've got the images in an array and I just place them 1 pixel lower without recreating the image.
Is it possible to add a border dynamically to images that reach a certain point and if so, how?
Yes, all you have to do is draw a path outside the image and call ctx.stroke() to make the border.
So say the image has the coordinates x and y, with a width and height of w and h, you just do:
ctx.rect(x, y, w, h);
ctx.stroke();
Want a different colored border?
ctx.strokeStyle = 'blue';
Thicker?
ctx.lineWidth = 5;
If you know your images' size and location and as you draw them you probably do, You can use the .rect canvas method to draw a rectangle around the image.