I want to import a SVG file using JavaScript and animate the graphic with CSS.
I'm able to import the file but
cursor: pointer
doesn't work and I'm not able to access the SVG graphics attributes like fill or totalPathLenght.
Where is the problem and how can I solve it?
I tried importing the SVG like this:
const myGraphic = document.createElement("object");
myGraphic.data = "mySVG.svg";
document.body.appendChild(myGraphic);
I also tried the same thing using iframe and embed
A good explanation on how to do this can be found here, I'll paraphrase and adapt it for what you are asking:
const svgElement = document.getElementById("svg");
const checkboxElement = document.getElementById("check");
checkboxElement.addEventListener("change", e => {
svgElement.style.fill = e.target.checked ? "PeachPuff" : "PapayaWhip";
});
#svg {
/* An example of how to set the cursor */
cursor: pointer;
}
<input type="checkbox" id="check" />
<svg id="svg" fill="AliceBlue">
<circle r="50" cx="70" cy="70" />
</svg>
I am trying to generate some SVG and allow users of my website to download these SVGs as PNGs.
After reading this I get all my external images included in the downloaded PNG.
Now I am trying to get the fonts on the PNG correct. This seems to answer that and so I added:
<defs>
<style type="text/css">
#font-face {
font-family: Parisienne;
src: url('data:application/font-woff;charset=utf-8;base64,.....')
}
</style>
</defs>
Where ..... is base64 encoded woff2 font. And then used it in text like so:
<text x="55" y="55" stroke="red" font-family="Parisienne">Blah</text>
The font gets displayed in the browser correctly (I haven't installed it on my OS), however it is still not included in the PNG.
Do I have to add some additional processing to the script I used from the first link?
Thanks.
--EDIT--
I have been asked for a complete example, here it is:
<svg id="generated-svg" class="generated-svg" width="300px" height="500px"
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink">
<defs>
<style type="text/css">
#font-face {
font-family: Parisienne;
src: url('data:application/font-woff;charset=utf-8;base64,.....')
}
</style>
</defs>
<rect width="300" height="500" fill="#222"/>
<text x="55" y="55" stroke="red" font-family="Parisienne" font-size="20px">Test text</text>
</svg>
I haven't added the base64 encoded font as it's simply too big. But you can encode any font you like and replace the ....... I am using Parisienne.
Here is working jsfiddle with the actual font: https://jsfiddle.net/z8539err/
In my browser this is the output:
Whilst after using the download script above I would end up with:
I'm able to include the font in the png itself with the following code, give it a try
var svg = document.getElementById('generated-svg');
var svgData = new XMLSerializer().serializeToString( svg );
var canvas = document.createElement("canvas");
canvas.width = 300;
canvas.height = 500;
var ctx = canvas.getContext("2d");
//display image
var img = document.createElement( "img" );
img.setAttribute( "src", "data:image/svg+xml;base64," + btoa( svgData ) );
img.onload = function() {
ctx.drawImage( img, 0, 0 );
//image link
console.log( canvas.toDataURL( "image/png" ) );
//open image
window.location.href=canvas.toDataURL( "image/png" );
};
https://jsfiddle.net/user3839189/hutvL4ks/1/
A working proof of concept project on GitHub to address OP problem statement.
https://github.com/nirus/SVG-PNG-Convert
Built generic Javascript module that can be modified and used anywhere. Read the documentation. Give it a try!
I am making use of canvg to convert svg present in div into canvas(upto this it's working fine) and then copying the innerHTML of div to another div, but it's not working. Canvas is coming but nothing will be present in that canvas.
Thanks in advance
<div id="k">
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
Sorry, your browser does not support inline SVG.
</svg>
</div>
<div id="kk">
<p>Watch me</p>
</div>
var svgTag = document.querySelectorAll('#k svg');
svgTag = svgTag[0];
var c = document.createElement('canvas');
c.width = svgTag.clientWidth;
c.height = svgTag.clientHeight;
svgTag.parentNode.insertBefore(c, svgTag);
svgTag.parentNode.removeChild(svgTag);
var div = document.createElement('div');
div.appendChild(svgTag);
canvg(c, div.innerHTML);
setTimeout(function(){
var data = $("#k").html();
$("#kk").append($(''+data+''));
},5000);
JSFiddle
The content of a canvas element is held as binary data, much like the content of an image element. Canvas elements do not have an innerHTML text property that can be used to recreate the canvas.
The following example shows a method of cloning a canvas element using standard canvas 2D methods:
function canvasClone(c1) {
var c2 = document.createElement('canvas');
c2.width=c1.width;
c2.height=c1.height;
c2.getContext("2d").drawImage(c1, 0,0);
return c2;
}
You can demonstrate it by including the function in the fiddle and changing the timeout processing to:
setTimeout(function(){
kk.appendChild(canvasClone(c));
},5000);
Feel free to rewrite the timeout code in JQuery if you prefer.
I want to drag path on SVG canvas.
The requirement is not to use any JS library.
Any example will help me.
I know with raphael.js its very easy.
Thanks.
Here is an example in pure JS:
<svg id='mysvg' height="800" width="800">
<path id='mypath' fill="#4444ff" stroke="#000000" d="M100,300L400,300L100,0Z" transform=""></path>
</svg>
JS:
el=document.getElementById("mypath");
sv=document.getElementById("mysvg");
flag=false; //to check if the mouse is currently down?
sv.onmousedown=function(e){
flag=true;
x1=e.clientX;
y1=e.clientY;
var t=el.getAttribute('transform');
if(t){
var parts = /translate\(\s*([^\s,)]+)[ ,]([^\s,)]+)/.exec(t);
var firstX = parts[1], firstY = parts[2];
x1=x1-firstX*1;
y1=y1-firstY*1;
}
/* x1 and y1 now contain the previous position*/
};
sv.onmousemove=function(e){
if(flag){
x=e.clientX;
y=e.clientY;
t="translate("+(x-x1)+","+(y-y1)+")"
el.setAttribute('transform',t);
}
};
sv.onmouseup=function(){flag=false};
fiddle: http://jsfiddle.net/gF8Wd/2/
I have created a html 5 canvas and added some shapes using
ctx.fillRect(X,Y,W,H); and some other javascript functions.
Now i want to add a svg graphic in multiple places of that canvas.
The reason i want to use a svg is the sharpness & quality of the image.
I tried using drawImage method in HTML5 but the image i want to draw is doesn't give a very quality output when it's added to the canvas using drawImage method.No matter how high resolution image i use it makes a very low quality image.
But i think using a svg graphic is the solution.
This is the code i used,
<canvas id="myCanvas" style="border: 2px solid #000000; width: 1280px; height: 800px;"></canvas>
<img id="location" src="location.png" alt="The Scream" width="25.5" height="41.5">
<script >
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillRect(4,4, 12,10);
ctx.fillStyle=fontBlack;
ctx.fillText("1",8,10);
ctx.fillRect(5,16, 7, 16);
ctx.fillRect(5,33, 7, 28);
ctx.fillRect(5,62, 7, 50);
ctx.fillRect(5,113, 7, 15);
ctx.fillRect(5,129, 7, 15);
//I have a list of coordinates in a javascript object list called selectedShelfList, I'm getting the necessary coordinates from that.
function drawLocations(){
for (var i=0; i<selectedShelfList.length; i++)
{
var x_coordinate = selectedShelfList[i].shelf_x;
var y_coordinate = selectedShelfList[i].shelf_y;
var img=document.getElementById("location");
ctx.drawImage(img,x_coordinate,y_coordinate,8.5,13.8);
//Instead of drawImage method i want to use a code to show a svg graphic here
}
}
</script >
As solutions i found on stackoverflow for this problem,
I tried using canvg.js as mentioned in the previous similar questions but it wasn't clear.
for example:
var ctx = document.getElementById('test').getContext('2d');
ctx.drawSvg('<svg><rect x="0" y="0" width="100" height="200" fill="red" /></svg>', 0 , 0 , 500, 500);
How shoul i give the url for external svg in this command?
Can i use the url in between the '' as the parameter for drawSvg ?
Eg: ctx.drawSvg('location.svg', 0 , 0 , 500, 500);
Is there any way i can show a svg graphic inside a canvas?
Can canvg do the trick? If so how exactly?
Please help me on this. :)
[Edited: include example of very small map pin]
Rendering a circle in a small 10 pixel boundary will always result in pixilation.
There's just too few pixels to "round" an edge.
Here's an example of a more square map pin that is far less pixelated:
You can produce this map pin in canvas code like this:
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(110,100);
ctx.lineTo(110,107);
ctx.lineTo(105,115);
ctx.lineTo(100,107);
ctx.lineTo(100,100);
ctx.closePath();
ctx.fillStyle="gold";
ctx.fill();
ctx.strokeStyle="black";
ctx.lineWidth=2;
ctx.stroke();
[Original answer]
SVG scales well since it is vector drawn.
You should be able to do this and get a high quality result:
Download this test image:
https://dl.dropboxusercontent.com/u/139992952/stackoverflow/rocket.svg
Then this code will scale the svg rocket while maintaining quality:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var size=100;
var svg1=new Image();
svg1.width=150;
svg1.onload=function(){
ctx.drawImage(svg1,0,0,size,size);
}
svg1.src="rocket.svg";
$("#bigger").click(function(){
size+=100;
ctx.drawImage(svg1,0,0,size,size);
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="bigger">Bigger!</button><br>
<canvas id="canvas" width=900 height=900></canvas>
</body>
</html>
Using the canvg worked!
var ctx = document.getElementById('test').getContext('2d');
ctx.drawSvg('location.svg', 0 , 0 , 100, 100);
using above code worked. Earlier I haven't add the javascript files into the html file properly.
Adding them to local folder worked
<script type="text/javascript" src="rgbcolor.js"></script>
<script type="text/javascript" src="StackBlur.js"></script>
<script type="text/javascript" src="canvg.js"></script>
Still the image quality is not that much but it's better than using an image with drawImage method.