HTML 5 - Use <img> element vs. Canvas drawImage - javascript

I'm working with a customHTML section, currently I'm using a canvas html5 element. Now, I need to display an image, but not sure if it will be a good idea to draw it in this canvas element or use a <img> html element directly.
My first approach is this:
a)
var customHTML = "<canvas id='viewport'></canvas>"
var canvas = document.getElementById('viewport'),
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src = 'img/base.png';
base_image.onload = function(){
context.drawImage(base_image, 100, 100);
}
Second approach:
b)
var customHTML = "<img src='../images/myicons/pin.png'>"
I would like to know if there is any advantage in using this canvas and drawing logic, instead of using directly an <img> html element. Performance? Resources?
Please, let me know if a) or b) is the best approach.
I want to use this customHTML element as a pushpin in Bing Maps.
Any help will be appreciated.

The img element works since the dawn of time. Png image support also since a very long time. The other piece of code always needs Javascript, and needs a more modern browser that supports HTML 5 canvas. Some of these advantages may not apply when the usecase is a pushpin in Bing Maps, since Bing Maps will have requirements on its ownn.
In general performance there won't be much difference, and this may even vary between browsers and versions. Drawing an image is pretty easy anyway (compared to, say, animation), so I wouldn't worry about it.

base_image.onload = function() {
context.drawImage(base_image, 100, 100);
}
assigns the function as an event handler that gets called only when the image in question has finished downloading.
base_image.src = 'img/base.png';
begins the download of the image and it may be regarded as an asynchronous (bon-blocking) call for the image.
<img src='../images/myicons/pin.png'>
begins drawing as the page loads and you get this line-by-line display of the image as it's data trickles in.
The difference between these approaches is at least partially a UI consideration and especially evident with large images and slow internet connection. Not so much an issue with fast connections, small/cached images.

Related

Creating a matrix of canvases

I'm trying to create a matrix of canvases which each would be the size of the device-width and device-height. The idea is to have this matrix from where the view would move from canvas to canvas by pressing a button. So basically you would only see one canvas at a time, and others would locate up/down and left/right out of the screen.
I'm really new to javascript and webdesign so I'm not sure if the canvas element is the best way to do this at all. I don't have any code to show because I just started this project and wanted to ask first to get it right from the begining.
Is the approach of multiple canvases a good way to go or what would be better option and how to do it?
Thanks!
This is a small start to get you started with how you can make canvas elements dynamically. You should look at W3 Schools for reference on how to edit DOM elements. Create element in the DOM.
window.onload = function() {
var canvasElements = [];
var canvas1 = document.createElement("canvas");
canvas1.id = "canvas1";
canvasElements.push(canvas1);
}
What you want in your solution
1) Make a CSS class with full width and height of the page.
2) Add canvas elements dynamically to the page using JavaScript and DOM manipulation.
3) For each canvas, add it to the DOM, and do the logic you want with it (render elements and draw circles / images whatnot). This will require a lot of JavaScript, so I would suggest you start out simple with a single canvas.
I hope that gets you going.

Clip by mask defined by pixel image or prevent drawing outside of that mask

I'm two days into js,html and css programming. So very newbie!
Following and building upon this TUTORIAL
Q1: How can I add this male into the background (see figuere 1.) and prohibit any strokes outside of the borders?
Adding image to background was no biggy!
function make_base()
{
base_image = new Image();
base_image.src = 'img/bmapFront.gif';
base_image.onload = function(){
context.drawImage(base_image, 0,0);
}
}
There is a context.clip function, not sure if I can use pixel form as clipping path. Making tons of "image substractions" isn't the best way.
Any suggestions
Edit:
Did the Job for me: VeryHelpful
var frontPath = new Path2D ("M 133.41,17.00 C 141.37,2.41 160.66, !VERY LONG! ")
context.clip(frontPath);
Messy strokes!
He should look like this. Then I want to save him.
Although there is such a thing as ctx.clip(), this is sometimes not what's wanted as it's impractical to use a path.
The solution that I like involves creating a virtual empty canvas onto which you draw your pixel image. Through various manipulations, like using ctx.getImageData and similar to make sure you only get one kind of color or apply other filters only once, you can obtain an image that seems to be empty (alpha of 0, mostly) in the places where you want to clip other images or paths out.
At that point, you'd use ctx.globalCompositeOperation = 'source-atop', or pick another one you might want to use from mdn's list of globalCompositeOperations.
At this point, you can just draw this virtual canvas image onto the main canvas

JavaScript image opacity is being ignored

I'm trying to display an image via JavaScript and set its opacity, but the opacity I've specified is getting ignored. I've tried all the latest browsers, but am mainly using IE11. The image I specify displays fine and I can position, scale, and rotate it without any problem. I've done extensive searches on this site and others to try to identify the problem but so far haven't had any luck. I've also tried rebooting my PC and using another PC to check the results. Nothing seems to help. Even trying a PNG file.
Here's my code:
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
imageObj.onload = function () {
imageObj.style.filter = "alpha(opacity=20)";
imageObj.style.opacity = 0.20;
ctx.drawImage(imageObj, 10, 10);
};
Oh, prior to this code, the background color was set to pure white (#ffffff). I tried playing around with the background color, but it seemed to make no difference.
Try context.imageSmoothingEnabled = true;. The canvas element has a global alpha attribute that lets you apply partial transparency to anything you draw. You can see more here.
The CSS opacity is applied to the Node and not to the image data, this means that when you draw to your canvas' context, this meta information is forgotten.
Instead, you can use context.globalAlpha
imageObj.onload = function () {
var x = ctx.globalAlpha;
ctx.globalAlpha = 0.2;
ctx.drawImage(imageObj, 10, 10);
ctx.globalAlpha = x;
};
Beware though, this may not be safe if you're expecting to draw a lot asynchronously, so you may even want to create a second canvas for fixing the alpha, then export/import into the canvas you're really interested in, getImageData, putImageData.
Another option could always be to use an image format which supports an alpha channel, such as PNG and just serve the images at the desired opacity. This would cut down on processing, but may increase bandwidth usage (really depends on the image contents to how well each format compresses the data, e.g. JPEG is designed for photos/real world images whereas a PNG may better compress an artificial image with no noise).

How to copy a kineticjs stage to another canvas

I am writing an app where there may be hundreds of canvasses on a page. Rather than having the overhead of an individual stage for each canvas, I decided to have an editor that holds a stage. Once editing is completed it should copy the stage content to another canvas.
Stage offers toImage and toDataURL to get hold of the content however according this performance test, both those methods will be very slow compared to context.drawImage.
See: http://jsperf.com/copying-a-canvas-element
Since I only use one layer in a stage and a layer holds a canvas, I thought I could do this:
desticationCtx.drawImage(layer.getContext().canvas, 0,0);
unfortunately that doesn't produce any results (It does run though)
Since a stage has a bufferCanvas I also tried:
destinationCtx.drawImage(this.stage.bufferCanvas.element,0,0);
Again no results although I can see the content on the stage canvas on the page.
However if I dig down in my page to get to the actual canvas created and used by kineticjs:
destinationCtx.drawImage(document.getElementById('mydiv').children[0].children[0],0,0);
I do get results. What is the proper way to copy kineticjs stage content to another canvas?
access a layer canvas element like this:
var canvasElement = layer.getCanvas().getElement();
and the context like this:
var context = layer.getCanvas().getContext();
Here's the docs of interest:
http://kineticjs.com/docs/Kinetic.Layer.html#getCanvas
http://kineticjs.com/docs/Kinetic.Canvas.html
With the last and newer version of kineticjs the method from the as correct marked answer doesn't work anymore.
Nowadays I just used the following approach to get the kineticjs main canvas - with the help of jquery:
var canvas = $('#canvasDiv').find('canvas');
console.log("Canvas: %O", layerCanvas);
Just replace
#canvasDiv
with the ID of your container.

How to optimize animation on canvas? HTML 5

I am faced with a problem that slows down animation on a canvas, as various pictures move left, right, up and down. I need advice on how to optimize the animation.
It is important that the animation works on all main browsers, in particular: Chrome, Firefox and Internet Explorer.
Is it possible to optimize the animation? Maybe put a delay on the drawing? Thank you in advance.
In javascript you can use the setInterval and setTimeout functions to create delays and throttle the frame rate.
for instance if you wanted to make your drawing loop approximately 30 FPS you could have some code that looks like this:
function draw(){
var canvas = document.getElementById('myCanvas');
//create the image object
var img = new Image();
//set the image object's image file path
var img.src = "images/myImage.png"
//check to see that our canvas exists
if( canvas.getContext )
{
//grab the context to draw to.
var ctx = cvs.getContext('2d');
//clear the screen to a white background first
//NOTE to make this faster you can clear just the parts
//of the canvas that are moving instead of the whole thing
//every time. Check out 'Improving HTML5 Canvas Performance'
//link mention in other post
ctx.fillStyle="rgb(255,255,255)";
ctx.fillRect (0, 0,512, 512);
//DO ALL YOUR DRAWING HERE....
//draw animation
ctx.drawImage(img, 0, 0);
}
//Recalls this draw update 30 times per second
setTimeout(draw,1000/30);
}
This will help you control how much processing time the animation is taking. Thus if you find that your animation is going too slow you can increase the frame rate by changing the denominator '30' to something like '60' fps or anything that really works well for your program.
As far as optimizing goes in addition to setTimeout() the way you draw your animations is critical too. Try to load all your images before you render them this is called "Preloading". That is if you have a bunch of different images for each animated cell then before you call your draw function load all the images into an array of images like so:
var loadedImages = new Array();
loadedImages[0] = new Image();
loadedImages[0].src = "images/animationFrame1.png";
loadedImages[1] = new Image();
loadedImages[1].src = "images/animationFrame2.png";
loadedImages[2] = new Image();
loadedImages[2].src = "images/animationFrame3.png";
loadedImages[3] = new Image();
loadedImages[3].src = "images/animationFrame4.png";
you could even put them in a hash if it makes sense for you app where instead of
loadedImages[0] = new Image();
loadedImages[0].src = "images/animationFrame1.png";
you do this
loadedImages['frame1'] = new Image();
loadedImages['frame1'].src = "images/animationFrame1.png";
once you have all your images loaded you references them for drawing by doing calling them like so:
//Using the integer array
ctx.drawImage(loadedImages[0], 0, 0);
//OR
//Using the stringed hash
ctx.drawImage(loadedImages['frame1'], 0, 0);
You want to separate your loading process from your rendering process because loading images is process intensive thus will slow your animations down if you are loading things while rendering.
That is not to say that you can't ever load anything while rendering, but instead just be conscience that this will slow animation speed down.
Here is an article on preloading images.
There is another post on here which talks about consistent animation speed on all browsers here
Note the link posted by the green checked answer
Other things to be noted are making sure to only clearing and redrawing bounding boxes as mentioned in the post with HTML 5 canvas optimization. That link has some really good techniques to be conscience of while developing canvas animations.
Here are some frame works as well which might come in handy to cross compare what you are doing to what other engines are doing.
Hope some of this helps. I am new to javascript (only started coding with it about 2 weeks ago) and so there could be better ways to do things but these are the things I have found thus far.
window.requestAnimationFrame() is one sure way to make your animation run smoother.
https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame
(cross browser http://paulirish.com/2011/requestanimationframe-for-smart-animating/ )
However it doesn't fix the possible problems with your drawing code which was missing from the question.

Categories

Resources