Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify output image dimensions #21

Closed
cronoklee opened this issue Feb 12, 2016 · 22 comments
Closed

Specify output image dimensions #21

cronoklee opened this issue Feb 12, 2016 · 22 comments
Assignees

Comments

@cronoklee
Copy link

It would be extremely useful to be able to optionally specify the dimensions for the output image and have the image rendered at a higher resolution than the DOM element itself.

This would have numerous uses but would be particularly useful for printing the image afterwards. Printing at 72dpi (screen resolution) is not advisable!

One simple idea for making this happen is to scale the DOM element before rendering using the CSS *_zoom *_property or the CSS *_transform *_property. I attempted this but the bounding box for the element seems to remain the same, so while the elements do render larger, as expected, the image itself is cropped to the original size of the element, cutting out the bottom and right part of the element.

@tsayen tsayen self-assigned this Feb 12, 2016
@tomgallagher
Copy link

+1 This would certainly be an enhancement

@tomgallagher
Copy link

Could you not wrap the cloned dom node in a wrapper div and then start the transform process? I was working on my own zoom function for something else the other day and the transform property worked OK for text and not so great for images/graphics.

@tsayen
Copy link
Owner

tsayen commented Mar 9, 2016

I think zoom property would be the way to go, I gotta check that. (yes, raster images will not look good when zoomed, but we can't do anything about that)

@stevie-p
Copy link

stevie-p commented Apr 6, 2016

+1. This would be a useful feature for creating thumbshots with consistent width/height irrespective of browser width.
My workaround at the moment is to clone and render the element at the required size before passing to dom-to-image:

var clone = element.cloneNode(true);
clone.setAttribute("style", "width: 640px; height: 480px;");
document.body.appendChild(clone);
domtoimage.toBlob(clone).then(function (blob) {
    clone.remove();
    /* Do something with the blob */
}

Although for me this doesn't produce exactly the same result for different browser widths at the moment due to (Bootstrap's) media queries. It would be good if dom-to-image rendered the node and calculated the css styles based on an (optional) browser width / media query.

@tsayen
Copy link
Owner

tsayen commented Apr 24, 2016

Hi, with recently added width, height and style options I think you can solve your issue. Feel free to reopen this issue otherwise

@tsayen tsayen closed this as completed Apr 24, 2016
@cronoklee
Copy link
Author

Looks great, thanks tsayen! I cant find any examples on how the style option works. I'm trying to double the size of the output but I'm not sure what syntax is expected:

domtoimage.toBlob(el, {style:"transform:(scale(2,2))"})

@tsayen
Copy link
Owner

tsayen commented Apr 25, 2016

style should be an object (see this test)

@cronoklee
Copy link
Author

Thanks. It's a clever solution and it would work well but there is still an issue unfortunately.

Is it possible to move the code that draws the output image boundaries, to after the new styles have been applied? If the boundries of the element are changed by the new styles, the resulting image remains the old size.

For example, domtoimage.toBlob( $(el), { style: {'zoom':zoom} }) misses part of the element because it ignores the new zoomed size. Adding width and height in the rendering options helps slightly but it means that any text inside the element needs to be re-styled as it's changing the element width.

@tsayen
Copy link
Owner

tsayen commented Apr 25, 2016

Maybe try also to add width and height properties to options? Also, you might want to use transfrom: scale(...) instead of zoom and it should scale the text as well. Correct me if I'm wrong.

@cronoklee
Copy link
Author

cronoklee commented Apr 25, 2016

I looked into this a bit more and I think using JS element.scrollWidth and element.scrollHeight in dom-to-image.js is actually the problem.

If we use getBoundingClientRect() instead to get the node's width & height, it should return the real dimensions after scaling/transforms, etc.

More info here

@tsayen
Copy link
Owner

tsayen commented Apr 25, 2016

just to make sure, does that screenshot somehow resemble your use case? (it's from a test I've just written)

screenshot from 2016-04-25 20 28 52

@tsayen
Copy link
Owner

tsayen commented Apr 25, 2016

concerning the getBoundingClientRect() - unfortunately it seems to return the same value. Maybe because this node was never actually rendered - since it's a clone of the original one, thus it's bounded rectangle was never calculated.

@cronoklee
Copy link
Author

cronoklee commented Apr 25, 2016

Thanks for looking into this tsayen, That is more or less what I have but I have a line of centered text outside the grey box which is to be included in the image.

I made a quick fiddle to show how getBoundingClientRect() behaves differently. CSS zoom doesnt work at all but scale is calculated correctly using getBoundingClientRect() .

I tried replacing all instances of .scrollWidth in the src code to .getBoundingClientRect().width and it did help but the resulting image is still too small. My node is 300px wide and now I'm getting an image of 450px wide, (I'm expecting 600px) when I scale the element before hand using plain CSS. Using domtoimage.toBlob( el, { style: {'transform': 'scale(2)'} }) does nothing, and returns the same 300px image it always did. (probably as you suggested, because it is never rendered)

Have you any idea why it might be reducing the size after calculation? If I run el.getBoundingClientRect(), I get 600 so where's the 450 coming from i wonder...

@tsayen
Copy link
Owner

tsayen commented Apr 25, 2016

take a look at this jsfiddle - does it do what you want?

@cronoklee
Copy link
Author

Almost. Mine is more like this. It should really just scale the dom node exactly without any restyling.

@tsayen
Copy link
Owner

tsayen commented Apr 25, 2016

that's a strange behavior (I mean the scaled text overflows). But if you wrap it into a div, the problem is fixed

@cronoklee
Copy link
Author

cronoklee commented Apr 25, 2016

Thanks I'll try putting a wrapper on it in the morning and see if it works. If so, it might work well to do it from the src code - wrap everything in a div before rendering

@cronoklee
Copy link
Author

cronoklee commented Apr 26, 2016

Hi tsayen,
Setting width and height and adding the top left origin and wrapping text nodes in a wrapper div has solved the problem! Thank you so much for all your help!

Can I suggest you add one more rendering option called "scale" which automatically sets these settings for users? It's a very powerful feature to be able to render DOM nodes at any resolution and as we have seen, this feature is not obvious or easy to use.

Here's my final, working function for downloading a scaled image, in case someone else wants to use it: (FileSaver.js is required)

function downloadAsImg( el, filename, scale ){
    if( scale!=undefined ) var props = {
        width: el.clientWidth*scale,
        height: el.clientHeight*scale,
        style: {
            'transform': 'scale('+scale+')',
            'transform-origin': 'top left'
        }
    }
    domtoimage.toBlob( el, props==undefined ? {} : props).then(function (blob) {
        window.saveAs(blob, filename==undefined ? 'image.png' : filename);
    });
}

@tsayen
Copy link
Owner

tsayen commented Apr 26, 2016

Hey, glad it worked for you :) The feature you're suggesting absolutely
makes sense.

On Tue, Apr 26, 2016 at 11:37 AM, cronoklee notifications@github.com
wrote:

Hi tsayen,
Setting width and height and adding the top left origin and wrapping text
nodes in a wrapper div has solved the problem! Thank you kindly for all
your support.

Can I suggest you add one more rendering option called "scale" which
automatically sets these settings for users? It's a very powerful feature
to be able to render DOM nodes at any resolution and as we have seen, this
feature is not obvious or easy to use.

here's my final, working function for downloading a scaled image in case
someone else wants to use it: (FileSaver.js
http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js is
required)
function downloadAsImg( el, filename, scale ){
if( scale!=undefined ) var props = {
width: el.clientWidth_scale,
height: el.clientHeight_scale,
style: {
'transform': 'scale('+scale+')',
'transform-origin': 'top left'
}
}
domtoimage.toBlob( el, props).then(function (blob) {
window.saveAs(blob, filename==undefined ? 'image.png' : filename);
});
}


You are receiving this because you modified the open/close state.
Reply to this email directly or view it on GitHub
#21 (comment)

@blasto333
Copy link

@tsayen

Width, height, and style options are nice; but would love if we could render that image at specific browser width without having the user resize their browser (so media queries can be provided).

html2canvas has this; but your library is faster and cleaner; but I cannot port from html2canvas unless I have a way to render the image with a certain width and also it would be great if we could render with media = printl

@michalzareba0001
Copy link

Had some issues to generate 10x bigger jpeg file, but it's finally working ;) Thank you!

My code:
`function generateJpeg() {
var node = document.getElementById('baner_image');

domtoimage.toJpeg(node, {
    quality: 0.99,
    width: node.clientWidth * 10,
    height: node.clientHeight * 10,
    style: {
        'transform': 'scale(10)',
        'transform-origin': '50% 50%',
    }
})
    .then(function (dataUrl) {
        var link = document.createElement('a');
        link.download = 'yourbaner.jpeg';
        link.href = dataUrl;
        link.click();
    });

}`

@aryanbhatt-clvt
Copy link

How to increase the domnode size which we have captured through findDomNode?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants