html2canvas Images with .svg format are not rendering - javascript

When we are taking screenshots using html2canvas, images having .svg extention will not render properly. I have tried giving allowTaint:true option, still it is not working.
Code snippet:
<div class="myDiv" style="background-image:url('image.svg');">
</div>
html2canvas($(".myDiv"), {
allowTaint: true,
onrendered: function (canvas){
//use canvas
}
});

html2canvas will capture background svg image if we used img tag instead of div tag with url in scr attribute. So the solution I found for this is, dynamically creating new img tag for each div before calling html2canvas function.
$(".myDiv").each(function () {
var url = $(this).css("background-image")
var src = url.substring(5, url.length - 2);
var image = new Image();
image.src = src;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = $(this).height();
ctx.canvas.height = $(this).width();
ctx.drawImage(image, 0, 0);
$(this).append(canvas);
});
This will work only for cases where you can replace div tag with img tag.

Related

Resize and preview base64 image, javascript

i am a newbie to programming,
I have an HTML code for displaying base64 image the image is dynamic link, always come with different sizes
I need to resize that image and create preview mode with smaller image with an aspect ratio
ex:
my original image on html are 600x300 I need to preview it 300x150
my original image HTML are 1000x500 I need to preview 500x250
I have a javascript for resizing but can't figure out how to get image base64 from my HTML code
Please who can give me some help on these to archive my goal
I cant paste HTMl code here because is to long please check HTMl on codepin
https://codepen.io/Gilavani/pen/JjLXBOb
function resizedataURL(datas, wantedWidth, wantedHeight)
{
// We create an image to receive the Data URI
var img = document.createElement('img');
// When the event "onload" is triggered we can resize the image.
img.onload = function()
{
// We create a canvas and get its context.
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = wantedWidth;
canvas.height = wantedHeight;
// We resize the image with the canvas method drawImage();
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
/////////////////////////////////////////
// Use and treat your Data URI here !! //
/////////////////////////////////////////
};
// We put the Data URI in the image's src attribute
img.src = datas;
}
Thanks you in Advice
Best Regards
let srcImg = document.getElementById("orignal").src;
let prev = document.getElementById("preview");
function resizedataURL(datas, wantedWidth, wantedHeight)
{
prev.src = datas;
prev.onload = function()
{
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = wantedWidth;
canvas.height = wantedHeight;
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
prev.src = canvas.toDataURL();
};
}
resizedataURL(srcImg, 150,150);
<html>
<body>
<img id="orignal" src="data:image/png;base64,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">
<h2>Preview</h2>
<img id="preview" src="#">
</body>
</html>

html2canvas not support transform property?

I build an image editor in javascript for my customer and we issue one huge problem. When we want to generate image where is some text rotated, canvas not generate full image with all contents over background.
Here is example:
When I click on save button I get empty background like this:
On other way, when I just add content and NOT do rotation, transform not exists in CSS, I can change color of text, change font, change background and all will look nice like on this example:
Result is perfect:
Here is my code:
function generateImage(canvas, width){
var img = new Image();
img.crossOrigin = "Anonymous";
img.width = width;
img.height = (img.width / ( 16 / 9 ));
img.src = canvas.toDataURL();
img.align = 'middle';
img.class = 'img-responsive';
img.style.width = '100%';
img.style.maxWidth = width;
document.body.appendChild(img);
}
html2canvas($this, {
onrendered: function(canvas) {
generateImage(canvas, ($this.width()+2));
},
width: $this.width()+2,
height: $this.height()+2
});
The main question is:
Is there a way to add in canvas CSS transition support to can render proper full image or some 3D canvas drawing which work properly?

How to handle SVG and canvas in pdfmake & html2pdfmake

I am using html2pdfmake to convert a div to pdf. My div contains tables and also contains some svg charts. But i am not getting the svg into the pdf. I tried converting it using base64 but is paste the base64 code into the pdf.
I converted my svg to base64 like :
var html = d3.select('#idOfSVG').select("svg").attr("version", 1.1).attr("xmlns", "http://www.w3.org/2000/svg").node().parentNode.innerHTML;
var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html);
var base_image = new Image();
base_image.src = imgsrc;
canvas = document.createElement('canvas');
canvas.id = 'canvas'
document.body.appendChild(canvas);
canvas.width = 500;
canvas.height = 500;
canvas.getContext('2d').drawImage(base_image,0,0);
Then i added the same into the content.
Also when i used ParseHtml(content,document.getElementById("myPDFDiv"))
My div myPDFDiv gets deleted from the DOM.
Any help will be highly appreciated !!
You can use html2pdfmake, it iterates all the elements in the div and make JSON for the same which you can use with pdfmake.
You can add SVG support by adding a switch case for SVG like :
Case 'SVG' :
addImage(cnt,e);
function addImage (cnt,e) {
//Serialize the svg element and then put it in a canvas
//Then update the cnt object
var url = canvas.toDataURL('image/png');
cnt.push({image: url,
width: 200,
height: 250,
margin: [ 20, 0, 0, 0 ]
});
}
Hope it helps !!

How to make html5 canvas display crisp image based off chrome screencap

I am making a chrome extension that uses the chrome.tabs.captureVisibleTab method to grab a screencap of the current tab and then displays that in a popup from the chrome extension. If I use the img tag and use the data coming from the chrome function, such as data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwME…UUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAf/2Q==, the <img> displays pixel perfect, it is crisp and that's what I want. Problem is that I need to make it into a canvas, and when I do that, it becomes blurry.
This is a screencap of the <img> that uses the link data provided by Google to be used as a comparison to the canvas which is below.
This is the blurry canvas.
This is the code that I am using to try to do this, but I can't figure out how to make the canvas crisp like the image.
chrome.runtime.sendMessage({msg: "capture"}, function(response) {
console.log(response.imgSrc);
var img = document.createElement('img');
var _canvas = document.createElement("canvas");
img.src = response.imgSrc;
img.height = 436;
img.width = 800;
document.getElementById('main-canvas').appendChild(img);
draw(response);
});
function draw(response) {
var canvas = document.getElementById('imageCanvas');
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
//Get a 2d context
var ctx = canvas.getContext('2d');
//use image to paint canvas
var _image = new Image();
_image.onload = function() {
ctx.drawImage(_image, 0, 0, 800, 436);
}
_image.src = response.imgSrc;
document.getElementById('main-canvas').appendChild(canvas);
}
This is what I used to fix my problem: High Resolution Canvas from HTML5Rocks

Trying to display image in an HTML5 canvas

I've tried all code variations that are online. I just want to display an image on a canvas. I've tried code from this site.
window.onLoad=function(){
function draw(){
var ctx = document.getElementById("canvas1").getContext("2d");
var img = new Image();
img.src = 'images/ball.png';
img.onload = function(){
ctx.drawImage(img,0,0);
};
};
};
It's not the file path that's a problem, that has been tested without the images folder. There are no errors in the console. Thanks.
One search in google and there you go with complete jsfiddle example:
// Grab the Canvas and Drawing Context
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
// Create an image element
var img = document.createElement('IMG');
// When the image is loaded, draw it
img.onload = function () {
ctx.drawImage(img, 0, 0);
}
// Specify the src to load the image
img.src = "http://i.imgur.com/gwlPu.jpg";
http://jsfiddle.net/jimrhoskins/Sv87G/

Categories