Render HTML to an image

后端 未结 17 1771
栀梦
栀梦 2020-11-22 16:06

Is there a way to render html to image like PNG? I know that it is possible with canvas but I would like to render standard html element like div for example.

相关标签:
17条回答
  • 2020-11-22 16:28

    You can't do this 100% accurately with JavaScript alone.

    There's a Qt Webkit tool out there, and a python version. If you want to do it yourself, I've had success with Cocoa:

    [self startTraverse:pagesArray performBlock:^(int collectionIndex, int pageIndex) {
    
        NSString *locale = [self selectedLocale];
    
        NSRect offscreenRect = NSMakeRect(0.0, 0.0, webView.frame.size.width, webView.frame.size.height);
        NSBitmapImageRep* offscreenRep = nil;      
    
        offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
                                                 pixelsWide:offscreenRect.size.width
                                                 pixelsHigh:offscreenRect.size.height
                                                 bitsPerSample:8
                                                 samplesPerPixel:4
                                                 hasAlpha:YES
                                                 isPlanar:NO
                                                 colorSpaceName:NSCalibratedRGBColorSpace
                                                 bitmapFormat:0
                                                 bytesPerRow:(4 * offscreenRect.size.width)
                                                 bitsPerPixel:32];
    
        [NSGraphicsContext saveGraphicsState];
    
        NSGraphicsContext *bitmapContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
        [NSGraphicsContext setCurrentContext:bitmapContext];
        [webView displayRectIgnoringOpacity:offscreenRect inContext:bitmapContext];
        [NSGraphicsContext restoreGraphicsState];
    
        // Create a small + large thumbs
        NSImage *smallThumbImage = [[NSImage alloc] initWithSize:thumbSizeSmall];  
        NSImage *largeThumbImage = [[NSImage alloc] initWithSize:thumbSizeLarge];
    
        [smallThumbImage lockFocus];
        [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];  
        [offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];  
        NSBitmapImageRep *smallThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];  
        [smallThumbImage unlockFocus];  
    
        [largeThumbImage lockFocus];  
        [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];  
        [offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];  
        NSBitmapImageRep *largeThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];  
        [largeThumbImage unlockFocus];  
    
        // Write out small
        NSString *writePathSmall = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_small.png", locale, collectionIndex, pageIndex]];
        NSData *dataSmall = [smallThumbOutput representationUsingType:NSPNGFileType properties: nil];
        [dataSmall writeToFile:writePathSmall atomically: NO];
    
        // Write out lage
        NSString *writePathLarge = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_large.png", locale, collectionIndex, pageIndex]];
        NSData *dataLarge = [largeThumbOutput representationUsingType:NSPNGFileType properties: nil];
        [dataLarge writeToFile:writePathLarge atomically: NO];
    }];
    

    Hope this helps!

    0 讨论(0)
  • 2020-11-22 16:31

    You could use PhantomJS, which is a headless webkit (the rendering engine in safari and (up until recently) chrome) driver. You can learn how to do screen capture of pages here. Hope that helps!

    0 讨论(0)
  • 2020-11-22 16:32

    This is what I did.

    Note: Please check App.js for the code.

    Link to source code

    If you liked it, you can drop a star.✌️

    0 讨论(0)
  • 2020-11-22 16:36

    There is a lot of options and they all have their pro and cons.

    Option 1: Use one of the many available libraries

    • dom-to-image
    • wkhtmltoimage (included in the wkhtmltopdf tool)
    • IMGKit (for ruby and based on wkhtmltoimage)
    • imgkit (for python and based on wkhtmltoimage)
    • python-webkit2png
    • ...

    Pros

    • Conversion is quite fast most of the time

    Cons

    • Bad rendering
    • Does not execute javascript
    • No support for recent web features (FlexBox, Advanced Selectors, Webfonts, Box Sizing, Media Queries, ...)
    • Sometimes not so easy to install
    • Complicated to scale

    Option 2: Use PhantomJs and maybe a wrapper library

    • PhantomJs
    • node-webshot (javascript wrapper library for PhantomJs)
    • ...

    Pros

    • Execute Javascript
    • Quite fast

    Cons

    • Bad rendering
    • No support for recent web features (FlexBox, Advanced Selectors, Webfonts, Box Sizing, Media Queries, ...)
    • Complicated to scale
    • Not so easy to make it work if there is images to be loaded ...

    Option 3: Use Chrome Headless and maybe a wrapper library

    • Chrome Headless
    • chrome-devtools-protocol
    • Puppeteer (javascript wrapper library for Chrome headless)
    • ...

    Pros

    • Execute Javascript
    • Near perfect rendering

    Cons

    • Not so easy to have exactly the wanted result regarding:
      • page load timing
      • viewport dimensions
    • Complicated to scale
    • Quite slow and even slower if the html contains external links

    Option 4: Use an API

    • ApiFlash (based on chrome)
    • EvoPDF (has an option for html)
    • Grabzit
    • HTML/CSS to Image API
    • ...

    Pros

    • Execute Javascript
    • Near perfect rendering
    • Fast when caching options are correctly used
    • Scale is handled by the APIs
    • Precise timing, viewport, ...
    • Most of the time they offer a free plan

    Cons

    • Not free if you plan to use them a lot

    Disclosure: I'm the founder of ApiFlash. I did my best to provide an honest and useful answer.

    0 讨论(0)
  • 2020-11-22 16:38

    Install phantomjs

    $ npm install phantomjs
    

    Create a file github.js with following code

    var page = require('webpage').create();
    //viewportSize being the actual size of the headless browser
    page.viewportSize = { width: 1024, height: 768 };
    page.open('http://github.com/', function() {
        page.render('github.png');
        phantom.exit();
    });
    

    Pass the file as argument to phantomjs

    $ phantomjs github.js
    
    0 讨论(0)
提交回复
热议问题