Rendering DOM contents to Canvas - html

I have couple of html elements (div/span etc.) I want to be able my HTML5 Canvas to read that html and render it as it is. Later on I will convert it into bytes with the help of canvas.toDataURL() and save as an image
I am not looking for plug-in based solutions and this is specifically targeted to IE9/10
Appreciate any help towards this !!

You can perhaps use this solution:
https://github.com/niklasvh/html2canvas
html2canvas( [ document.body ], {
onrendered: function(canvas) {
/* canvas is the actual canvas element,
to append it to the page call for example
document.body.appendChild( canvas );
*/
}
});
Note: If images are loaded from non-origin (and doesn't have accept header set) it won't show up.
Optionally you can use your server as a proxy to fetch the images and serve them to client:
<img src="http://myserver.com/getexternalimage?http....

Related

Drawing photo from file to canvas rotates in Chrome based on EXIF

Chrome auto-rotates any image from a file input drawn to a canvas based on it's exif data. This is great, but iOS doesn't do the same. Is there a way to prevent this behavior in so I can just transform the image myself. With a fix I wrote it works in iOS, disabling that fix works on Android ... would rather disable/enable then play the browser identifying game.
I've tried setting the style of the image to image-orientation: none; .... but that didn't do anything. Still rotated it.
Edit: I detected this by looking to see if the 'imageOrientation' on the style object was undefined or an empty string on a newly create img tag. Maybe not a perfect test, but it worked for my situations I tested. Not sure on how future proof it is.
This should be future proof:
// returns a promise that resolves to true if the browser automatically
// rotates images based on exif data and false otherwise
function browserAutoRotates () {
return new Promise((resolve, reject) => {
// load an image with exif rotation and see if the browser rotates it
const image = new Image();
image.onload = () => {
resolve(image.naturalWidth === 1);
};
image.onerror = reject;
// this jpeg is 2x1 with orientation=6 so it should rotate to 1x2
image.src = 'data:image/jpeg;base64,/9j/4QBiRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAYAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAAITAAMAAAABAAEAAAAAAAAAAABIAAAAAQAAAEgAAAAB/9sAQwAEAwMEAwMEBAMEBQQEBQYKBwYGBgYNCQoICg8NEBAPDQ8OERMYFBESFxIODxUcFRcZGRsbGxAUHR8dGh8YGhsa/9sAQwEEBQUGBQYMBwcMGhEPERoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa/8IAEQgAAQACAwERAAIRAQMRAf/EABQAAQAAAAAAAAAAAAAAAAAAAAf/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAF/P//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAQUCf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Bf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEABj8Cf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8hf//aAAwDAQACAAMAAAAQH//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Qf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Qf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8Qf//Z';
});
}
The only way to really find out for sure if the browser rotates based on exif data: Load up an image with exif ratation and see how it comes out.
This is due to an update in Chrome 81 that now has and respects the 'image-orientation' property. https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation
Chrome now defaults all images to 'from-image' meaning it will read the EXIF data to determine the rotation data of the image. Below is basically what I did to detect if the browser supports functionality like this since future versions of iOS and other browsers expect to do this also.
function browserImageRotationSupport(){
let imgTag = document.createElement('img');
return imgTag.style.imageOrientation !== undefined;
}
I was able to use this test to differentiate the browsers:
if (CSS.supports("image-orientation", "from-image")) {
...
}
const iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
I use this snippet to check if it is IOS and only rotate the canvas ctx if it is IOS. I think older versions of android don't auto-rotate the image because I still have bugreports coming in from android users.
Setting the CSS on the canvas element as opposed to the img will fix this if you're drawing to a canvas that is part of the DOM.
canvas {
image-orientation: none;
}
As of writing the element has to be in the DOM because it uses the computed style. That only exists in a DOM context. You can read more in the issue on the Chromium tracker.
https://bugs.chromium.org/p/chromium/issues/detail?id=158753

Do Browsers Load Hidden Assets

If an asset (for example, a .jpg image) is found in the DOM, but marked with 'display: none' CSS, which browsers will download that asset, even though it doesn't technically display it to the user?
This is a website load speed question. I want to know how CSS display properties affect page load time. This question has been asked before on StackOverflow. However, that was two years ago, and I've heard rumors that things have changed since then.
Internet Explorer versions 6+ all appear to load the image. Firefox doesn't appear to load the image in versions 3-5, but do load the image from version 6 and up. As for Chrome, the image would be loaded at least as far back as version 14. Safari 4 and up also load the image.
Run the test yourself: http://jsfiddle.net/jonathansampson/4L9adwcu/
(function () {
var image = document.createElement( "img" ),
timeout = setTimeout(function timeout () {
alert( "Image was not loaded." );
}, 3000);
function loaded () {
clearInterval( timeout );
alert( "Image was loaded." );
}
if ( image.addEventListener ) {
image.addEventListener( "load", loaded );
} else if ( image.attachEvent ) {
image.attachEvent( "onload", loaded );
}
image.style.display = "none";
image.src = "http://gravatar.com/avatar/a84a8714fd33f6676743f9734a824feb";
document.body.appendChild( image );
}());
If I had to speculate as to why this was the case, I suspect it would have something to do with loading DOM resources as quickly as possible so they will be ready when they're needed. If the Image is not added to the document (meaning we remove document.body.appendChild...) it will not be requested.
You can keep images from being loaded by using a data-* attribute instead. When the image is needed, swap the src value out for the data-src value, and at that point the browser will load the image:
<img data-src="http://example.com/dont-load-me.png" />
The actual swap would be fairly straight-forward:
imageReference.src = imageReference.getAttribute( "data-src" );
I should mention that I am an engineer on the Internet Explorer team.
With specific regard to images, this test has already been done by W3 located at: http://www.w3.org/2009/03/image-display-none/results

HTML5 File API Image Preview and Reset

Plenty of examples of using HTML5 to preview an image selected in file field but I can't find any examples with a remove/reset link - after selecting image and writing image to canvas is it possible to reset field AND reset the image or effectively hide it?
if you are referring to the html5imageupload by STBeets from here then you have to access the html5imageupload object through the function of a callback. For instance, if you are applying this plugin to a #formuploader div:
$('#formuploader').html5imageupload
({
onAfterProcessImage : function(obj)
{
obj.reset();
}
});
You can do this with any of the callbacks available

Stop img tags from flickering when re-rendering with JavaScript

Our web app is built entirely in JS.
To make it snappy we cache resources (models) between page views and reload the resource when you view a page.
Our flow is like this:
The user is in ViewA
The user switches to ViewB
We use the cached resource to render ViewB
We start a fetch for resource
When the resource is fetched we render again
This has a nasty drawback of causing <img> tags to flicker, ever if they are the same.
The problem is that Backbone.js, which we use, doesn't tell us if anything changed when fetching a collection, just that it was fetched.
Here's a quick demo of what I mean: http://jsfiddle.net/p7DdG/
It only happens in webkit and with <img> tags, not with background images as you can see.
We think it's kinda ugly to use background-image instead of a proper img tag.
Is there any solution to this?
The problem is gone in Chrome 19, problem solved :)
Not knowing exactly how the URL of each image is being built I'm not certain this will work, but could you check the src attribute of each image tag against the one you are replacing it with before doing the replace?
e.g.
var newImageSrc = "http://www.google.com/intl/en_com/images/srpr/logo3w.png";
if (newImageSrc != $("img").attr("src")) {
$('img').replaceWith('<img src="'+newImageSrc +'">');
}
Alternatively - load the image offscreen, and attach an event handler to the onload event of the image, which moves the image to the current image's parent tag, and remove the old one.
e.g.
var oldImage = $("#oldImageId");
var newImageSrc = "http://www.google.com/intl/en_com/images/srpr/logo3w.png";
var newImage = new Image();
$(newImage).load(function (event) {
$(oldImage).parent().append(newImage);
$(oldImage).detach();
});
$(newImage).attr("src", newImageSrc);
I ran into the same problem and noticed that sometimes images do flicker and sometimes don't. Even in latest Chrome (v33 as of now).
For posterity, flickering happens with uncached images.
In my case, Cache-Control: public, max-age=31536000 totally eliminated it.

Internet Explorer CPU usage goes high after an animated GIF image has been displayed

I have been working on a web application for some time now and did notice that the CPU usage was a bit high a long time ago, but the development has been halted for a while.
Recently I started developing again and discovered that the CPU usage goes high after an animated GIF image has been display as the background image.
I use Ajax to update content and apply CSS classes to elements to display a loading indicator. I remove the CSS class when the content has finished loading. If I comment out the classes in the stylesheet that contains the GIFs, everything looks normal.
I have tested it in Internet Explorer 7 and Internet Explorer 8.
What can be done to alliviate this problem?
var blabla = function() {
var element = $('id of element');
element.addClassName('a css classname');
new Ajax.Request({some parameters},
onSuccess: function() {
element.removeClassName('a CSS classname');
....
},
onFailure: function() {
element.removeClassName('a CSS classname');
....
},
onComplete: function() {
element.removeClassName('a CSS classname');
....
}
}
}
It's possible that this issue is related to how Internet Explorer loads data needed from CSS classes. Might I suggest an alternate approach: instead of using the loading animation contained within a CSS class, just put the .gif in a visible <img> tag straight into the HTML. Then, when onSuccess or another method is called, you can just run:
$("#ajax-gif").hide();
As already commented on, it looks like it doesn't have anything to do with the GIF image itself, especially not one at 20x20 pixels.
If you are changing the background of a page with a GIF image, it must redraw what's on top of it to a certain extent.
To bring down the CPU usage, either reduce what's on your page before you change the background or stop using GIF images, it's 2011!
If this problem is only occurring in Internet Explorer, it is indeed the redraw issue that commenters to Barnzy's answer have talked about. It should create similar problems across other browsers as well.
One solution would be to use the JavaScript onload event handler to preload all of your GIF images in the DOM, which would reduce the need to redraw and should stop escalating the CPU cycles.
I agree that in 2011 using GIF images is probably not the best approach for web design.