I am trying to achieve grass like bend on a straight line created by using Cubic bezier curve.I have created a straight line using Bezier curve and now i want to bend it from top.But the problem I am facing is I am not able to do it dynamically.The moment I use mousemove for creating the bend,series of curves appear giving the canvas a paint like look which is somthing I dont want.I just want a single curved line.My question is how do I clear the previous lines that have been drawn and restore the latest bended curve??
My CODE:here is my code if you want to have a look at it
Create two canvases stacked on top of each other:
The first one containing the static content, the other only the dynamic content.
This way you will only need to be concerned about clearing the area the grass was drawn in (and this is much faster too as there is no need to redraw static all the time).
Place the two canvases inside a div which have position set to relative, then place the canvases using position set to absolute.
Now you can make a function to draw the static content (you will need to redraw it if the browser window gets resized etc.).
Record the area the grass is drawn within and clear only this (for each grass) in the next frame.
If this last is too complicated, just use a simple clear on the "dynamic" canvas:
ctxDyn.clear(0, 0, canvasDyn.width, canvasDyn.height);
This will also preserve transparency of this canvas, or "layer" if you like.
Use requestAnimationFrame to do the actual animation.
var isPlaying = true;
function animate() {
ctxDyn.clear(0, 0, canvasDyn.width, canvasDyn.height);
drawGrass(); //function to draw the actual grass
if (isPlaying) requestAnimationFrame(animate);
}
animate(); // start
The isPlaying is a flag you can toggle with a button on screen or something similar, to be able to stop the animation. See the link for requestAnimationFrame on how to make this cross-browser as this is still a "young" implementation.
dynCtx and dynCanvas can of course be called what you want.
You need to erase the current contents of the canvas before redrawing your updated "grass". This would involve redrawing everything else that is "static" on the canvas. For example:
function redraw() {
// Erase the current contents
ctx.fillStyle = 'white';
ctx.fill(0, 0, canvas.width, canvas.height);
// Draw the stuff that does not change from frame to frame
drawStaticContent();
// Draw the dynamic content
drawGrass();
}
In your mousemove event, update your grass curve information, then 'redraw'.
Related
I am creating a html5 canvas game and the main idea is that there is a loop at every animation that redraws everything on my canvas in every frame.
For some reason the objects drawn don't appear in the order i want them to. i want the background image first, then a rectangle and finally an other image to be shown on top of each other.However, the rectangle blocks the view of the second image not other way around.
my relevant code:
function playerdraw(p){
ctx.rect(p.x,p.y,100,150);
ctx.stroke();
//irrelevant stuff here...
ctx.drawImage(p.im,p.x,p.y+25,100,100);
}
I run the whole thing on window.onload so image loading shoudn't be a problem.
Why is this happening?
(as you haven't provided enough code, I assume this could be the issue.)
You need to redraw the background image each time you run the playerdraw() function (if you're clearing the entire canvas each time). So, the following code should work :
function playerdraw(p) {
// clear entire canvas
ctx.clearRect(...);
// draw background image
ctx.drawImage(...);
// draw rectangle
ctx.rect(p.x, p.y, 100, 150);
ctx.stroke();
// irrelevant stuff here...
// draw other image
ctx.drawImage(p.im, p.x, p.y + 25, 100, 100);
}
Note: You need to clear the entire canvas at the very beginning (if you're doing so). There's is also a possibility that you're doing some kind of canvas translating or scaling stuff which if done in wrong order, things can get pretty messed up.
I now know what my issue was. I forgot to add
ctx.beginPath();
in my code. I called my function again and again and it drew more rectangles then I wanted to. I feel so silly.
I have the start of a project here and ran into a little issue.
https://jsfiddle.net/kylebrown219/gn10Lh8g/
In the jsFiddle you can click and create as many circles as you wish. When you press 'Spawn' you will see a Rectangle move across the screen. How do I get rid of the trail, without erasing the circles behind it?
I think this is where the issue is:
context.clearRect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);
Thanks!
Depending on your needs; if you just are after animation you can use this little trick:
Set the current content of canvas as background to the element before drawing the rectangle:
canvas.style.backgroundImage = "url(" + canvas.toDataURL() + ")";
Then, when animating, clear the whole canvas, then redraw rectangle at current position:
context.clearRect(0,0,canvas.width,canvas.height);
drawRectangle(myRectangle, context);
Modified fiddle
To clear everything just reset the background style ("none") and clear.
You will of course have to limit the spawn button, or store the circles (as objects) for redraw (which in that case you could have used to redraw the background).
I would like to create an element, that shows a red circle. Once the user clicks on it, she can record her voice. In order to show the LIVE mode, I'd like to make the circle "breath" according to the incoming frequencies.
I'm experimenting with a <canvas> element. That means it creates a circle that gets bigger and smaller, depending on the variable arcrad. However, the lines are being drawn correctly, but they do not disappear afterwards. I tried to apply .clip() but can't get it to work...
if (arcrad <= 10) arcrad = 10;
analyserContext.beginPath();
analyserContext.arc(100,120,arcrad,0,2*Math.PI);
analyserContext.closePath();
analyserContext.lineWidth = 2;
analyserContext.strokeStyle = 'red';
analyserContext.stroke();
Any ideas - or completely different strategies for this use case?
Canvas will overdraw by default. For your animation you’ll need to clean the canvas at the start of each frame. Use something the following at the start of your drawing function:
analyserContext.clearRect(0,0,200,200);
assuming your canvas is 200 pixels wide and high. It’s worth pointing out that sometimes you don’t want to completely clear the animation field every frame. For example, if you were to draw a semi transparent rectangle over the frame at the beginning (instead of clearing it) then you’d end up with a basic ‘bullet time’ style effect.
It's a normal behavior. Once something it's drawn on the canvas, it's there forever. You have to think like if you were painting something: what has been done cannot be undone.
Luckily, you still have solutions:
1) redraw another circle on top of the first one with the background color. It's really not the recommend way, but it still can be useful
2) use clearRect method (see How to clear the canvas for redrawing)
There are numerous ways to clear a canvas pre drawing to create animation:
How to clear the canvas for redrawing
simplest in my mind:
canvas.width=canvas.width;
though can equally use clearRect (which is actually quicker and won't reset the entire canvas if that is an issue regarding transforms etc!) over the region or whole canvas.
Get the likes of:
http://jsfiddle.net/dw17jxee/
I have a polygon object (say a car) drawn inside a HTML5 canvas with help of methods moveTo and lineTo. I want to repeatedly draw that object at different positions in the canvas (simulating a moving object). My problem is that the previous drawn object is not getting cleared. Instead, multiple images are drawn on the canvas. How can I fix this issue?
You have to clear the canvas at the start of every draw frame
context.clearRect(0, 0, canvas.width, canvas.height);
Canvases are just arrays of pixels, they know nothing of the shapes you have drawn.
There are animation tricks that used to be used on bitmapped displays (e.g. "xor drawing") that can be used to remove the old shape before you draw the new one, but on modern machines it's generally far simpler (and perfectly fast) to just erase the canvas and start again for each frame.
Given your comments to other answers, I'd suggest just using two Canvases - one for the static background and one for the car. If the background image is static it could even be an <img> element instead of a Canvas.
If the car image is static you could also just draw that once, and then use CSS positioning to set its position relative to the background for each frame.
suppose your shape is car then you first have to assign a new graphic like:
car.graphics = new createjs.Graphics();
car.graphics
.setStrokeStyle(1)
.beginStroke("#000000")
.moveTo()
.lineTo()
.lineTo()
I would like to export my canvas onto a PDF and only render the elements added to the canvas. For example:
I have this canvas, with a background-image set to it.
http://i49.tinypic.com/n7lv.png
This is my result when I render it to PDF (using Bytescout library)
http://i50.tinypic.com/346ud7m.png
This is how I want it to end up as:
http://i50.tinypic.com/2q1s9hv.png
Meaning, I want it to end up with no rounded corners, without the background image. The canvas is done using the fabric framework. My idea is to get all the elements added to the canvas, except background image, then render the PDF from there. Any guidelines? Is that the way to go?
You simply redraw the entire scene, omitting the parts you don't want to write to a PDF.
If you don't feel like keeping track of everything to redraw, then create a second, in-memory canvas (document.createElement('canvas')) and do every drawing operation to that canvas instead of your normal one, then draw that canvas onto your normal one as the user edits instead of drawing directly onto your normal canvas.
The old way:
// First you round the corners permanently by making a clipping region:
ctx.roundedRect(etc)
ctx.clip();
//then a user draws something onto normal canvas, like an image
ctx.drawImage(myImage, 0, 0);
The new way:
// make a hidden canvas:
var hiddenCanvas = document.createElement('canvas');
var hCtx = hiddenCanvas.getContext('2d');
// First you round the corners permanently by making a clipping region:
ctx.roundedRect(etc)
ctx.clip();
//then a user draws something onto HIDDEN canvas, like an image
// This image never gets its corners cut
hCtx.drawImage(myImage, 0, 0);
// Then you draw the hidden canvas onto your normal one:
ctx.drawImage(hiddenCanvas, 0, 0);
When its time to print, you use your hidden canvas, which does not have a background image and does not have clipped corners.