nwjs / nw.js

Call all Node.js modules directly from DOM/WebWorker and enable a new way of writing applications with all Web technologies.
https://nwjs.io
MIT License
40.29k stars 3.88k forks source link

API for taking “screenshot” of the whole page (not only the visible part of it) #827

Open Mithgol opened 11 years ago

Mithgol commented 11 years ago

Right now I am watching http://www.justin.tv/neregate and I see in real time how the newest versions of http://neregate.com/blog/2013/04/11/summer-2013-anime/ anime charts are generated in Photoshop manually.

It's sowewhat painful to watch ever for a remotely experienced web developer.

A dedicated person is spending hours of manual labor to generate a chart that could be rendered much faster as HTML5 page with a bunch of display: inline-block divs of fixed width, border-radius of correct radius, and carefully crafted shadows.

With <textarea> and CSS these blocks could be made editable on the page. With some JavaScript (such as $('textarea.whatever').autosize()) the blocks could even become autosizing on the fly (like the textarea of this GitHub issue interface).

Even the parts of there charts that are seemingly outside of HTML5+CSS3 capabilities can be imitated (for example, gradient colours of text could be achieved with “Project Rainbows”).

But then what?

Could node-webkit capture the HTML5 page to a PNG (or JPEG) file?

Unfortunately, not yet.

We have Window.capturePage(…) to capture the visible area of the window.

However, for the above described task, we would have to capture the whole page to PNG.

Can we have an API for that?

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

katanacrimson commented 11 years ago

Have you considered node-webshot? That seems like it'd be ideal for your use-case.

Mithgol commented 11 years ago

Unfortunately, PhantomJS screen capture (node-webshot is based on it) does not allow its user to interact with the page before taking a screenshot.

In my use case it's implied that some text is edited in the textareas before a screenshot is taken. Maybe also some images are replaced. That's why I need an interactive browser (such as in node-webkit) and a button that takes “whole page screenshot”.

I could utilize PhantomJS as a workaround, so that the page is edited in node-webkit and then (instead of a non-existing node-webkit capture) the page is served (with node-webkit's Node HTTP server on localhost) to the PhantomJS screenshot script, such as the following:

require('webpage').create().open('http://localhost:8888/', function(){
   page.render('rendered.png');
   phantom.exit();
});

But that's a “crutch” for a missing “limb” of an API method.

P. S.   Thank you for pointing me to that PhantomJS. Though not very helpful in the context of this issue, it's still a very interesting project that could be valuable in many applications. It's even supported as a tool in Travis CI's environment.

Ydro commented 11 years ago

Hi, @Mithgol! If use web-server then as a temporary variant use third-party service, for example http://url2png.com (the include API). Or programmatically scroll the page, and etc. Or the best: HTML5 Canvas Save Drawing as an Image.

donaldpipowitch commented 11 years ago

I would like to see this feature, too. Additionally it would be nice if I could set the resolution and quality of the screenshot.

Fenchurchh commented 10 years ago

just flew by and wanted to confirm that node-webshot works for exact this kind of request. All you have to do is feed back the altered HTML to it and it will produce lovely images.

As of February 2014 it's in the README: https://github.com/brenden/node-webshot#examples-a-simple-url-example

donaldpipowitch commented 10 years ago

I think this is a good solution for most cases, but node-webshot uses PhantomJS for rendering and even if it is based on WebKit/Blink like node-webkit the results can differ a little bit.

mitchstababs commented 10 years ago

http://jsonwhois.com/ is the best way I have seen for doing this.

felipebrahm commented 10 years ago

I was looking for an easy way to take screenshots using a real webkit browser (phantomjs is not good enough because it has a known bug which prevents it from rendering some types of web fonts) and ended up using node-webkit. For all those looking to do this same thing, here's a workaround until this feature is implemented: simply resize the window before taking the screenshot.

function takeScreenshot(win) {

  // the page I need screenshots from is using jQuery, but you can modify this to use plain JS
  height = win.window.$('body').outerHeight();
  width = win.window.$('body').outerWidth();

  win.resizeTo(width, height);

  // unfortunately, we can't use the "resize" event here because it is fired before the DOM is refreshed, that's why I'm simply using a timeout
  setTimeout(function() {
    win.capturePage(function(img) {
      var base64Data = img.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
      require("fs").writeFile("/path/to/screenshot.png", base64Data, 'base64', function(err) {
        if(err) {
          alert(err);
        }
      });
    }, 'png');
  }, 500);
}

This might be a good idea on how to implement this natively on node-webkit (automating the resize).

ruanjf commented 9 years ago

@felipebrahm Emitted after window is resized https://github.com/nwjs/nw.js/wiki/Window#user-content-resize

felipebrahm commented 9 years ago

@ruanjf not sure what you mean... my comment is pretty clear: // unfortunately, we can't use the "resize" event here because it is fired before the DOM is refreshed, that's why I'm simply using a timeout. That means that the event you mention is triggered almost instantly as soon as the window is resized, but the page is not actually repainted instantly by the browser, so it can't be used in this case.

Mithgol commented 9 years ago

@felipebrahm Thanks for a good workaround.

rufushuang commented 9 years ago

@felipebrahm On windows, you cannot resize a window size much over the screen size restriction. So what can we do, if we need to take a snapshot of a 800x2400 webpage on a 1366x768 resolution screen?

wilsoncook commented 8 years ago

REALLY looking forward!

limitedeternity commented 5 years ago

A little bit late for the party but I've made a gist to accomplish this task. Check it out. It resizes a window to match the screen size, then just scrolls down and takes a screenshot of visible part until the bottom is reached. After that, fragments are being glued into one big picture and removed.

Spoiler ``` "dependencies": { "fs-extra": "^8.0.1", "image-size": "^0.7.4", "jimp": "^0.6.4", "merge-img": "^2.1.3" } ```