I'm a newbie regarding canvas and I've searched and tried alot, but never accomplished to find the right solution to use this one: http://www.quasimondo.com/BoxBlurForCanvas/FastBlurDemo.html
I want to use it with a image for a fixed background, so I can put the same non-blurred image on top, while having a changeable page, that changes design when exchanging the image.
I know I'm able to use CSS3 Filters for this but it doesnt work on Firefox and the performance of such a blurred big image is terrible...
Thanks!
"I know I'm able to use CSS3 Filters for this but it doesnt work on Firefox ..."
Firefox can do CSS blurring:
First, include an SVG file containing the desired blur in the web page
<svg xmlns:svg="http://www.w3.org/2000/svg">
<filter id="gaussian">
<feGaussianBlur id="myBlur" stdDeviation="5" />
</filter>
</svg>
Next, get a reference to the canvas element in the normal way, eg:
var canvas = document.getElementById('myCanvas');
... and apply the filter to it:
canvas.style.webkitFilter = 'url(#gaussian)';
canvas.style.filter = 'url(#gaussian)';
To change the blur value, you need a handle to the gaussian blur element itself:
var blurFilter = document.getElementById('myBlur');
Use the setStdDeviation(stdDeviationX, stdDeviationY) method to change the blur. Both arguments are numbers, not strings:
blurFilter.setStdDeviation(5, 5);
(Seems to work OK in latest versions of Firefox and Chrome - though Chrome doesn't like it when the blur values are set to 0 ...)
Related
I'm using feGaussianBlur on multiple spinning slotmachine reels to blur images. As the weels speed up, the stdDeviation is increased accordingly. This results in a very high CPU usage and laggs in the safari browser. Is there a way to improve performance? I read about css blur in some articles but they summarized, that the performance is the same.
Edit:
I tested css blur and the performance was even worse.
Blur, by its nature, produces partially transparent results. These need to be blended with the background. In the context of an animation, this can lead to high performance costs. I can see three ways to counteract this. They all aim at ensuring the browser does not need to compute a pixel-by-pixel blending operation but can simply copy image buffers into the area of the animation:
Use blur on elements that sit on a completely transparent background. That means, no colors at all in any background layer. Admitedly, this is not a very realistic scenario.
Make sure there is no partially transparent object on top of the animated object.
If it is not needed outside the opaque area of an object, restrict the blur filter region to the object area.
The third one sounds as if it could be applicable to your problem.
If the area that is blurred is rectangular, you could change the filter region itself. As a default, filters are computed for a region that goes 10% beyond the bounding box of the element it is applied to. To restrict this, set it differently:
<filter id="blur" x="0" y="0" width="100%" height="100%">
<feGaussianBlur stdDeviation="5" />
</filter>
But if your element has a different outline, you would have to set a clip-path to make sure the filter remains invisible outside.
Both approaches could probably benefit from setting the CSS property will-change: contents. But be sure to read the warnings about its usage: use it as a last resort, and use it sparingly.
I have an image. I have a second graphical element ontop of this image, whose alpha I want to use to "hide" parts of the image below it, while the top element itself isn't shown.
Something along the lines of
CanvasRenderingContext2D.globalCompositeOperation = "destination-out"
This top element will change transparency and shape live, so prerendering everything onto a seperate canvas won't be an option.
I was thinking of "multiply" but it didn't do what I expected it to. I thought if I put the alpha of the top layer to "0", that would be multiplied with the layer below, also making it transparent. (I was sad it didn't work)
Is there someway to "hack" this using the existing CSS blending modes (or any other method)?
As an alternative, consider mask-image (however, note that currently there's no support for this on IE / Edge):
img {
-webkit-mask-image: url(http://www.lordtennyson.ca/uploads/1/2/4/2/12421219/paw_print_small.png);
mask-image: url(http://www.lordtennyson.ca/uploads/1/2/4/2/12421219/paw_print_small.png);
}
<img src="http://www.dizzydi.com/uploads/6/5/6/5/65656887/6168555.jpg" />
Let's say that I use some HTML5 markup:
<canvas id="e" width="400" height="200"></canvas>
<script>
var canvas = document.getElementById("e");
var context = canvas.getContext("2d");
context.fillStyle = "red";
context.font = "bold 72px JerseyLetters";
context.fillText("Bulls", 50, 100);
</script>
To make some cool text like this:
Then I decide I want these letters to fit into an envelope that looks like this:
Hoping to get something like this:
How would I go about (1) defining an envelope like the one above and then (2) putting the text in the envelope using HTML5 Canvas to get the result?
I am open to either something that directly places text in the envelope or a solution that first creates an image and then fits the image in an envelope.
Thanks!
EDIT
I added the tags "webgl" and "three.js" to this question on the advice of #markE. I will research those two packages in the mean time as well. I'm very new to .
webGL way:
Do it as a image-processing with pixel-shader.
Render text with 2d canvas, bind webGL texture with buffer and fill texture with canvas image (rendered text). Have prepared envelope that actually maps the area that envelope holds and also every pixel play role of the UV coordinate from the first image. Running that as pixel shader, you have image-to-be-squeezed and envelope (uvs) you'll output final image. That way, it's completely font and text independent. You could even probably make one image-processing step more so you could load any envelope shape and process it on spot, so it becomes font, text and envelope-shape independent.
I'm not sure how well did I explain this.
Hope this helps, though.
SVG provides these sort of text transforms. See http://tavmjong.free.fr/SVG/TEXT_PATH/TextPath.html
EDIT: This link appears to be converting the text to actual SVG. Probably not going to be helpful for you, sorry.
I've created a button with Raphael.js that has a gradient background. Now I want to change to a different gradient when hovering over the button using Element.hover. But as soon as I move the mouse over the button, it starts showing only a solid color.
Here's my fiddle.
Maybe it's browser-related. I only tested Chrome and Safari under OS X.
The problem is that you call transform on the set afterwards. The tranform() method is deprecated, use the transform attr instead. Also, you might want to apply the transformation individually when you create the elements, as Raphael is known to have some issues in transforming sets uniformly.
Is it possible to only trigger a div's mouseover when the cursor is over an opaque part of the div's background image? Perhaps via Javascript?
All I can find with Google are old IE PNG fixes.
This looks like a similar question to this one: Hit detection on non-transparent pixel
I suppose this could also be done for background image by getting the attribute with jQuery:
$('#myDiv').css('background-image');
I haven't personally done this, but it seems like a viable solution. This will only work for modern browsers, but you should be able to make it back-compatible with excanvas.
It is possible, just not very easily. You'll have to use a lot of Javascript.
You'd want to attach to your <div>'s onmousemove event, which returns the X,Y coordinates of the cursor. Your event handler function would then test to see if the cursor is in the correct place in order to trigger an alternative onmouseover event.
Implementing the "is the cursor over an opaque pixel or not?" test can be done two ways: the first is to create a simple mathematical expression (say if the opaque parts of the image make neat rectangles, circles or polygons). The more difficult (and less browser-supported) way is to load the background image into a Canvas object and then get the current pixel value's opacity figure and take it from there, like so:
var pixel = canvas.getImageData(x, y, 1, 1).data;
var alpha = pixel[3]; // assuming RGBA
if( alpha > threshold ) onMouseOver(); // raise the event
Another alternative is to create an entirely transparent div (or some other element) positioned and sized so that it only covers the opaque part of the div below, then just test the mouseover of that element's box.
It's a bit of tweaking but why don't you add a class to your opaque div, and use JavaScript to check for it?
In jQuery:
$('div').mouseover(function(){
if ($(this).is('.opaque')) {
//Some actions
}
});