I have problem with canvas createPattern. I have two boxes, both will move after pressing a keyarrow:
Example:
http://jsfiddle.net/wA73R/1/
The problem is that the box background filled by createPattern also is moving. How to avoid that? Is there any solution? The big box is only an example (drawImage is not the good solution for me, I need something that will repeat background image).
Thank you for help
The problem is that the box background filled by createPattern also is moving.
Actually your problem is that the background is not moving - it is static, while you are drawing your rectangle to different positions.
How to avoid that?
The pattern will always be drawn at the coordinate origin, whose actual position is defined by the current transformation. In future you will be able to transform the pattern itself with the setTransform method, but since that currently is not implemented anywhere you instead will have to change the global transformation matrix.
In your case it means, that instead of drawing your rectangle at x/y, you translate the whole context to x/y and draw your rectangle at 0/0 then:
ctx.fillStyle=pattern;
ctx.save();
ctx.translate(boxes[i].x - left , boxes[i].y);
ctx.fillRect(0, 0, boxes[i].width, boxes[i].height);
ctx.restore();
(updated demo)
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.
I'm making a 2d game using melonJS.
In my game, i have an arrow which rotate on its axis. This arrow is a png image. When i keep the left mouse button, the arrow needs to fill from yellow to red, from the base to the top. Here's an exemple :
The initial arrow is all light red, like the top of the example image. when i keep the button clicked, the arrow color should change from the bottom with a white line as a current position to the top.
How can i do this with javascript ? Is there any things embbeded in melonJS to handle this kind of trick ?
Since your question is text based rather than code based, I'll do the same.
Here is how to draw your rotated changing-gradient arrow
Clear the canvas with context.clearRect.
Rotation: Translate to your desired center-axis coordinate around which you want to rotate. Then Rotate to your desired angle. Transformations (context.translate & context.rotate) will actually rotate the canvas itself. That way all new drawings will be translated (moved) and rotated. Note: Existing pixels will be unaffected.
Drawing the arrow: Draw your arrow with path commands (beginPath, moveTo, lineTo, ... for each piece of the arrow). Since you have already done your transformations (translate & rotate), you don't need to try to rotate your arrow drawings.
Gradient fill for arrow: Create a linear gradient (context.createLinearGradient) that extends through your arrow drawings. Set color stops (context.addColorstop) to create your desired yellow & red gradient along your arrow. Use the gradient as your context.fillStyle and fill your arrow path with context.fill.
Using gradients for the white indicator line You can also use gradients to display your white indicator bar. To do this, draw your arrow and then overdraw with another gradient that is transparent at all places except your desired indicator percentage where it will be white.
var g=ctx.createLinearGradient(0,170,0,0);
g.addColorStop(pct-0.01,'transparent');
g.addColorStop(pct-0.01,'white');
g.addColorStop(pct+0.01,'white');
g.addColorStop(pct+0.01,'transparent');
ctx.fillStyle=g;
ctx.fill();
Always clean up! Undo your transformations. You can undo transformation by either (1) reissuing your transformation commands in reverse order and with negative arguments or (2) resetting every transformation to defaults by resetting the transformation matrix with context.setTransform(1,0,0,1,0,0).
Put your code into a requestAnimationFrame animation loop and change the angle and/or the gradient to meet your design needs.
You can layer two PNG files, one with the arrow, one with the stripe, and control the position of the white stripe that sits on top of the arrow. Canvas should enable that pretty easily by default, and even more so if you're using a library.
I need to clear a rectangle Drawn on Image in Canvas with out damage existing image. I can draw small rectangle points and clear that out. But the problem is when I clear rectangle it remains as white small patch on image.
Can someone tell me how to clear a rectangle on image without damage the existing image.
I have used following methods to clear rectangles but didn't work.
1) context.fillStyle ="white";
2) context.clearRect(xCoordinate, yCoordinate, 10, 08);
Thanks in advance!
Canvas doesn't work that way. It's a single layer, its also transparent by default. So with that in mind, you might be able to achieve what you want by simply giving the canvas element a CSS background. That way anything you draw on top of that background can easily be removed and the background will show through.
#backed-canvas{
background-image: url(http://www.placebear.com/300/200);
}
JSFiddle example: https://jsfiddle.net/yLf5erut/
There is one thing you can do.
When create a rectangle on the canvas just get the image data like:
var imgData = context.getImageData(xCoordinate, yCoordinate, 10, 8);
and draw the rectangle.
When clearing out the rectangle just place then image data back like this:
context.putImageData(imgData, xCoordinate, yCoordinate);
I suggest using 2 canvas elements one over another.
So you can have the original image drawn on the bottom canvas with low zIndex, and the top one with highter zIndex can be used to draw / clear whatever needed. This is a common practice, and for more complecated animations you will end up with better performance.
I have a function in script that draws a rectangular on canvas.I want to clean the rectangular drew in the "if" condition.
I also have text on the canvas(its coordinates are 0,80) and it shouldn't be cleaned. Only the rectangular must be cleaned.
function red_stroke_2(yy)
{
//Red color edges
context.strokeStyle = "#f00";
context.strokeRect(0,yy,800,40);
}
if (Option1==answers[qnumber])
{
red_stroke_2(80);
}
Canvas is "stateless" in the sense that it does not know about the primitives that have been drawn or the calls that have been made. As such it is impossible to undo only a certain drawing call. If you need to modify the drawing, you need to redraw all of the items that you don't want to change. Of course you have the option to change single pixels, so if your text is black and the rectangle is red, you can replace all red pixels, but this won't work so good if antialiasing is enabled and is utterly complicated.
So either redraw the whole area (omit the rectangle drawing but render the text). Or consider using 2 Canvases on top of each other (one with the text, one with the background), then of course you can rerender the background without having to worry about the text.
Last but not least using SVG might be also an alternative, since this is stateful and consists of DOM elements that you can modify/insert/remove and the browser will do the compositing. In that case you would have a rect element and a textelement and you could simply remove the former.
This will put transparent pixels instead of your rectangle:
function clean_red_stroke(yy)
{
context.clearRect(0,yy,800,40);
}
//Call it with the same 'yy' you used in the drawing method
clean_red_stroke(80);
However I think you code could be improved, by using more variables (and consequently a most generic function) for exemple.
I wanted to know if Html5 supports shape translation in canvas..For instance I have a rectangle,is it possible to apply a transformation to it?
canvas = document.getElementById('Canvas');
context =canvas.getContext('2d');
context.rect(myRectangle.x,myRectangle.y,myRectangle.width,myRectangle.height);
There's a few different methods for animating and changing the position that you want to draw your thingy. Either way, if you're after an animation, you're going to need to clear your canvas and keep drawing - like a flip book if you will.
Choices for setting the newly drawn item include:
moveTo - to move to the new position of your thing
translate - to translate the centre point of the canvas and keep the drawing positions the same, but move the underlying coordinate system
.rect(newX, newY, height, width) - drawing the specific position
I mocked together a (contrived) example of using translate on a canvas - which will move the the animating box around the position of your cursor. It's done in a loop - and I'd suggest checking out Paul Irish's article on requestAnimFrame for better animation loops. Here's the example: http://jsbin.com/afofur/2/edit#preview
As the comments say in the previous answer - SVG maintains a object model, so you can reference objects on the page, canvas is a bitmap API (basically), and once the pixels are committed to the canvas, there's no reference to the method or shape behind the drawing, it's just pixels to the canvas API.
No, once it is drawn to the canvas you can't change it anymore, there is no in-memory representation of the shapes you draw on the canvas. However, you can transform the canvas before you draw the shape and reset transform (canvas.setTransform(1, 0, 0, 1, 0, 0)) after you've drawn the shape.
Edit
Remember that the canvas API doesn't keep track of which objects you draw. It just fills the pixels with a color where you ask it to draw a rectangle. If you want to make animations, you will have to keep track of which rectangle you drawn yourself (make an object with properties x, y, width, height). Then you will have to do the following in each animation step:
clear the canvas
update the objects for the new time frame
redraw the canvas
You can find a tutorial here.