Cropping PhantomJS screen capture sized to content - phantomjs

PhantomJS is doing a great job of capturing web pages into image files for me. I am using a script based on rasterize.js.
However, for certain web elements of a fixed size, I need the resulting image to match the size of the web element.
e.g. I have a page like this:
<html>
<body>
<div id="wrapper" style="width:600px; height:400px;">
Content goes here...
</div>
</body>
</html>
In this example, I need it to produce an image sized at 600x400. Is thre a way to get the viewport size dynamically based on a web element in the page I am rasterizing.
I know this one is not a easy one... Ideas?
Thanks

Wow. Not that hard after all. Just set the viewport really big and use the cropRect function. What a great tool!
Mods to rasterize.js:
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
var height = page.evaluate(function(){
return document.getElementById('wrapper').offsetHeight;
});
var width = page.evaluate(function(){
return document.getElementById('wrapper').offsetWidth;
});
console.log('Crop to: '+width+"x"+height);
page.clipRect = { top: 0, left: 0, width: width, height: height };
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});

Related

Puppeteer full page screenshot, getting extra white space rendered at bottom of page

I'm playing with Puppeteer v1.3.0 to generate some screenshots at various breakpoints during build/deploy. I don't seem to understand how to generate a full page screenshot properly.
I can get a full page screenshot exactly as I want it, but I have to set the viewport dimensions twice which seems very odd to me (I just set an arbitrary height, then evaluate the clientHeight):
//xl
await page.setViewport({
width: 1201,
height: 600
});
await page.setViewport({
width: 1201,
height: await page.evaluate(() => document.body.clientHeight),
isMobile: true //whether the meta viewport tag is taken into account
});
await page.screenshot({path: 'xl.png');
I've tried setting waitUntil networkidle, just evaluating the clientHeight and setting fullPage to true in the page.screenshot:
await page.goto('my-url-here', {
waitUntil: 'networkidle2'
});
await page.setViewport({
width: 1201,
height: await page.evaluate(() => document.body.clientHeight),
isMobile: true //whether the meta viewport tag is taken into account
});
await page.screenshot({path: 'arrowdental_xl.png', fullPage: true});
And I get a full page screenshot, but there's a bunch of extra white space at the bottom, which I don't want.
What's the proper way to get a full page screenshot in Puppeteer? Again, the first method above works, but it feels dumb I have to set the viewport dimensions twice. I'd like to have cleaner code, if possible.
With puppeteer sharp v 1.11.2
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
});
var page = await browser.NewPageAsync();
await page.GoToAsync("https://www.google.com/");
await page.ScreenshotAsync(#"c:\temp\google.png", new ScreenshotOptions {FullPage = true});
so passing ScreenshotOptions.FullPage to ScreenshotAsync()

phantomjs - running render after loading the page, but loading never fires

I'm trying to create a graph-to-png converter with phantomjs, but having a hard time getting it to work. Almost every example I see out there uses some external URL as if all you ever do with it is scraping, and the documentation is terribly lacking.
To test out things, I created a very simple d3 function that adds an <svg> tag and a blue circle inside. Looking at other questions on SO and examples, I hooked it to onLoadFinish but that event never triggers.
I'm guessing I need to open the page, but open only uses a url, which isn't relevant for me (and again, the docs are completely lacking in information. Even when I see something I think might be relevant, my only choice is guesswork. This is ridiculous )
Here's my code:
var page = require('webpage').create();
var content = '<html>';
content += '<body>';
content += '<h1> test title </h1>';
content += '<div id="graph">';
content += '</div>';
content += '</body></html>';
page.content = content;
page.injectJs('lib/d3/d3.min.js');
page.onLoadFinish = function(status) {
console.log('loading finished'); // this never happens!
var svg = d3.select('#graph')
.append('svg')
.attr({'width': 100, 'height': 100});
var circle = svg
.append('circle')
.attr({ 'cx': 10, 'cy': 10, 'r': 10, 'fill': 'blue' });
page.render('test.png');
phantom.exit();
};
Any suggestions?
It's evaluate. That was the function I was looking for. It "evaluates the given function in the context of the web page".
Finally, it's working:
page.content = content;
page.injectJs('lib/d3/d3.min.js');
page.evaluate(function() {
var svg = d3.select('#graph')
.append('svg')
.attr({'width': 100, 'height': 100});
var circle = svg
.append('circle')
.attr({ 'cx': 10, 'cy': 10, 'r': 10, 'fill': 'blue' });
page.render('test.png');
phantom.exit();
};

Animate DIV to another DIV position

I can't figure out how to animate my DIV so that it goes to the #slot1 position (and later any slot I choose).
Here is my javascript code and the fiddle
$(function (){
$('#deck').click(function (){
var slotPos = $('#slot1').position();
$(this).animate({left: slotPos.left}, 400);
});
});
http://jsbin.com/ejeweb/4/
Thanks in advance!
$(#slot1 ).position()
function giving the relative position w.r.t to
<div id='head'>
container. So you can try below code. And use accordingly it:
$(function (){
$('#deck').click(function (){
var slotPos = $('#slot1').position(),
hand=$("#hand").position();
$("#deck").animate({
left: 10+hand.left+slotPos.left,
top:10 + hand.top},
400);
})
}
);
Let me know if this works for you!

How to run a jquery function but only when the browser window width is > 1024px?

This is a functionality I'd like to add to my responsive one-page website, but only when the browser width is greater than 1024px.
My knowledge of jQuery is minimal. This is the code I have now:
$(document).ready(function() {
var pageWidth = $(window).width();
if (pageWidth > 1024) {
$('.footer a').mouseenter(function() {
$(this).effect("bounce", { times:1, distance:4 }, 250);
});
});
});
This is the code I have in the HTML that loads this function:
<script type="text/javascript" src="js/tiny-bounce.js"></script>
Another question, when this function isn't firing—for example when a user loads the site on a device that has < 1024px width, do they still have to load the javascript file?
All you need to do this is
instead of this
if (pageWidth > 1024) {
do this
if (pageWidth < 1024) {
Yes, you still have to load the JS code when the width is less than 1024, unless you include this code in your HTML or an existing JS script.
I believe you can call $(window).width() without $(document).ready(), so that could be one way to lessen the impact of having this extra code on small screens.

Facebook Canvas App Height less than 800px

I have 2 facebook app one that is 872px height and another one that is 712px height. For the 827px app I have successfully re-sized the app from 800 to 872px using the facebook JS SDK. But for the 712px I haven't been able to get it down from 800px. Is there a minimum height for facebook canvas app or I'm doing something wrong?
Apparently Canvas APP can't go lower than 800 px.
have you tried to set the height dynamically? this worked for me as i am attempting to display multiple pages that are less than 800px in height. the usual height of my page tabs were ~700px.
window.fbAsyncInit = function() {
FB.init({
appId: window.FB_APP_ID
});
// set height dependent on page (min height is 800px)
// but we are attempting to get it shorter
var body_height = $('body').first().outerHeight();
FB.Canvas.setSize({
height: body_height
});
}
what also worked for me, if not grabbing the body height is to set the height to something shorter than any of your pages at load, then triggering the setAutoGrow() function to expand it to the proper height with some delay. though this will cause your canvas to be the initial set height (eg. 480px) then will expand to size whenever your timeout fires.
window.fbAsyncInit = function() {
FB.init({
appId: window.FB_APP_ID
});
FB.Canvas.setSize({
height: 480 // some height shorter than necessary
});
setTimeout(function(){
FB.Canvas.setAutoGrow();
}, 500);
}
To deal with it:
FB.Canvas.getPageInfo(
function(info) {
// console.log(info);
if (info.clientHeight< 800) FB.Canvas.setSize({ height: 800 });
}
);