i'm using phantom js to screen shot a page
http://code.google.com/p/phantomjs/wiki/QuickStart#Rendering
it has a feature called clipRect
http://code.google.com/p/phantomjs/wiki/Interface#clipRect_(object)
can someone show me how i would modify the following code to us clipRect so i only get a partial screenshot and not the whole thing?
if (phantom.state.length === 0) {
if (phantom.args.length !== 2) {
console.log('Usage: rasterize.js URL filename');
phantom.exit();
} else {
var address = phantom.args[0];
phantom.state = 'rasterize';
phantom.viewportSize = { width: 600, height: 600 };
phantom.open(address);
}
} else {
var output = phantom.args[1];
phantom.sleep(200);
phantom.render(output);
phantom.exit();
}
If you are trying to get a screenshot of a particular element, you could get the necessary information for clipRect from getBoundingClientRect as per the bottom of this article:
page.clipRect = page.evaluate(function() {
return document.getElementById(THE_ELEMENT_YOU_WANT).getBoundingClientRect();
});
From the fine manual:
clipRect (object)
This property defines the rectangular area of the web page to be rasterized when render() is invoked. If no clipping rectangle is set, render() will process the entire web page.
Example: phantom.clipRect = { top: 14, left: 3, width: 400, height: 300 }
So try setting clipRect right before you call render:
var output = phantom.args[1];
phantom.sleep(200);
phantom.clipRect = { top: 14, left: 3, width: 400, height: 300 }
phantom.render(output);
phantom.exit();
You'd have to figure out where the upper left corner (top and left) is and how big (width and height) you want the clipping rectangle to be.
You can probably set the clipRect any time before render() is called but start with that and see what happens.
What was happening is i was using brew and it was installing v 1.0.0 where clipRect and almost every other function wasn't supported as v 1.0.0 is the oldest version.
If you follow these instructions: http://code.google.com/p/phantomjs/wiki/BuildInstructions#Mac_OS_X
then right click on the complied file and click show/view contents (on mac) then copy the executable bin/phantomjs.app/Contents/MacOS/phantomjs to some directory in your PATH.
Feel free to post on here i'm monitoring this and i can help if needed.
Related
I have six floors of a building drawn on a canvas with fabric.js. In order to show only one floor, I do this:
building.selectFloor = function(floorId){
for (var i = 0; i < floors.length; i++){
if (floorId == floors[i].name){
floors[i].visible = true;
}else{
floors[i].visible = false;
}
}
canvas.renderAll();
};
But nothing changes - all floors are still visible. The floors set to visible = false don't disappear until renderAll() is called later on a window resize:
$(window).resize(setSize);
setSize();
function setSize(){
viewportWidth = $(window).width();
viewportHeight = $(window).height();
$appContainer.css({ "width": viewportWidth, "height": viewportHeight});
canvas.setDimensions({ width: viewportWidth, height: viewportHeight });
if (canvas.building){
canvas.building.center();
canvas.building.scaleX = canvas.building.scaleY = (viewportWidth + viewportHeight) / (1920 + 1080);
canvas.renderAll();
}
}
but then they do disappear. Why is one renderAll() working, and the other not? I've tried wrapping the non-functioning renderAll() in a window.timeOut to see if a delay helps, but no luck.
Ok - so I figured it out in the end: building is a group which appears to be getting cached by some internal fabric magic, and the cached version is being rendered instead of the updated version. To render the updated version you have to do this
canvas.building.set('dirty', true);
canvas.renderAll();
Hope that helps someone on down the line.
EDIT
Turns out there's an easier solution still:
canvas.building.objectCaching = false
There is a new version that changed the format to:
canvas.requestRenderAll();
This worked for me in later versions:
// for one canvas
myCanvas.objectCaching = false;
// for all canvas
fabric.Object.prototype.objectCaching = false;
// in both case it still needs to be re-rendered
myCanvas.renderAll();
ps: using version 4.2.0
You have to update (at least in the new version) object properties with object.set({...}) or set object.dirty = true in order to make the cache system recognize the change in the object properties. Disabling cache might not be the best idea, it has been included for a reason. canvas.requestRenderAll(); then works as intended.
I tried asking this question before but the way I asked it was so confusing that I didn't get any help. I originally thought it was React to blame for my touchmove events to ceasefire when updating subcomponents. I now am pretty sure it is the Chartist.js library, or possibly how I'm wrapping chartist into a react component, that is stopping the action.
Instead of rambling on about my question I've created two JSfiddles. One that shows you can create a React slider that updates it's values continuously, regardless of being called from mousemove or touchmove.
http://jsfiddle.net/higginsrob/uf6keps2/
// please follow the link for full example
The Second fiddle implements my react wrapper for chartist, and a simplified example of how I'm using it. When you click/drag on the chart it will select the data point at the current x value. This is working fine with a mouse, but trying it on mobile touch devices (or chrome's mobile emulator) it will only fire a few times, and only update the chart once.
http://jsfiddle.net/higginsrob/Lpcg1c6w/
// please follow the link for full example
Any help is appreciated!
Ok, so you need to put a transparent div in front of the chartist chart that captures the mousedown/touchstart, mousemove/touchmove, and mouseup/touchend events.
working example:
http://jsfiddle.net/higginsrob/jwhbzgrb/
// updated event functions:
onTouchStart: function (evt) {
evt.preventDefault();
this.is_touch = (evt.touches);
var node = evt.currentTarget.previousSibling;
var grid = node.querySelector('.ct-grids');
var bbox = grid.getBBox();
this.columnwidth = bbox.width / this.props.data.length;
this.offset = this.getScrollLeftOffset(node) + bbox.x + (this.columnwidth / 2);
this.istouching = true;
this.onTouchMove(evt);
}
onTouchMove: function (evt) {
if(this.istouching){
var x;
if (this.is_touch) {
if(evt.touches && evt.touches[0]){
x = evt.touches[0].clientX - this.offset;
}
} else {
x = evt.clientX - this.offset;
}
this.setState({
index: Math.round(x / this.columnwidth)
});
}
}
onTouchEnd: function(evt){
this.istouching = false;
}
// updated render function:
render: function () {
return React.DOM.div(
{
style: {
position: "relative"
}
},
ReactChartist({ ... your chartist chart here .... }),
// this div sits in front of the chart and captures events
React.DOM.div({
onMouseDown: this.onTouchStart,
onTouchStart: this.onTouchStart,
onMouseMove: this.onTouchMove,
onTouchMove: this.onTouchMove,
onMouseUp: this.onTouchEnd,
onTouchEnd: this.onTouchEnd,
style: {
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0
}
})
);
}
jsPDF doesn't work well with the latest version of Firefox. It does not let me to download the PDF. Is there a fix on this? I tried downloading the latest version of jsPDF.
EDIT:
My FF version is 32.0.3
I don't get any error messages.
This is the code that "downloads" the pdf. It works well in IE and Chrome:
So I think it has nothing to do with the code. What I want to know is how can I download the pdf in Firefox.
function appendDataToPDF(div, doc, top)
{
html2canvas(div, {
background: '#fff',
onrendered: function(canvas) {
var img = canvas.toDataURL();
doc.addImage(img, 'JPEG', 10, top, parseInt($(div).css("width"), 10), parseInt($(div).css("height"), 10));
if(top > 240)
{
doc.addPage();
top = 27;
}
div = $(div).next();
if(div.length === 0)
{
doc.save('doc.pdf');
}
else
{
if(div.get(0).nodeName === 'BR')
div = $(div).next();
appendDataToPDF(div, doc, top);
}
}
});
}
The issue lies within the execution of the doc.save(). The document is not ready yet, when the save() command is invoked. Try to set a timeout and it should work.
setTimeout(function() {
doc.save(filename);
}, timeout);
I just placed an alert() after the doc.save() function and now the download works. You could try this solution if you run into the same problem.
One thread is going on related this issue, may be you will get fix here.
https://github.com/parallax/jsPDF/issues/3391
I have a need to create a pdf straight from the source of my html page, which is does successfully, but now I need to get the formatting right. What I want, is to be able to add a new page every time a <p class="form-control-static"></p> pops up in the source.
I have checked the documentation and some other stack overflow answers but these are all for adding pages when the content is static and you can create it yourself. My content is changing all the time.
I am using jsPDF to achieve all of this. I am aware of the pdf.addPage() command yet I am not sure how to add pages depending on a condition. My current code as follows:
$('#downloadPDF').click(function () {
$('#report').width(522);
$('.img-thumbnail').width(522).height(348);
var pdf = new jsPDF('p', 'pt', 'letter')
, source = $('#report')[0]
, specialElementHandlers = {
'#bypassme': function (element, renderer) {
return true
}
}
margins = {
top: 20,
bottom: 20,
left: 40,
width: 550
};
pdf.fromHTML(
source
, margins.left
, margins.top
, {
'width': margins.width
, 'elementHandlers': specialElementHandlers
},
function (dispose) {
pdf.save('Job Report - ' + #ViewData["jobid"] + '.pdf');
},
margins
)
});
Obviously it has something to do with the source variable containing the html or am I mistaken?
In my app, everytime when I call the camera ( either take a picture or scan barcode), there will be a white space added to the bottom(tested on ios 7). It can grow by how many times I used the camera. Looks like the same height of the status bar.
The camera is just using native SDK, nothing else in the code.
CameraHelper.prototype.takeCameraImage = function(callback){
console.log("takeCameraImage");
navigator.camera.getPicture(onSuccess, onFail, { quality: 49,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.CAMERA,
correctOrientation: true,
targetWidth: 266,
targetHeight: 266
});
function onSuccess(imageURI) {
callback({imageURI: imageURI});
}
function onFail(message) {
callback({message: message});
}
};
what's the possible reason for it?
try this one, put this code in your MainViewController.m class
- (void)viewDidLayoutSubviews{
if ([self respondsToSelector:#selector(topLayoutGuide)]) // iOS 7 or above
{
CGFloat top = self.topLayoutGuide.length;
if(self.webView.frame.origin.y == 0){
// We only want to do this once, or if the view has somehow been "restored" by other code.
self.webView.frame = CGRectMake(self.webView.frame.origin.x, self.webView.frame.origin.y + top, self.webView.frame.size.width, self.webView.frame.size.height - top);
}
}
}
For the height try using self.view.frame.size.height - 20 (or what the status bar height is).
I had exactly the same problem on a cordorva app running on an iPhone on OS 7.1. It happens on calls to inAppBrowser, as well. None of the solutions suggested here worked for me.
However, what did work was to find this in MainViewController.m (starting on line 78 for me):
- (void)viewWillAppear:(BOOL)animated
{
// View defaults to full size. If you want to customize the view's size, or its subviews (e.g. webView),
// you can do so here.
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
CGRect viewBounds = [self.webView bounds];
viewBounds.origin.y = 20;
viewBounds.size.height = viewBounds.size.height - 20;
self.webView.frame = viewBounds;
}
[super viewWillAppear:animated];
}
Comment out the following line:
viewBounds.size.height = viewBounds.size.height - 20;
That fixed the compounding white space issue for me completely and I found no negative consequences.
use this code
static int score = 0;
- (void)viewWillAppear:(BOOL)animated
{
// View defaults to full size. If you want to customize the view's size, or its subviews (e.g. webView),
// you can do so here.
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
CGRect viewBounds = [self.webView bounds];
viewBounds.origin.y = 10;
//viewBounds.size.height = viewBounds.size.height - 18;
if (score==0) {
viewBounds.size.height = viewBounds.size.height - 18;
score=1;
}
self.webView.frame = viewBounds;
}
[super viewWillAppear:animated];
}