I am using Rafael 2.1.0 with JavaScript on Firefox 19.0.2 on Windows 7.
I would like to make a rectangle that is completely opaque around the edges but transparent in the interior. Is this possible?
I have looked at
paper.rect.attr({fill:
but it appears to only have the option of the color to fill with.
paper.rect.attr({fill: 'red', opacity:0.0});
makes the edge disappear
paper.rect.attr({fill: 'red', fill-opacity:0.0});
produces an error in the JavaScript code (in that subsequent functions do not work).
You have to set strokes instead of fill and you might also alter strokes-width.
Actually setting strokes will let you set their color and setting strokes-width will let you edit their width in viewport units.
Related
I'm creating an Rpg in Phaser, and I'm trying to make a Flash effect happen over a Sprite -that means turning the Sprite all white for a moment and then returning to its original color-.
So my question is: what's the best way of achieving this effect?. I've tried two solutions so far, but i'm missing something:
Solution 1:
I tried tweening the tint parameter of the sprite, like this:
this.game.add.tween(enemy).to({
tint: 0xffffff,
}, 100, Phaser.Easing.Exponential.Out, true, 0, 0, true);
But it doesn't work since setting the tint to 0xffffff is the same as setting it to its default color.
Solution 2:
My second possible solution is adding a white square that has the same size of the sprite, and using the actual sprite as a mask for the square:
var flash = this.game.add.graphics(0, 0);
flash.beginFill(0xffffff);
flash.drawRect(enemy.x, enemy.y, enemy.width, enemy.height);
flash.endFill();
flash.mask = enemy // enemy is my Sprite
/* .. code for tweening the flash */
The problem with this solution is that the mask needs to be a PIXI.Graphics object; and I'm using a Sprite object.
So please, any guidance would be appreciated.
In the version of Pixi that Phaser 2.2.2 uses there is a 'tintCache' which basically rounds the tint value, then caches the result. This means you can't do subtle tint ramping like you're trying to do with a tween. We removed this in Phaser 2.3, so it will be available from then, but as of now it's still in dev.
Also you can tint to a 'near white' colour - only 0xffffff precisely resets the tint. But a value very close to that would still be set ok and probably have the desired result.
If you're using WebGL I would still use a tint with 'as near as white as possible' colour values and tween them. You could disable the tint cache for yourself by copying that part of the changed code from the Phaser dev branch.
In Canvas mode it's expensive though as it has to recalculate the pixels every single time you update it.
If you need to worry about Canvas performance then honestly I would create a new PNG that matches your sprite, colour it in all-white and display it over the top of your main sprite as needed and alpha it out. It's less than ideal because of the extra assets required, but it would be the fastest in canvas mode for sure. All depends on your game though is that's acceptable or not.
Edit: Also occurred to me that you could probably achieve what you need by using a blend mode too, such as lighten. You'd duplicate your main sprite, set the blend mode on it, display it over the top of your sprite and fade it out. This would work fine in Canvas at least.
You can use a ColorMatrixFilter on the Sprite. In Phaser, you may have to manually load in the PIXI script first:
game.load.script('filter', 'js/filters/ColorMatrixFilter.js');
Use this for white:
var filter = new PIXI.ColorMatrixFilter();
filter.matrix = [1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1];
this.game.filter = [filter];
You can also tween the matrix values if you want a smooth transition.
I am wondering if there's a way to access the Bounding Box Gui properties of mask shapes so that I can see how to create perfect circle shape masks in After Effects?
My code is below:
maskpath = app.project.item(1).layer("Orange Solid 2").property("ADBE Mask Parade").property("ADBE Mask Atom").property("ADBE Mask Shape");
Not sure what you mean by "access the Bounding Box Gui properties of mask shapes", but I do think I know what you mean by "how to create perfect circle shape masks in After Effects".
See D. Ebberts' script code posted here: http://aenhancers.com/viewtopic.php?f=11&t=2084
I believe it does (or will lead you to do) what you want.
I found the answer from After-Effects-CS6-Scripting-Guide.pdf page 48
AVLayer sourceRectAtTime() method
Retrieves the rectangle bounds of the layer at the specified time index, corrected for text or shape layer content.
Use, for example, to write text that is properly aligned to the baseline.
app.project.item(index).layer(index).sourceRectAtTime(timeT, extents)
Returns
A JavaScript object with four attributes: [top, left, width, height].
I think you are talking about how to access Left Top Right Bottom values of this window.
This window appears when you click on shape of mask path
(position where pointing hand drown blue color arrow)
please any one can tell me how to access those values via Script
I have two canvases. I have made them circular using border-radius. The 2nd is positioned inside the first one (using absolute position).
I have click events on both circles. If you click on inside canvas, the color at the point of the click is loaded in the outside canvas with opacity varying from white to the picked color and finally to black. If you click on outer canvas the exact color value at that point is loaded in the text-box at the bottom
I am unable to click in red zones (as shown in figure below) of the outer canvas when using chrome. I tried z-idex, arcs but nothing is helping me. But In Firefox everything is working fine.
Note: You can drag the picker object in the outer circle. But if you leave it in red zones, you would not be able to click it again in Chrome. Clicking in green zone will get you its control again
Code in this JSFiddle
Edit
I excluded all irrelevant code to make it easy. Now there is only a container having two canvas.
Filled simply with two distinct colors. Open following fiddle link in both chrome and firefox. Click on both cirles in different zones and see difference in chrome and firefox. I want them to behave in chrome as they do in firefox
Note I will ultimately draw an image in inner canvas.
Updated Fiddle Link
-
Your problem is because canvases currently are always rectangular, even if they don't look rectangular. Border radius makes the edges except the circle transparent, but it still doesn't stop events in Chrome on the corner areas. This is why you cannot click the bottom circle in those areas
I even tried putting it inside of a container that had a border-radius instead but the click event still goes through
With that being said, you have two options. You could either change your code to only use one canvas with the same type of layout, just drawing the background circle before the other each time. Essentially you'd draw a circle, draw your black to color to white gradient, use the xor operation to combine the two into one circle, then do the same with the rainbox gradient. You must draw the background circle first because canvas paints over the old layers every time
or
You could use javascript to only detect clicks in the circular area which takes just a little bit of math (: This solution is featured in edit below
In the future, CSS Shapes may allow canvases to be non-rectangular elements to be used, I'm actually not sure, but we don't have that capability yet at least
Edit
Alright, so after going through your code a bit it seems there are some things I should cover before I offer a solution
Setup all your finite variables outside of the functions that run every time. This means you don't put them (like radiuses, offsets, etc.) in the click function or something that runs often since they don't change
Your "radius"es are actually "diameter"s. The format of .rect goes .rect(x, y, width (diameter of circle), height (diameter of circle))
Almost always when overlaying canvases like you are you want to make them equal dimensions and starting position to prevent calculation error. In the end it makes it easier, doing all relative positioning with javascript instead of mixing it with CSS. In this case, however, since you're using border-radius instead of arc to make a circle, keep it like it is but position it using javascript ....
jQuery isn't needed for something this simple. If you're worried about any load speed I'd recommend doing it in vanilla javascript, essentially just changing the .click() functions into .onclick functions, but I left jQuery for now
You can declare multiple variables in a row without declaring var each time by using the following format:
var name1 = value1,
name2 = value2;
Variables with the same value you can declare like so:
var name1 = name2 = sameValue;
When children have position:absolute and you want it to be positioned relative to the parent, the parent can have position:relative, position:fixed, or position:absolute. I would think you'd want position:relative in this case
When you don't declare var for a variable it becomes global (unlessed chained with a comma like above). For more on that read this question
Now, onto the solution.
After talking with a friend I realized I could sort do the math calculation a lot easier than I originally thought. We can just calculate the center of the circles and use their radiuses and some if statements to make sure the clicks are in the bounds.
Here's the demo
After everything is set up correctly, you can use the following to detect whether or not it's in the bounds of each
function clickHandler(e, r) {
var ex = e.pageX,
ey = e.pageY,
// Distance from click to center
l = Math.sqrt(Math.pow(cx - ex, 2) + Math.pow(cy - ey, 2));
if(l > r) { // If the distance is greater than the radius
if(r === LARGE_RADIUS) { // Outside of the large
// Do nothing
} else { // The corner area you were having a problem with
clickHandler(e, LARGE_RADIUS);
}
} else {
if(r === LARGE_RADIUS) { // Inside the large cirle
alert('Outer canvas clicked x:' + ex + ',y:' + ey);
} else { // Inside the small circle
alert('Inner canvas clicked x:' + ex + ',y:' + ey);
}
}
}
// Just call the function with the appropriate radius on click
$(img_canvas).click(function(e) { clickHandler(e, SMALL_RADIUS); });
$(wheel_canvas).click(function(e) { clickHandler(e, LARGE_RADIUS); });
Hopefully the comments above and code make enough sense, I tried to clean it up as best as I could. If you have any questions don't hesitate to ask!
I'm having trouble describing the issue, but here goes:
I'm trying to make a SVG circle progress bar and I've found a perfect example of what I want to do without any third part libraries like snap:
http://codepen.io/JMChristensen/pen/Ablch
The problem is that I'm having real issues with changing the origin of the stroke. As you'll notice if you try it out, the origin is on the right hand side. I need it to come from the top.
Now, I'm a developer, so I've tried myself, but I can't for the life of me figure out how to do it. If I change the stroke-dasharray attribute the stroke won't match the percentage set in stroke-dashoffset.
I understand it all comes down to math with the stroke-dasharray value, but I don't quite understand what to do.
The dashoffset is calculated like this:
var pct = ((100-val)/100)*(Math.PI*(r*2));
And there has to be some kind of correlation between that and the standard dasharray value 565.48. There's no mention of it anywhere.
Add this to the 2nd <circle ...></circle> in the SVG:
transform="rotate(270,100,100)"
Demo here
Regarding your last bit of inquiry:
And there has to be some kind of correlation between that and the standard dasharray value 565.48. There's no mention of it anywhere.
Well, π(r*2) or simply 2πr will give you the circumference of a circle, which in turn gives you the appropriate value for the dash-array that completes the circle.
For example:
Your SVG circle has a radius of 90.
2π(90) = 565.48, therefore your dash-array will be 565.48.
If your radius is 45...
2π(45) = 282.74, so your dash-array will be 282.74.
An alternative for 270deg rotation:
transform="matrix(0,-1,1,0,0,200)"
I just started with fabric.js and I have a (probably beginner) error:
I am using fabric with jquery with the following code:
$(document).ready(function () {
canvas = new fabric.StaticCanvas('scroller');
canvas.add(
new fabric.Rect({ top: 0, left: 0, width: 140, height: 100, fill: '#f55' })
);
});
This code should draw a 140x100 Rectangle on the canvas.
Sadly, only a quarter of the Rectangle appears.
If I change the top and left values to higher numbers, more of the Rectangle appears on the canvas.
So it seems, that the canvas origin is not at 0/0, but at sth. higher.
Does someone know how to fix this or what I am doing wrong?
Thanks in advance,
McFarlane
Here is a jsfiddle link with some examples http://jsfiddle.net/pukster/sdQ7U/2/
My guess is that fabric.js calculates everything from the origin (middle point) since it is drawing exactly one quarter of a rectangle even with a canvas 10 times the size of the rectangle. My guess is that top and left actually refer to the origin and not the top and left sides of the imaginary bounding box. Trouble is there is very little documentation on fabricjs. Is there any reason you are using fabricjs and not easeljs
EDIT Here's the same fiddle but with squares instead of rectangles (it is more clear) http://jsfiddle.net/pukster/sdQ7U/3/
EDIT OK I am now almost absolutely certain that fabric.js uses the center as the top/left. I ripped their example off of their site and overlayed it with the transparent couterpart to those shapes had they been coded in pure canvas http://jsfiddle.net/pukster/uathZ/2/ (blue border is the limit of the canvas element).
What you see is that the boxes are exactly offset by half but the circle (I only drew a semi circle otherwise it would not have been discernable) is perfectly overlapped. This is b/c in HTML Canvas, the circle coordinates (x,y) refer to the origin and not the top left. I did not bother with the triangle b/c my trigonometry is a bit rusty. I personally think it's misleading to use the terms top and left, when x and y would have been more representative and shorter.
Yes, this is highly unexpected and even more undocumented.
Workaround:
Set
originX: "left"
originY: "top"
for each created object.
edit: or use kangax simpler solution in the comment below.
I want to comment but lack the reputation to do so. So anyway, here is what happens when I do the following:
fabric.Object.prototype.originX = "left";
fabric.Object.prototype.originY = "top";
The shape gets rendered fine but when I select it for resizing or moving, it gets offset to a different location. The best approach seems to be to set the coordinates for every object separately using the set() method.