I have a page with any number of images with the class pinch-zoom-element I want to replace all of that images with canvas and apply them the PinchZoomCanvas library. Canvas is added to the code, even the library is applied, but the canvas remains at 0px width and height.
var pictures = document.getElementsByClassName('pinch-zoom-element');
for(var i = 0; i < pictures.length; i++){
var imageItem = pictures.item(i);
var canv = document.createElement('canvas');
var foto = imageItem.src;
canv.id = 'canvasIdItem';
canv.style.width = "300px";
canv.style.height = "300px";
imageItem.parentNode.insertBefore(canv, imageItem.nextSibling);
imageItem.parentNode.removeChild(imageItem);
console.log(canv);
var pinchZoom = new PinchZoomCanvas({
canvas: canv,
path: foto,
zoomMax: 2,
doubletap: true,
onZoomEnd: function (zoom, zoomed) {
console.log("---> is zoomed: %s", zoomed);
console.log("---> zoom end at %s", zoom);
},
onZoom: function (zoom) {
console.log("---> zoom is %s", zoom);
}
});
}
How can I get this working? Thanks in advance!
Set your canvas height and width like:
canv.style.width = "300";
canv.style.height = "300";
You can also set it in your css using specific selector:
canvas {
width: 500px;
height: 400px;
}
I'm trying to use HTML2Canvas to render the contents of a div. Here is the code:
var htmlSource = $('#potenzial-page')[0];
$('#btn').on("click", function() {
html2canvas(htmlSource).then(function(canvas) {
var img = canvas.toDataURL();
window.open(img);
});
});
I'm using v5 beta 3.
When this code runs, it only renders what is visible on the screen. The #potenzial-page div is essentially the entire page, minus the header and footer. All content in this div is visible by scrolling (there are some hidden elements, but I do not want the hidden elements visible in the image.)
I cannot find what's wrong or why it won't save the entire div. I should also note that it appears the image is as tall as the div but only partially visible.
To give an example of what I mean, here is a comparison:
The left is how HTML2Canvas should render the div. The right shows how it renders when it runs the code above. The right image is what's visible in my browsers screen.
I did try adding the height option but it doesn't make a difference.
UPDATE
If I scroll to the very top of the page then run the script it will render the entire div as it should.
How do I render the div without having to scroll to the top?
I hope thet help you
html2canvas(htmlSource, {scrollY: -window.scrollY}).then(function(canvas) {
var img = canvas.toDataURL();
window.open(img);
});
A solution that worked for me was to add the following to my css:
.html2canvas-container { width: 3000px !important; height: 3000px !important; }
It prevents html2canvas from limiting the rendering to the viewable area (which seems to be the default).
See here: https://github.com/niklasvh/html2canvas/issues/117
I used window.scrollTo()in my case and it worked for me.
Below is a sample code
$('#btn').on("click", function() {
window.scrollTo(0,0);
html2canvas(htmlSource).then(function(canvas) {
var img = canvas.toDataURL();
window.open(img);
});
window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
});
I just did something like this and it worked for me:
html2canvas(document.querySelector("#capture2image"), {
allowTaint: true,
useCORS: true,
logging: false,
height: window.outerHeight + window.innerHeight,
windowHeight: window.outerHeight + window.innerHeight,
You can add in scroll position as a variable in html2canvas which removes the need to scroll the page.
html2canvas(document.querySelector("#your-element"), {
scrollX: 0,
scrollY: 0
}).then(function(canvas) {
If you have a height set to the div you want to turn to a canvas - you need to remove that before actually taking the snapshot. Otherwise it will just cut it off because of that height.
$(".yourElemThatHasSomeHeightSet").css("height", "");
Then you will notice that scrolling down - will still cut your document.
Simply do a:
$("html, body").scrollTop(0);
before taking the snapshot.
This is how I've achieved in Reactjs.
Main problem were ratio and scale
If you do a quick window.devicePixelRatio, it's default value is 2 which was causing the half image issue.
const printDocument = () => {
const input = document.getElementById('divToPrint');
const divHeight = input.clientHeight
const divWidth = input.clientWidth
const ratio = divHeight / divWidth;
html2canvas(input, { scale: '1' }).then((canvas) => {
const imgData = canvas.toDataURL('image/jpeg');
const pdfDOC = new jsPDF("l", "mm", "a0"); // use a4 for smaller page
const width = pdfDOC.internal.pageSize.getWidth();
let height = pdfDOC.internal.pageSize.getHeight();
height = ratio * width;
pdfDOC.addImage(imgData, 'JPEG', 0, 0, width - 20, height - 10);
pdfDOC.save('summary.pdf'); //Download the rendered PDF.
});
}
window.scrollTo(0,0);
Add this works for me.
for people dont wanna hacky a way for scroll problem.: dom-to-image
you can scroll while you are snapshotting image
and its much more faster (70x according to this blog ).
blog: https://betterprogramming.pub/heres-why-i-m-replacing-html2canvas-with-html-to-image-in-our-react-app-d8da0b85eadf
in the blog it mentions html-to-image. it is fork of dom-2-image. i used dom-to-image (ancestor , original one).
var node = document.getElementById('my-node');
domtoimage.toPng(node)
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
The following code worked for me:
window.scrollTo(0, 0);
html2canvas(htmlRef, {
scrollX: -window.scrollX,
scrollY: -window.scrollY,
windowWidth: document.documentElement.offsetWidth,
windowHeight: htmlRef.scrollHeight,
}).then((canvas) => {
const img = new Image();
const imgData = canvas
.toDataURL("image/png")
.replace("image/png", "image/octet-stream");
const pdf = new jsPDF("p", "mm", "a4");
const imgProps = pdf.getImageProperties(imgData);
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, "JPEG", 0, 0, pdfWidth, pdfHeight);
pdf.save();
});
<div #potentialContainer id="potentialContainer" class="potentialContainer" style="height: auto;">
some large content here--------------------
</div>
import html2canvas from 'html2canvas';
downloadImage() {
html2canvas(document.querySelector('#potentialContainer'), {
logging: true,
allowTaint: false,
useCORS: true,
width: document.querySelector('#potentialContainer').scrollWidth,
height: section.scrollHeight,
scrollX: -window.scrollX,
scrollY: -window.scrollY,
}).then((canvas) => {
var imgWidth = 210;
var pageHeight = 290;
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
var doc = new jsPDF('p', 'mm');
var position = 0;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var imgData = encodeURIComponent(pageData);
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
doc.setLineWidth(5);
doc.setDrawColor(255, 255, 255);
doc.rect(0, 0, 210, 295);
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
doc.setLineWidth(5);
doc.setDrawColor(255, 255, 255);
doc.rect(0, 0, 210, 295);
heightLeft -= pageHeight;
}
doc.save('file.pdf');
});
}
Note:- It is important to add style height:auto
The above code will convert a large image to a multipage pdf
Another React Approach...
On your submit button on click set the document height dynamically, then call html2canvas using document.body as the first argument
<button onClick={() => {
var body = document.body,
html = document.documentElement;
var height = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
document.body.style.height = `${height}px`
html2canvas(document.body).then(function (canvas) {
var imgData = canvas.toDataURL('image/pdf')
var doc = new jsPDF('p', 'mm', [canvas.width, canvas.height])
doc.addImage(imgData, 'PDF', 10, 10, canvas.width, canvas.height)
doc.save('name-of-pdf.pdf')
});
}}>Submit</button>
This will set the html height of public/index.html which html2canvas seems to render from (i.e. not the "root" div).
This works for me:
const input = document.getElementById('fragmentForPDF');
// This row fixed problem
input.parentNode.style.overflow = 'visible';
html2canvas(input)...
window.scrollTo(0, 0); // this will help to print if div hidden or on mobile screen
html2canvas(document.getElementById("my_div_img")).then(function (canvas)
{
//for give white BG
var context = canvas.getContext('2d');
context.save();
context.globalCompositeOperation = 'destination-over';
context.fillStyle = "rgb(255, 255, 255)";
context.fillRect(0, 0, canvas.width, canvas.height);
context.restore();
var imgData = canvas.toDataURL('image/jpeg', 1);
//console.log(imgData);
}
This worked for me:
html2canvas(el, {
width: el.scrollWidth,
height: el.scrollHeight,
})
See here for the source.
document.getElementById("dld_report").addEventListener("click", function() {
// Make sure the area you want to take screenshot is visible in CSS
document.querySelector('#boundary').style.overflow = 'visible';
html2canvas(document.querySelector('#boundary'), {
// Set the height of screenshot image same as page hieght
height: window.outerHeight + window.innerHeight,
}).then(function(canvas) {
saveAs(canvas.toDataURL(), 'report.png');
});
});
// dld_report -> button to trigger the screenshot
Set style overflow = "visible" and height were the key to make this happen.
General advice regarding html2canvas Try and set height of html to 100%.
I use mozilla pdf.js. I have a code:
<canvas id="the-canvas"/>
function displayDocument(){
PDFJS.getDocument(numberOdDocument[attachment]).then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
renderPage(pageNum);
});
}
function renderPage(num) {
pdfDoc.getPage(num).then(function(page) {
var viewport = page.getViewport(scale, rotate);
canvas.height = '900';
canvas.width = '500';
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
pageRendering = false;
if (pageNumPending !== null) {
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
}
Now i see only one page in canvas tag, but I want add scrollbar to my canvvas, and I want change page with scroll. How can I do that?
Allow scroll
First, create a parent div to encapsulate the canvas element :
<div>
<canvas id="the-canvas"/>
</div>
Then, set a fixed size with a vertical scroll
<div style="width:650px;height:600px;overflow-y:scroll;">...</div>
Finally, you can set the scale you want using the variable "scale" but keep these original lines :
function renderPage(num) {
pdfDoc.getPage(num).then(function(page) {
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
...
Render all pages
Keep in mind, that render a lot of pages will take a bit of time but here is how to do it.
Idea : you need to render each page in a separate canvas element.
First, create dynamically the canvas element with a specific id during render :
<div id="pdf-viewer"></div>
...
function renderPage(num) {
pdfDoc.getPage(num).then(function(page) {
var canvasId = 'pdf-viewer-' + num;
$('#pdf-viewer').append($('<canvas/>', {'id': canvasId}));
var canvas = document.getElementById(canvasId);
...
Finally, call renderPage() for each page
function renderAllPages() {
for (var i = 1; i <= pdfDoc.numPages; i++) {
renderPage(i);
}
}
I am testing phantomjs for creating screenshots from a web page at my local end.
This is how HTML is rendering in localhost - Output
But on creating pdf from code, width is not setting properly in PDF, ie some text gets cut as shown below.
Following is the code I tired -
var url = 'http://localhost:5656';
page.open(url);
page.onLoadFinished = function() {
var pdfName = 'screen';
page.render(pdfName + ".pdf");
var height = page.evaluate(function() { return document.body.offsetHeight }),
width = page.evaluate(function() { return document.body.offsetWidth });
console.log(height,width);
};
I also tried these two properties but getting same result -
page.clipRect = { top: 0, left: 0, right: 0, width: 1286};
page.viewportSize = { width: 1024, height: 768};
Let me know what I am doing wrong here.
Output I am getting - pdf image I am getting
I solved the issue on my own. Following is the working code -
var url = 'http://localhost:5656';
page.open(url);
page.onLoadFinished = function() {
//page.viewportSize = { width: 1400, height: 1200 };
page.paperSize = {format: 'A4'};
var pdfName = 'screen';
page.render(pdfName + ".pdf");
var height = page.evaluate(function() { return document.body.offsetHeight }),
width = page.evaluate(function() { return document.body.offsetWidth });
console.log(height,width);
};
As you can see, following is the line that performed the magic for me -
page.paperSize = {format: 'A4'};
Hope it will help to the future visitors.
Notice the data:img images... I dont know how to remove them from memory and document.images does not contain them...
I am writing a Chrome Extension. Its somewhat of a hybrid screenshot app and basically when a user scrolls it takes the new part of the screen that the user has scrolled to and appends it on to a master screenshot of the entire site (yeah i have used googles screenshot app). My code works, but when I pass the img from the extension to the content script its storing the data:img sources into somewhere in memory where I cant access. I have tried document.images and tested to see if they may be populated within but with no luck.
Heres the code if you are interested.
page.js
var ovr = 0;
var run = (window==window.top)?1:0;
if(run&&ovr){
function obj(){
window.onload = function(){
obj.conversion = .5;
obj.screenShot();
obj.startRecordingScroll();
obj.showShot();
};
}
obj.showShot = function(){
obj.fullShot = document.createElement('canvas');
obj.fullShot.zIndex = -100;
obj.fullShot.style.position = 'fixed';
obj.fullShot.style.top = '70px';
obj.fullShot.style.right = '20px';
obj.fullShot.style.backgroundColor = '#999999';
obj.fullShot.width = window.innerWidth*obj.conversion;
obj.fullShot.height = document.height*obj.conversion;
document.body.appendChild(obj.fullShot);
obj.ctx = obj.fullShot.getContext('2d');
};
obj.startRecordingScroll = function(){
document.onscroll = function(){
obj.scroll();
};
};
obj.scroll = function(){
var pagxoff = window.pageXOffset;
var pagyoff = window.pageYOffset;
alert(document.images.length);
console.log("scroll");
obj.screenShot();
};
obj.displayScreenShot = function(img){
console.log('displayScreenShot');
var ycur = window.pageYOffset;
var yMaxCur = window.innerHeight+window.pageYOffset;
var distance = yMaxCur - obj.lastMaxYSeen;
distance = Math.abs(distance);
if(!obj.firstRunShot){
obj.lastMinYSeen = window.pageYOffset;
obj.lastMinXSeen = window.pageXOffset;
obj.lastMaxYSeen = (window.innerHeight+window.pageYOffset);
obj.lastMaxXSeen = (window.innerWidth+window.pageXOffset);
var shot = document.createElement('img');
shot.src = img;
console.log(img);
shot.onload = function(){
obj.ctx.drawImage(
shot,
0, // 0 right
0, // 0 down
window.innerWidth, // viewport width
window.innerHeight, // viewport height
0, // 0 right
0, // 0 down
window.innerWidth*obj.conversion,
window.innerHeight*obj.conversion
);
};
obj.firstRunShot = true;
return;
}
if(obj.firstRunShot){
if(ycur>obj.lastMinYSeen){
obj.lastMinYSeen = window.pageYOffset;
obj.lastMinXSeen = window.pageXOffset;
obj.lastMaxYSeen = (window.innerHeight+window.pageYOffset);
obj.lastMaxXSeen = (window.innerWidth+window.pageXOffset);
var xshot = document.createElement('img');
xshot.src = img;
xshot.onload = function(){
obj.ctx.drawImage(
xshot,
0,
window.innerHeight-distance,
window.innerWidth,
distance,
0,
(obj.lastMaxYSeen-distance)*obj.conversion,
window.innerWidth*obj.conversion,
(distance)*obj.conversion
);
};
return;
}
}
};
obj.screenShot = function(){
var port = chrome.extension.connect({
name: "screenshot"
});
port.postMessage({
request: "screenshot"
});
port.onMessage.addListener(function (msg) {
obj.displayScreenShot(msg);
});
console.log('screenShot');
};
var builder = new obj();
}
You can track resources being added and manipulate all contents of these resources using chrome.devtools.inspectedWindow API's, if you want to delete some resource modify DOM by deleting node(s).
document.images does contain the resources.
The Resources panel lets you inspect resources that are loaded in the inspected page, are you loading your image into inspected page to show up here?
If you are trying to store image to local disk using FILE API, remember they are sand-boxed and cannot be accessed by other means.
References
chrome.devtools.inspectedWindow
Resources Panel
File API
Content Scripts