Canvas with moving bubbles over a blurred div - javascript

I have a canvas which has bubbles moving randomly, now when i put it on to a div which has a filter
-webkit-filter: blur(50px);
then the canvas bubble movement fps drops down and smoothness reduces.
I am not getting what is the issue.
Version with blurred background : http://freakengineers.com/bubbles/index.php
Version with normal background : http://freakengineers.com/bubbles/index2.php

You can load and blur the image (but I don't know if you can use a built in blur algorithm - I've used StackBlur) in a separate canvas as a sort of buffer, then copy it to your main canvas on each frame. JSFiddle: http://jsfiddle.net/1m8rbt7j/
Add a new <canvas> element to the HTML, load your image into it and then blur the new canvas:
var blurimg = new Image();
blurimg.onload = function() {
var blurcv = document.getElementById('blurcanvas');
blurcv.getContext('2d').drawImage(blurimg,0,0);
stackBlurCanvasRGB('blurcanvas', 0, 0, 1580, 730, 50);
};
blurimg.src = 'http://i.imgur.com/WaMsYBC.jpg';
(I had to use a different image to get around cross-origin rules.)
Then just draw the content of the new canvas to your main canvas at the start of each frame:
context.clearRect(0,0, w,h);
context.drawImage(document.getElementById('blurcanvas'),0,0);
With your versions I get 30 FPS without the blur and 20 FPS with it. I get 30 FPS with the blur in my version.

Related

Exact clearRect on moving clipped image on canvas

I'm trying to make a simple side scrolling avoider game in html/javascript using canvas. Having some troubles removing (clearRect) the moving variable height clipped image so it doesn't also remove the sprite/image the user is controlling above, I can get it to remove everything above/below the image but cannot find how to exactly remove the moving shadow image so it doesn't remove the hero of the game as well whilst animating!
https://jsfiddle.net/6k354f5x/3/
Currently the banana is also cleared, any help would be greatly appreciated!
//<canvas id="board" width="480" height="640"></canvas>
//Getting the canvas
var board = document.getElementById("board");
var cx = board.getContext("2d");
//Example Images
var pipe = new Image();
pipe.src = "http://www.appcycle.me/flappy/img/pipe.png";
var hero = new Image();
hero.src = "http://vignette2.wikia.nocookie.net/drunken-peasants-podcast/images/9/9c/Banana-in-8-bit.png/revision/latest?cb=20150821213530";
//Pipe randomness calculated from board height
var pipeVariation = Math.floor((Math.random() * 250) + 1);
var pipeY = 456;
var pipeX = 350;
//interval
var timer = setInterval(function() {
//draw the hero
cx.drawImage(hero, 0, 150);
//clear the afterimage
cx.clearRect(pipeX, 80, pipe.width / 1.6, pipe.height / 1.6);
//move it on the X-axis some px
pipeX -= 2;
//draw the clipped pipe with some Y-axis placement variation from pipeVariation variable
cx.drawImage(pipe,
0, -pipeY+pipeVariation, pipe.width, pipe.height,
pipeX, 80, pipe.width / 1.6, pipe.height / 1.6)
//Temporary to keep pipe from running away while testing
if (pipeX <= 0) {
clearInterval(timer);
}
});
Full canvas animation redraw everything.
When rendering canvas animation that has many elements, such as a game, the most effective method to render is to redraw everything every frame.
At the start of every frame you either clear the whole screen or draw the background image over the top of the last frame (same as clearing) then draw the game elements one by one in order of lowest to highest z-index (where the highest element is on top of all the other elements)
This makes the code very simple as opposed to complex dirty rects schemes that quickly become very complex and can reduce performance.
On all but a small number of devices most rendering is done via the GPU and is very fast (NOTE this does not apply to moveTo, lineTo, shadows, arcs, text, ellipses) Clearing and re-rendering everything can easily be done in 1/60 of a second creating smooth high quality animations
Note on shadows. Do not use the context2D shadows, most browsers and the hardware do not do it well at all and can be a major performance hit. This can be so even if you render one shadow for one small image. It is best to either pre render the shadow, or load a separate shadow as an image.

HTML Canvas - auto re-size as its content grows

How can i set an HTML5 canvas to auto re-size when the content inside it grows beyond its margins? I am developing a family tree application and when a generation comes wider than the defined limits of the canvas, lines which connect nodes together disappear.
With canvas there is no automatic features. It's a passive bitmap which you can use to draw graphics to, so all forms of logic need to be implemented "manually".
So in order to have it grow you will have to track positions and sizes of everything that is being drawn so you can calculate the total bounding box for the current graphics.
If the position + size of that bounding box exceed the canvas size, update the canvas size with that (canvas size = bounding box' position + size).
However, when resizing a canvas all current content as well as state(s) are lost so you will have to re-render and reinitialize the content as well as if was the first time drawing to it. This is something you need to plan for and incorporate into the design.
Again, it really depends how you're drawing the content, but here is an example of how to do it when drawing an image to canvas..
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
base_image = new Image();
base_image.src = 'someImaeg.png';
base_image.onload = function(){
document.getElementById('canvas').width = base_image.width;
document.getElementById('canvas').height = base_image.height;
context.drawImage(base_image, 0, 0);
}
Fiddle

How to get color that is behind a transparent element?

I am working on a site where the body has many color. When the content is scrolled down the background of the content changes.
In the below image u can see body text with blue color background. So when the content is scrolled down with the scrollbar then the background image should also scroll along with the content.
So what happens is when scroll bar stops at a color like blue then automatically the menu header(Home) background should change to blue.
First of all we should know what we want to do. Step one is actually get a color of the image, thus acces a property of the image.
However the browser cannot get direct information of the image itself(You can, of course, get information from the element of the image). However one webbrowser drawing method let us control every aspect of a image: Canvas.
So first we have to convert our image to an canvas element.
This is fairly simply done with drawImage(img, posx, posy, canvasWidth, canvasHeight);
We will also stretch the canvas image + the element to the entire screen. The reason we want to define to size also at the canvas is because this way the canvas will calculate every new generated pixel, so we can acces every of the new pixels:
var screenWidth = window.innerWidth,
screenHeight = window.innerHeight,
c = document.createElement('canvas');
ctx = c.getContext("2d"),
img = document.getElementById("image");
c.width = screenWidth;
c.height = screenHeight;
ctx.drawImage(img, 0, 0, screenWidth, screenHeight);
$(c).attr('id', 'c');
$('body').prepend(c);
$(img).remove();
An Canvas element as is dynamically made and will fit to the screen size(Note that this is only at first start of the webbrowser. So when you resize the canvas will not resize with the screen).
We remove the image as it is no use anymore. It's a good practive to transform from image to canvas in my opinion. As you will be certain that the image will be loaded in the browser first and then transformed to a canvas element.
Next we're going to acces a pixel. You can acces pixel data with getImageData(offsetX, offsetY, sizeX, sizeY).data; And RGBA color array will be returned.
Now the offsetX and offsetY will be the offset of the element color picker. Note that this elements offset should be relative to the webbrowsers viewport as the background is fixed You can do this with getBoundingClientRect();
The size is just 1x1 as we want 1 pixel.
This all should happen when the user is scrolling, you can catch the scroll event with .scroll(function); :
$(window).scroll(function () {
var offset = document.getElementById('color').getBoundingClientRect(),
offsetX = offset.left,
offsetY = offset.top;
var color = document.getElementById('c').getContext('2d').getImageData(offsetX, offsetY, 1, 1).data;
$('header').css('background-color',"rgba("+ color[0] + ', ' + color[1] + ', '+ color[2] + ', ' + color[3] + ")");
});
Where we add the rgba array colors just with the first 4 indexes(Because and rgba collor pattern never has more as 4 values) with plain css to the header element.
Loading External image into a canvas
When you want to transform an external image to a canvas element you might get this error:
Cross-origin image load denied by Cross-Origin Resource Sharing policy.
It is for security reasons that you can't fully acces this image.
As explained here: HTML 5 canvas getImageData from an externally-loaded image
There are some external hosts that supports this, for example dropbox.
Local
However when you just store it locally it will just work fine.
jsFiddle
This method was tested in chrome, IE and firefox.
I want to use those external (dropbox) files
I'm not sure why this happens but for some reason with this method there are still some security diffecults. To enable this CORS you have to add a image property .crossOrigin = "Anonymous";. However when you load the image with HTML the the element has been made without this property. So you should assign this property when the image is created:
var canvas = document.getElementById("c"),
ctx = canvas.getContext("2d"),
screenWidth = window.innerWidth,
screenHeight = window.innerHeight;
// Using image WITH crossOrigin=anonymous
// Succeeds in Chrome+Mozilla, Still fails in IE
var externalImage2 = new Image();
externalImage2.onload = function(){
canvas.width= screenWidth;
canvas.height= screenHeight;
ctx.drawImage(externalImage2, 0, 0, screenWidth, screenHeight);
// this will FAIL on a CORS violation
}
externalImage2.crossOrigin = "Anonymous";
externalImage2.src="https://dl.dropboxusercontent.com/s/8g8lgmdx341j1d6/rainbow_gradient_horizontal.jpg";
This is just an picture i uploaded to my dropbox where i just shared the photo. Note:
The way to convert a share link to a direct link is to change the domain from "www.dropbox.com" to "dl.dropboxusercontent.com". See https://www.dropbox.com/developers/blog/53/programmatically-download-content-from-share-links.
source: Cross-origin image load from cross-enabled site is denied
This creates an image and puts it into an excisting canvas element. So note that you should have a canvas element into your HTML.
jsFiddle
This method does only work for chrome and firefox as other browsers still have some security issues.
Additional note is the pixel that gets captured is the top-left pixel of the 'color-pick' element. You can adjust this offset if you want it to catch, for example, the middle pixel of the element.
This was a very interesting question. I hope it helped!
well, you may give background color of the home bar as transparent if you have no band between the home and the content.
.home{
background:transparent;
}

How to blur ImageData in different coordinates

I am studying HTML5 and building my slot game from scratch. when spinning, i want to implement a blur in Y to imageData. I try some algrothim already to imageData, it makes everything become very slow, and i try webkitFilter for canvas's style as well, it is only available for radius. Do you have any good suggestions for it?
You can pre-render your motion blurred slot spinning wheel:
Start with an image that has all the slot elements arranged vertically.
Create vertical motion blur using a temporary canvas (see code below).
To "spin", animate the taller wheel canvas through the slot window.
To efficiently create vertical motion blur:
Repeatedly drawing the vertical slot image.
Increase the Y-offset with each draw.
Decrease the opacity with each draw.
This is the y-blur code:
function motionBlur(wheelContext, image, blurAmount) {
wheelContext.clearRect(0,0,wheelContext.canvas.width,wheelContext.canvas.height)
var y=0;
while (++y <= blurAmount) {
wheelContext.globalAlpha=1/y;
wheelContext.drawImage(image, 0, 0, image.width, image.height+y);
}
}

canvas - layer small image on larger background image, merge to single canvas pixel data

How do I merge a smaller image on top of a larger background image on one canvas. The smaller image will move around. So I will need to keep reference of the original background pixel data, so that the each frame the canvas can be redrawn, with the overlay in its new position.
BgImage: 1280 x 400, overlayImage: 320 x 400, overlayOffsetX: mouseX
I think it is common to draw whole scene each time you want to change something, so:
context.drawImage(bgImage, 0, 0);
context.drawImage(overlayImage, overlayOffsetX, 0);
UPDATE
You could manually compose image data of two images with making copy of background image data
or
do something easier, probably faster. You could create new canvas element (without attaching to the document) which would store image data in easy to manage form. putImageData is good if you want to place rectangular image into the canvas. But if you want to put image with transparency, additional canvas will help. See if example below is satisfying you.
// preparation of canvas containing data of overlayImage
var OVERLAY_IMAGE_WIDTH = 320;
var OVERLAY_IMAGE_Height = 400;
var overlayImageCanvas = document.createElement('canvas');
overlayImageCanvas.width = OVERLAY_IMAGE_WIDTH;
overlayImageCanvas.height = OVERLAY_IMAGE_HEIGHT;
overlayImageCanvas.getContext('2d').putImageData(overlayImage, 0, 0);
// drawing scene, execute this block every time overlayOffsetX has changed
context.putImageData(bgImage, 0, 0);
context.drawImage(overlayImageCanvas, overlayOffsetX, 0);

Categories

Resources