I'm struggling to clear a canvas for 2 simple stroke paths.
Example: http://dl.dropbox.com/u/104380/canvas-test-case.html
... I'm using the new
requestAnimFrame()
by Paul Irish. But I don't think this should have any effect on Canvas contexts, as opposed to a setInterval. As far as I know, I'm also correctly using beginPath() and recalling getContext() inside the render loop.
... problem is, the two original strokes are not clearing!
Any ideas?
this line...
context.clearRect(0,0,canvas.width,canvas.height);
should be
context.clearRect(0,0,canvas[0].width,canvas[0].height);
Related
The problem: I'm trying to create a simple drawing app using p5.js. Instead of the standard cursor image, I'd like to show a circle at my cursor location that represents the size of the drawing brush.
Potential solution 1: Replace the cursor using the cursor() function native to p5.
Why it doesn't work: The p5 cursor function only takes the following parameters:
ARROW, CROSS, HAND, MOVE, TEXT, or WAIT, or path for image
As such, there's no native way to replace the cursor using the ellipse class.
Potential solution 2: Use the noCursor() function and then draw the circle at the cursor location, while also drawing the background, as such:
var brushSize = 50;
function setup() {
createCanvas(1080,720);
noCursor();
}
function draw() {
background(100);
ellipse(mouseX,mouseY,brushSize);
}
Why it doesn't work: While this solution gets the desired effect i.e. replacing the cursor with a circle the size of the brush, the constantly updating background prevents me from actually drawing to the canvas with the brush when I want to.
Is there some way I can replace the cursor without actually drawing the ellipse to the canvas? Is there any way to save and then instantly reload a canvas in p5? I couldn't find such a method searching through the API docs. Any hints are appreciated.
According to the reference, you can pass a URL into the cursor() function to set an image.
If you want to use an image that you draw, you're going to have to draw them ahead of time and save them to files, and then use those files. Something like this:
cursor('images/ellipse-15.png');
Where ellipse-15.png is an image that you generated ahead of time, to match when brushSize is 15, for example.
Btw P5.js is just setting the cursor CSS property. You can read more about it here.
If you want to go with the noCursor() approach and draw the ellipse yourself, you could draw your drawing to a buffer (the createGraphics() function is your friend) and then draw the ellipse on top of that every frame. I'd still probably use a cross cursor just because there's going to be some annoying lag if you draw it yourself.
Create a circular DIV inside the canvas container and show it on top of the actual canvas.
Iv`e created canvas pointer error. It shows a target to desired location (mouse position):
http://jsfiddle.net/conmute/rk276q3g/
The problem is in Firefox rendering, (move mouse very fast):
http://jsfiddle.net/conmute/rk276q3g/1/
rectangle acts weirdly, and i am missing smth. Can anybody point what exactly?
ctx.rect(
// start x,y pair
patternOffset.x, -p.circle.h/2 - patternOffset.y - 12,
// end x,y pair
-p.repeat.w, distance - p.circle.h - 1
);
ctx.fillStyle = pattern;
ctx.fill();
Status update
I fixed this issue:
http://jsfiddle.net/rk276q3g/2/
By commenting out ctx.save() and .restore()
and placing arrow image before drawing the rectangle.
So actually i fixed this issue, But the thing is...
Question update
... what if i need to draw after i did some ctx.translate(... and some drawings?
I need to use ctx.save() and .restore() methods, but it cause a problems. How can i do this work without commenting them? Cause when i remove them it solves problem.
I thought that i understand properly how they work, but i see that i don't.
Update
It appears that by removing all ctx.restore() and ctx.save() solves the solution, but when i add my part to be drawn after i translateed back by calculating previous position, problem appears again!
Please see:
http://jsfiddle.net/rk276q3g/5/
The save() and restore() work as follows: The <canvas> maintains a stack of its state and each item in the stack represents all the attributes of the context (lineStyle, strokeWidth, transform, …). By calling save() a new item of the state is created and pushed onto stack. By calling restore() the item is popped from the stack and the state of the canvas is set to the properties from the item on top of the stack.
Here is a good example.
To answer your question: You need to save the state of the context before you translate and rotate it, to create a new current item on the stack, which you can modify to your needs. Once you've done the heavy lifting and want to draw some things based on the default values, you need to restore the state and every paint action will be based on default values.
To not run into conflicts as you do, I always write painting methods following this pattern:
function drawSomethingFanzy (ctx) {
ctx.save();
//some really awesome drawing here;
ctx.restore();
}
Edit
I have missed to point out that save() creates a new Item on the stack, but does not restore the default settings, all settings remain unchanged, but are saved and can be restore()-ed later on.
Edit
I attached a screenshot of the result which shows up at my computer from fiddle. For me that looks correct, so could please post a picture that shows what the exact problem is, or what you would like to achieve? I honestly do not get what the problem is. Do you mean the gaps in the pattern fill?
Update
I just had a moment and created a fiddle of what I think you want here. I hope it helps!
I am having trouble finding a good method to limit my mouse to be only able to click on a pre existing line in canvas (stroke width of 3)
What I need to know
how to limit mouse so can only click on pre- existing line, add a dot on click
line is drawn with this function
function createLine(startX:Float, startY:Float, endX:Float, endY:Float)
{
surface.beginPath();
surface.moveTo(startX, startY);
surface.lineTo(endX, endY);
surface.closePath();
surface.strokeStyle = '#ffffff';
surface.lineWidth = 2;
surface.stroke();
}
I am working in haxe, but solution in JS is fine
Thanks in advance.
The only way is for you to keep track of what you have drawn and do the collision/mouse over detection on your own.
If you need your canvas to be highly interactive, you should probably be looking at SVG. http://raphaeljs.com/ is a great library for drawing which will use canvas or SVG, whichever is available.
I'm trying to accomplish an effect similar to what you might see on the cartoon Chowder (example link) , where shapes serve as masking layers for a texture underneath that stays static. I've begun playing around with this idea by creating a render loop that clears the canvas, saves it's state, then draws a rectangular clipping region, followed by drawing the background texture that occupies the entire width and height of the canvas.
Here's the draw function:
function draw()
{
context.clearRect(0,0, 640, 480);
context.save();
x += velocityX;
y += velocityY;
context.rect(x, y, 40, 40);
context.clip();
context.drawImage(image, 0,0, 640, 480);
context.restore();
}
Basically it just runs at 60 frames per second, updating the position of the rectangle and clipping a background image inside the clipping region. (I know the code isn't structured perfectly, but I was just experimenting to see if this effect was even possible on the canvas).
http://jsfiddle.net/JERje/86/
The problem I seem to be having is that the clipping area from the previous iteration of the loop hangs around creating the weird effect that you see in the fiddle above. I've tried reordering everything in the draw() step of the loop, but the only thing that seems to work is the canvas.width = canvas.width trick for clearing the screen. I'd like to avoid this method of clearing the screen, since it doesn't seem to work in IE, and it also destroys the canvas state. clearRect() should work to clear the screen. What am I doing wrong?
You're using the same HTML5 Canvas paperback I am aren't you.
If you set up an adhoc canvas as I did on your jsfiddle like so:
var newCanvas = document.createElement('canvas');
newCanvas.getContext("2d").drawImage(image,0,0);
A function such as this would be able to hack a section out of that canvas:
context.putImageData(newCanvas.getContext("2d").getImageData(x,y,40,40),x,y);
Thus giving you the chowder effect. Good show man, good luck. Pst me if it doesn't work
EDIT: However this solution will ignore some context scaling transformations. Just be smart about how you handle scale on your own (and you really should be anyways if you want the true "chowder" effect)
So, feel pretty dumb about this, but apparently when you call rect() you also have to make sure to call closePath afterwards in order to close the clipping area. Glad I figured it out finally, now on to adding multiple layers!
Here's the working fiddle: http://jsfiddle.net/JERje/129/
Hi I am playing around with shapes and canvas and I have a question:
So say I have this code that draws a nice rectangle on the canvas:
$("#create_rectangle").bind("click", function() {
if(canvas[0].getContext){
var ctx = canvas[0].getContext('2d');
ctx.strokeRect(50,50,50,50);
}
});
Now I say I want to store a reference to that rectangle so that I can make alteration to it at a later stage. The stokeRect() method does not seem to return any value. How do I reference that particular rectangle that was created?
Well you can't reference it, but you can include it in a draw function which depending your arguments allow you to move/rotate hide etc.
It very depend on what you want to do with this shape.
This tutorial can be helpfull to understand manipulation of shape.
http://simonsarris.com/blog/140-canvas-moving-selectable-shapes
You can't.
Canvas is basically just a canvas. You throw some paint at it, it dries and you're done. You can't take your paint and move it somewhere else—but you can paint over it.
What you may want is SVG. It keeps track of shapes and other assorted things so that you can change them, deal with interactions much more precisely, et cetera.