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.
Related
Is it possible to draw with transparency like you would draw with any colour?
For example if i'm using a createGraphics() you can use clear() to make the canvas transparent, but what if I wanted to draw a black background with a see-through hole in the middle (draw a "transparent filled" ellipse that cuts through?).
You could play around with the blendMode() function. Here is the reference for the blendMode() function.
Or you could call the set() function on each pixel. Here is the reference for the set() function.
Or you could look into using an image mask. For example, you could create an image with a transparent center ahead of time, and then display that over top your sketch.
Another option is to use the mask() function. Here is the reference for the mask() function.
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 have this javascript (and the markup and css is in this fiddle)
$('input[type=range]').change(function (e) {
$('.box').css('transform','rotateY('+($(this).val()/100)*360+'deg) rotateX(20deg)');
});
So basically I am trying to light the cube based on some directional light coming from certain direction.
Lets say directional light is coming from (x,y,z)... (100,100,100) to (0,0,0).
Then the gradient need to be darker based on its vector alignment from on side and lighter or same depending on the other side. It's all doable but I can't wrap my mind around it as to get transformation data comes in 3dmatrix which is beyond me.
/* .front { background: linear-gradient(to bottom, blue, rgba(220,30,30,0));} */
pseudo code may look like this:
get div's base color.
get cube 3d vector based on its transformation and its parent if any.
calculate what angle of gradient should be.
calculate what intensity of base color should be on each side..better yet add second div inside and apply transparent gradient over it which will enable for even pictures and stuff easily.
apply that
etc
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)
I'm using svg/d3 for creating a chart made of 'rect' elements.
What is the best way for adding a partical border/stroke for each rectangle (only on top of the rectangle)?
Thanks
I don't think SVG supports stroking only portions of a rectangle or path - stroke isn't like a CSS border. You're left with a few other options, all of which take some extra work:
Stroke the entire rect and apply a clipPath to remove the other three edges - probably works best if you make the rectangles bigger than necessary.
Apply a linear gradient fill to each rect, using the gradient definition to show a "border" at the top of the shape.
Add a separate line element to act as the border for each rect.
Use the stroke-dasharray property (docs) to set a dash definition where the "dash" only covers the top of the rect. This might be tricky to get right, but I suspect it wouldn't be too hard, as the stroke probably begins at the top left of the shape.