Related
I added a new button in exporting list of a chart
Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({
text: 'Add Issue ',
onclick: function () {
this.AddIssue();
}
});
i want to add a screenshot of a chart in the img tag in same page when i click AddIssue button,
Highcharts.Chart.prototype.AddIssue = function () {
....
$('#mock').attr('src', .........);
}
i had an img tag as
<img id="mock" src="../" />
i tried using getSVG Function but i want it to be a PNG or JPEG image not SVG.
Inside AddIssue Function
var svg = this.getSVG();
var base_image = new Image();
var Isvg = "data:image/svg+xml," + svg;
base_image.src = Isvg;
You can convert SVG from getSVG method to PNG by HTML canvas:
load: function() {
var chart = this,
svg;
$('#btn').on('click', function() {
svg = chart.getSVG();
var canvas = document.createElement('canvas');
canvas.width = chart.chartWidth;
canvas.height = chart.chartHeight;
var ctx = canvas.getContext('2d');
var img = document.createElement('img');
img.onload = function() {
ctx.drawImage(img, 0, 0);
canvas.toDataURL('image/png');
};
img.setAttribute('src', 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svg))));
});
}
Live demo: http://jsfiddle.net/BlackLabel/3azfr1nL/
Other solutions can be find here: https://ourcodeworld.com/articles/read/15/3-ways-to-export-highcharts-charts-to-image-with-javascript-client-side-solution-
and here: https://gist.github.com/philfreo/0a4d899de4257e08a000
How can I get base64 with image inside of svg? Check this Fiddle that I got from another question. If you see the second graphic, its not generating the image that overlays the bar.
var chart = new google.visualization.ColumnChart(document.getElementById('chart_survey'));
$("[fill='#FFFFFF']").each(function( index, element ) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttributeNS(null,'x',element.x.baseVal.value);
svgimg.setAttributeNS(null,'y',element.y.baseVal.value);
svgimg.setAttributeNS(null,'width',element.width.baseVal.value);
svgimg.setAttributeNS(null,'height',element.height.baseVal.value);
svgimg.setAttributeNS(null,'preserveAspectRatio','none');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', '${application.contextPath}/images/textura/patt.gif');
$(element).parent().append(svgimg);
});
$('#test').val(chart.getImageURI())
In order to save this svg to a png, which keeps the linked <image> then you'll have to encode each <image>'s href to a dataURL first.
Edit
I rewrote the original snippets (which can still be found in the edit history).
I changed the <image> tags to <use>. This results in a much smaller memory usage.
I also added a fallback for IE11, which accepts to encode the external image to data URL, but still fails to convert svg to png via canvas.
The fallback will replace the destination <img>tag, with the canvas. The later can be saved by user with a right click.
A few caveats :
It doesn't work in Safari 7, and maybe in other outdated webkit browsers. That's a strange bug, since it does work like a charm in localhost, but won't on any other network (even on my home network, using 192.168.xxx).
IE 9 & IE 10 will fail to convert the external images to data URL, CORS problem.
// What to do with the result (either data URL or directly the canvas if tainted)
var callback = function(d, isTainted) {
if (!isTainted) {
$('#chartImg')[0].src = d;
} else
$('#chartImg')[0].parentNode.replaceChild(d, $('#chartImg')[0]);
};
// The url of the external image (must be cross-origin compliant)
var extURL = 'https://dl.dropboxusercontent.com/s/13dv8vzmrlcmla2/tex2.jpg';
google.load('visualization', '1', {
packages: ['corechart']
})
var encodeCall = getbase64URI.bind(this, extURL, callback);
google.setOnLoadCallback(encodeCall);
// Google Chart part
function drawVisualizationDaily(imgUrl, callback, isTainted) {
var data = google.visualization.arrayToDataTable([
['Daily', 'Sales'],
['Mon', 4],
['Tue', 6],
['Wed', 6],
['Thu', 5],
['Fri', 3],
['Sat', 7],
['Sun', 7]
]);
var chart = new google.visualization.ColumnChart(document.getElementById('visualization'));
chart.draw(data, {
title: "Daily Sales",
width: 500,
height: 400,
hAxis: {
title: "Daily"
}
});
// Link to chart's svg element
var svgNode = chart.ea.querySelector('svg');
// Create a symbol for our image
var symbol = document.createElementNS('http://www.w3.org/2000/svg', 'symbol');
// An svg wrapper to allow size changing with <use>
symbol.setAttributeNS(null, 'viewBox', '0,0,10,10');
symbol.setAttributeNS(null, 'preserveAspectRatio', 'none');
symbol.id = 'background';
// And the actual image, with our encoded image
var img = document.createElementNS('http://www.w3.org/2000/svg', 'image');
img.setAttributeNS(null, 'preserveAspectRatio', 'none');
img.setAttributeNS(null, 'width', '100%');
img.setAttributeNS(null, 'height', '100%');
img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imgUrl);
symbol.appendChild(img);
svgNode.appendChild(symbol);
var blueRects = $("[fill='#3366cc']");
var max = blueRects.length - 1;
blueRects.each(function(index, element) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg', 'use');
svgimg.setAttributeNS(null, 'x', element.x.baseVal.value);
svgimg.setAttributeNS(null, 'y', element.y.baseVal.value);
svgimg.setAttributeNS(null, 'width', element.width.baseVal.value);
svgimg.setAttributeNS(null, 'height', element.height.baseVal.value);
svgimg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#background');
svgNode.appendChild(svgimg);
if (index === max && !isTainted) // no need to call it if we don't have our dataURL encoded images
// a load event would be better but it doesn't fire in IE ...
setTimeout(exportSVG.bind(this, svgNode, callback, isTainted), 200);
});
}
function exportSVG(svgNode, callback, isTainted) {
var svgData = (new XMLSerializer()).serializeToString(svgNode);
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = svgNode.getAttribute('width');
canvas.height = svgNode.getAttribute('height');
canvas.getContext('2d').drawImage(this, 0, 0);
var data, isTainted;
try {
data = canvas.toDataURL();
} catch (e) {
data = canvas;
isTainted = true;
}
callback(data, isTainted);
}
img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
}
// A simple function to convert an images's url to base64 data URL
function getbase64URI(url, callback) {
var img = new Image();
img.crossOrigin = "Anonymous";
img.onload = function() {
var c = document.createElement('canvas');
c.width = this.width;
c.height = this.height;
c.getContext('2d').drawImage(this, 0, 0);
var isTainted;
try {
c.toDataURL();
} catch (e) {
isTainted = true;
}
// if the canvas is tainted, return the url
var output = (isTainted) ? url : c.toDataURL();
drawVisualizationDaily(output, callback, isTainted);
}
img.src = url;
}
svg { border: 1px solid yellow; }
img { border: 1px solid green; }
canvas { border: 1px solid red; }
<script src="http://www.google.com/jsapi?.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="visualization"></div>
Right-click this image to save it:
<br>
<img id="chartImg" />
This example creates an svg container populated by an image. In my example the image is an svg image but you should be able to put in any type of image (jpg, png, gif). The container is created first then the image is created inside the container.
// create svg
var svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
svg.setAttribute('class','shadowed handle_icon_sensors');
svg.setAttribute('height','25');
svg.setAttribute('width','25');
svg.setAttribute('id',idAttr);
svg.setAttribute('z-index','21000');
document.getElementById("zones_container").appendChild(svg);
// create svg image
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttribute('height','25');
svgimg.setAttribute('width','25');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href','svg/icon_sensorYellow.svg');
svgimg.setAttribute('x','0');
svgimg.setAttribute('y','0');
document.getElementById(idAttr).appendChild(svgimg);
Note, When converted to src of img element retained blue background-color .
Try , after .each()
// set namespace attributes
var svg = $("svg").attr({
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:xlink": "http://www.w3.org/1999/xlink"
})[0];
// create `data URI` of `svg`
var dataURI = "data:image/svg+xml;charset=utf-8;base64," + btoa(svg.outerHTML.trim());
// post `svg` as `data URI` to server
$.post("/path/to/server/", {
html: dataURI
}, "html")
.then(function (data) {
// do stuff
// `svg` `data URI`
console.log(data);
}, function (jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
});
jsfiddle http://jsfiddle.net/R8A8P/58/
this html worked in react
<a
href={chart.getImageURI()}
download="chart.png">
getImage
</a>
How can I get base64 with image inside of svg? Check this Fiddle that I got from another question. If you see the second graphic, its not generating the image that overlays the bar.
var chart = new google.visualization.ColumnChart(document.getElementById('chart_survey'));
$("[fill='#FFFFFF']").each(function( index, element ) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttributeNS(null,'x',element.x.baseVal.value);
svgimg.setAttributeNS(null,'y',element.y.baseVal.value);
svgimg.setAttributeNS(null,'width',element.width.baseVal.value);
svgimg.setAttributeNS(null,'height',element.height.baseVal.value);
svgimg.setAttributeNS(null,'preserveAspectRatio','none');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', '${application.contextPath}/images/textura/patt.gif');
$(element).parent().append(svgimg);
});
$('#test').val(chart.getImageURI())
In order to save this svg to a png, which keeps the linked <image> then you'll have to encode each <image>'s href to a dataURL first.
Edit
I rewrote the original snippets (which can still be found in the edit history).
I changed the <image> tags to <use>. This results in a much smaller memory usage.
I also added a fallback for IE11, which accepts to encode the external image to data URL, but still fails to convert svg to png via canvas.
The fallback will replace the destination <img>tag, with the canvas. The later can be saved by user with a right click.
A few caveats :
It doesn't work in Safari 7, and maybe in other outdated webkit browsers. That's a strange bug, since it does work like a charm in localhost, but won't on any other network (even on my home network, using 192.168.xxx).
IE 9 & IE 10 will fail to convert the external images to data URL, CORS problem.
// What to do with the result (either data URL or directly the canvas if tainted)
var callback = function(d, isTainted) {
if (!isTainted) {
$('#chartImg')[0].src = d;
} else
$('#chartImg')[0].parentNode.replaceChild(d, $('#chartImg')[0]);
};
// The url of the external image (must be cross-origin compliant)
var extURL = 'https://dl.dropboxusercontent.com/s/13dv8vzmrlcmla2/tex2.jpg';
google.load('visualization', '1', {
packages: ['corechart']
})
var encodeCall = getbase64URI.bind(this, extURL, callback);
google.setOnLoadCallback(encodeCall);
// Google Chart part
function drawVisualizationDaily(imgUrl, callback, isTainted) {
var data = google.visualization.arrayToDataTable([
['Daily', 'Sales'],
['Mon', 4],
['Tue', 6],
['Wed', 6],
['Thu', 5],
['Fri', 3],
['Sat', 7],
['Sun', 7]
]);
var chart = new google.visualization.ColumnChart(document.getElementById('visualization'));
chart.draw(data, {
title: "Daily Sales",
width: 500,
height: 400,
hAxis: {
title: "Daily"
}
});
// Link to chart's svg element
var svgNode = chart.ea.querySelector('svg');
// Create a symbol for our image
var symbol = document.createElementNS('http://www.w3.org/2000/svg', 'symbol');
// An svg wrapper to allow size changing with <use>
symbol.setAttributeNS(null, 'viewBox', '0,0,10,10');
symbol.setAttributeNS(null, 'preserveAspectRatio', 'none');
symbol.id = 'background';
// And the actual image, with our encoded image
var img = document.createElementNS('http://www.w3.org/2000/svg', 'image');
img.setAttributeNS(null, 'preserveAspectRatio', 'none');
img.setAttributeNS(null, 'width', '100%');
img.setAttributeNS(null, 'height', '100%');
img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imgUrl);
symbol.appendChild(img);
svgNode.appendChild(symbol);
var blueRects = $("[fill='#3366cc']");
var max = blueRects.length - 1;
blueRects.each(function(index, element) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg', 'use');
svgimg.setAttributeNS(null, 'x', element.x.baseVal.value);
svgimg.setAttributeNS(null, 'y', element.y.baseVal.value);
svgimg.setAttributeNS(null, 'width', element.width.baseVal.value);
svgimg.setAttributeNS(null, 'height', element.height.baseVal.value);
svgimg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#background');
svgNode.appendChild(svgimg);
if (index === max && !isTainted) // no need to call it if we don't have our dataURL encoded images
// a load event would be better but it doesn't fire in IE ...
setTimeout(exportSVG.bind(this, svgNode, callback, isTainted), 200);
});
}
function exportSVG(svgNode, callback, isTainted) {
var svgData = (new XMLSerializer()).serializeToString(svgNode);
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = svgNode.getAttribute('width');
canvas.height = svgNode.getAttribute('height');
canvas.getContext('2d').drawImage(this, 0, 0);
var data, isTainted;
try {
data = canvas.toDataURL();
} catch (e) {
data = canvas;
isTainted = true;
}
callback(data, isTainted);
}
img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
}
// A simple function to convert an images's url to base64 data URL
function getbase64URI(url, callback) {
var img = new Image();
img.crossOrigin = "Anonymous";
img.onload = function() {
var c = document.createElement('canvas');
c.width = this.width;
c.height = this.height;
c.getContext('2d').drawImage(this, 0, 0);
var isTainted;
try {
c.toDataURL();
} catch (e) {
isTainted = true;
}
// if the canvas is tainted, return the url
var output = (isTainted) ? url : c.toDataURL();
drawVisualizationDaily(output, callback, isTainted);
}
img.src = url;
}
svg { border: 1px solid yellow; }
img { border: 1px solid green; }
canvas { border: 1px solid red; }
<script src="http://www.google.com/jsapi?.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="visualization"></div>
Right-click this image to save it:
<br>
<img id="chartImg" />
This example creates an svg container populated by an image. In my example the image is an svg image but you should be able to put in any type of image (jpg, png, gif). The container is created first then the image is created inside the container.
// create svg
var svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
svg.setAttribute('class','shadowed handle_icon_sensors');
svg.setAttribute('height','25');
svg.setAttribute('width','25');
svg.setAttribute('id',idAttr);
svg.setAttribute('z-index','21000');
document.getElementById("zones_container").appendChild(svg);
// create svg image
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttribute('height','25');
svgimg.setAttribute('width','25');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href','svg/icon_sensorYellow.svg');
svgimg.setAttribute('x','0');
svgimg.setAttribute('y','0');
document.getElementById(idAttr).appendChild(svgimg);
Note, When converted to src of img element retained blue background-color .
Try , after .each()
// set namespace attributes
var svg = $("svg").attr({
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:xlink": "http://www.w3.org/1999/xlink"
})[0];
// create `data URI` of `svg`
var dataURI = "data:image/svg+xml;charset=utf-8;base64," + btoa(svg.outerHTML.trim());
// post `svg` as `data URI` to server
$.post("/path/to/server/", {
html: dataURI
}, "html")
.then(function (data) {
// do stuff
// `svg` `data URI`
console.log(data);
}, function (jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
});
jsfiddle http://jsfiddle.net/R8A8P/58/
this html worked in react
<a
href={chart.getImageURI()}
download="chart.png">
getImage
</a>
First off see this Fiddle
I want to create a canvas on the fly and append it to a particular DIV and draw an inline svg onto the canvas. But does not work as expected.
var randn = '1';
function createme(){
alert("completed 0");
var crCavs = $('<canvas />',{ id : 'mycanvs'+randn })
$('#album').append(crCavs);
alert("completed 1");
var svg2 =document.getElementById('sVgsource'+randn).outerHTML,
vms =document.getElementById('mycanvs'+randn), // target canvas
ctx2 =vms.getContext('2d');
//callback
svgToImage(svg2, function(img2){
vms.width =$('#sVgsource'+randn).width();
vms.height =$('#sVgsource'+randn).height();
alert("completed 3");
ctx2.drawImage(img2, 30, 40);
alert("completed 4");
}
function svgToImage(svg2, callback) {
var nurl = "data:image/svg+xml;utf8," + encodeURIComponent(svg2),
img2 = new Image;
//invoke callback
callback(img2);
img2.src = nurl;
alert("completed 2");
}
}
createme();
You are missing an end-parenthesis for the svgToImage() function:
svgToImage(svg2, function(img2) {
vms.width = img2.width;
vms.height = img2.height;
alert("completed 3");
ctx2.drawImage(img2, 0, 0);
alert("completed 4");
}); // <-- here
There are also some other issues:
Just reuse the canvas element:
var canvCrtrWrp = $('<canvas />',{ id : 'mycanvs'+randn })
...
var vms = canvCrtrWrp[0]; // index 0 is the actual canvas element
You could also use the width from the produced image on the canvas:
svgToImage(svg2, function(img2) {
vms.width = img2.width;
vms.height = img2.height;
...
Remember to use the onload handler for image (it was removed from the original code).If not an image element is passed back without any actual image data (need some time to load, decode etc.):
function svgToImage(svg2, callback) {
var nurl = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg2),
img2 = new Image;
img2.onload = function() {
callback(this);
}
...
etc.
Updated fiddle.
I have a html5 canvas where you can erase the blur on top of an image. I would like to replace the blur with another image. I would like the end result to be once you erase the top image the bottom image will appear below it. I have been using an easeljs demo as a template.
http://www.createjs.com/#!/EaselJS/demos/alphamask
I feel like what I need to edit is in the html page script but it might be much deeper than that.
(Full code can be viewed here)
HTML
<canvas id="testCanvas" width="960" height="400"></canvas>
JavaScript
var stage;
var isDrawing;
var drawingCanvas;
var oldPt;
var oldMidPt;
var displayCanvas;
var image;
var bitmap;
var maskFilter;
var cursor;
var text;
var blur;
function init() {
if (window.top != window) {
document.getElementById("header").style.display = "none";
}
document.getElementById("loader").className = "loader";
image = new Image();
image.onload = handleComplete;
image.src = "images/summer.jpg";
stage = new createjs.Stage("testCanvas");
text = new createjs.Text("Loading...", "20px Arial", "#999999");
text.set({x:stage.canvas.width/2, y:stage.canvas.height-80});
text.textAlign = "center";
}
function handleComplete() {
document.getElementById("loader").className = "";
createjs.Touch.enable(stage);
stage.enableMouseOver();
stage.addEventListener("stagemousedown", handleMouseDown);
stage.addEventListener("stagemouseup", handleMouseUp);
stage.addEventListener("stagemousemove", handleMouseMove);
drawingCanvas = new createjs.Shape();
bitmap = new createjs.Bitmap(image);
blur = new createjs.Bitmap(image);
blur.filters = [new createjs.BoxBlurFilter(15,15,2)];
blur.cache(0,0,960,400);
blur.alpha = .5;
text.text = "Click and Drag to Reveal the Image.";
stage.addChild(blur, text, bitmap);
updateCacheImage(false);
cursor = new createjs.Shape(new createjs.Graphics().beginFill("#FFFFFF").drawCircle(0,0,20));
cursor.cursor = "pointer";
stage.addChild(cursor);
}
function handleMouseDown(event) {
oldPt = new createjs.Point(stage.mouseX, stage.mouseY);
oldMidPt = oldPt;
isDrawing = true;
}
function handleMouseMove(event) {
cursor.x = stage.mouseX;
cursor.y = stage.mouseY;
if (!isDrawing) {
stage.update();
return;
}
var midPoint = new createjs.Point(oldPt.x + stage.mouseX>>1, oldPt.y+stage.mouseY>>1);
drawingCanvas.graphics.setStrokeStyle(40, "round", "round")
.beginStroke("rgba(0,0,0,0.15)")
.moveTo(midPoint.x, midPoint.y)
.curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);
oldPt.x = stage.mouseX;
oldPt.y = stage.mouseY;
oldMidPt.x = midPoint.x;
oldMidPt.y = midPoint.y;
updateCacheImage(true);
}
function handleMouseUp(event) {
updateCacheImage(true);
isDrawing = false;
}
function updateCacheImage(update) {
if (update) {
drawingCanvas.updateCache(0, 0, image.width, image.height);
} else {
drawingCanvas.cache(0, 0, image.width, image.height);
}
maskFilter = new createjs.AlphaMaskFilter(drawingCanvas.cacheCanvas);
bitmap.filters = [maskFilter];
if (update) {
bitmap.updateCache(0, 0, image.width, image.height);
} else {
bitmap.cache(0, 0, image.width, image.height);
}
stage.update();
}
If you simply want to replace the blur-image, you have to change the following parts:
Add this after the loading of the first image:
image.src = "images/summer.jpg";
// add new part
image2 = new Image();
image2.onload = handleComplete;
image2.src = "images/your_newImage.jpg";
In the handleComplete() you now wait for 2 images to be loaded, so you add this:
function handleComplete() {
loaded++; // and initialize this variable in the very top with: var loaded = 0;
if ( window.loaded < 2 ) return;
//... other stull
and finally you change the following lines:
// old
blur = new createjs.Bitmap(image);
blur.filters = [new createjs.BoxBlurFilter(15,15,2)];
blur.cache(0,0,960,400);
blur.alpha = .5;
// new
blur = new createjs.Bitmap(image2);
This should now replace the blurred image with your desired image, it's not the best way, but it should get you there. I recommend you to start with some tutorial if you are planing to do more "deeper" stuff ;)
a common, though kinda janky, way is to re-size your canvas real quick. so changing your <canvas> elements width and height attributes. This will erase everything in your canvas.
Once that is done, reset it back to what you want it to be right away, and redraw the bottom image.
As I said this method is kinda sketchy but it does get the job done.