How to animate a mask svg from js? - javascript

How to animate using js mask, and masked the layer and layer mask svg? Without using third-party libraries?
<svg id="mask-layer" width="200" height="50" >
<defs>
<mask id="mask">
<rect width="200" height="50" style="fill: red" />
</mask>
</defs>
<rect id="masked" width="200" height="50" style="fill: red"/>
</svg>
Need to make a moving mask.
Was looking for an answer all day and is desperate. I will be glad to any advice on the topic.

You can draw one rect over another.
HTML:
<svg id="mask-layer" width="200" height="50" >
<rect id="masked" width="200" height="50" style="fill: blue"/>
<rect id='mask' width="0" height="50" style="fill: red" />
</svg>
<br />
<span id='progress'></span>
Javascript:
(function() {
var mask = document.getElementById('mask');
var progressSpan = document.getElementById('progress');
var fullWidth = 200;
var curWidth = mask.getAttribute('width');
var calculateProgress = function() {
var progress = (curWidth*100)/fullWidth;
progressSpan.innerHTML = ['Progress: ', Math.floor(progress), '%'].join('');
}
var interval = setInterval(function() {
mask.setAttribute('width', ++curWidth);
calculateProgress();
if(curWidth > fullWidth) {
clearInterval(interval);
progressSpan.innerHTML = 'Finished!';
}
}, 50);
})();
Here you have working example: https://jsfiddle.net/L1vy2t3o/

Using svg mask, you can do something like this:
(function() {
var btnMove = document.getElementById("btnMove");
var rect = document.getElementById("rect");
var pos = 100;
btnMove.addEventListener("click", function() {
rect.setAttribute("x", pos);
pos += 100;
});
})();
<svg id="mask-layer" width="200" height="50">
<defs>
<mask id="mask" style="stroke: #9595C6;">
<rect width="200" height="50" />
</mask>
</defs>
<rect id="rect" x="0" y="0" width="200" height="50" style="fill: #9595C6;" />
<rect x="0" y="0" width="200" height="50" mask="url(#mask)" />
</svg>
<br />
<button id="btnMove">Move</button>

Related

Using SVG with IDs for subcomponents

I am trying (in javascript) to access parts of a list of SVG components in a little test page, but I am not sure I can achieve what I want this way. The main question is:
Can I have sub-components having the same id in the two SVG top components?
In the code hereafter I want to change the color inside the first disk and the first rectangle. Here is what I tried, but it is not working.
Any tip would be appreciated.
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name=viewport content='width=device-width, initial-scale=1'>
<title>SVG-ID-Test</title>
</head>
<body>
<svg id="theSVGOne" width="200" height="300" fill="#d55">
<circle id="theCircle" cx="100" cy="75" r="50"
stroke="firebrick" fill="#ddd" stroke-width="3" />
<rect id="theRectangle" x="30" y="140" width="110" height="30"
stroke="black" fill="#ddd" stroke-width="3" />
</svg>
<svg id="theSVGTwo" width="200" height="200">
<circle id="theCircle" cx="100" cy="75" r="50"
stroke="firebrick" fill="#ddd" stroke-width="3" />
<rect id="theRectangle" x="30" y="140" width="110" height="30"
stroke="black" fill="#ddd" stroke-width="3" />
</svg>
<div id="status"></div>
<script type='text/javascript'>
let svgOne = document.getElementById('theSVGOne')
let svgTwo = document.getElementById('theSVGTwo')
let statusPane = document.getElementById('status')
statusPane.innerHTML = 'svgOne => '+svgOne.childElementCount.toString()
let circOne = svgOne.firstChild
let rctOne = svgOne.lastChild
circOne.setAttribute(('fill', '#ec3'))
rctOne.setAttribute(('fill', '#e3c'))
</script>
</body>
You can use a class instead of id on the child elements (you can have as many duplicate class attributes as you want in the document) and then use querySelector on each svg to target specific children.
let svgOne = document.getElementById('theSVGOne')
let svgTwo = document.getElementById('theSVGTwo')
let statusPane = document.getElementById('status')
statusPane.innerHTML = 'svgOne => '+svgOne.childElementCount.toString()
let circOne = svgOne.querySelector(".theCircle")
let rctOne = svgOne.querySelector(".theRectangle")
circOne.setAttribute('fill', '#ec3')
rctOne.setAttribute('fill', '#e3c')
let circTwo = svgTwo.querySelector(".theCircle")
let rctTwo = svgTwo.querySelector(".theRectangle")
circTwo.setAttribute('fill', 'blue')
rctTwo.setAttribute('fill', 'green')
<svg id="theSVGOne" width="200" height="300" fill="#d55">
<circle class="theCircle" cx="100" cy="75" r="50" stroke="firebrick" fill="#ddd" stroke-width="3" />
<rect class="theRectangle" x="30" y="140" width="110" height="30" stroke="black" fill="#ddd" stroke-width="3" />
</svg>
<svg id="theSVGTwo" width="200" height="200">
<circle class="theCircle" cx="100" cy="75" r="50" stroke="firebrick" fill="#ddd" stroke-width="3" />
<rect class="theRectangle" x="30" y="140" width="110" height="30" stroke="black" fill="#ddd" stroke-width="3" />
</svg>
<div id="status"></div>
Don't use IDs
While technically you can have duplicate ids in the DOM (and make it work), this is very bad practise. Id stands for identifier and should be unique to be able to "tell them apart". You can't do that with identical ids (which theCircle are we talking about?).
Problem is, html won't complain about duplicate ids (no errors are thrown).
To actually get feedback on right or wrong markup you can go to w3's validator and check your html there.
Eg. Error: Duplicate ID theCircle.
Working (but wrong) example using id:
let svgOne = document.getElementById('theSVGOne')
let svgTwo = document.getElementById('theSVGTwo')
let statusPane = document.getElementById('status')
statusPane.innerHTML = 'svgOne => '+svgOne.childElementCount.toString()
let circOne = svgOne.getElementById("theCircle")
let rctOne = svgOne.getElementById("theRectangle")
circOne.setAttribute('fill', '#ec3')
rctOne.setAttribute('fill', '#e3c')
let circTwo = svgTwo.getElementById("theCircle")
let rctTwo = svgTwo.getElementById("theRectangle")
circTwo.setAttribute('fill', 'pink')
rctTwo.setAttribute('fill', 'teal')
<svg id="theSVGOne" width="200" height="300" fill="#d55">
<circle id="theCircle" cx="100" cy="75" r="50" stroke="firebrick" fill="#ddd" stroke-width="3" />
<rect id="theRectangle" x="30" y="140" width="110" height="30" stroke="black" fill="#ddd" stroke-width="3" />
</svg>
<svg id="theSVGTwo" width="200" height="200">
<circle id="theCircle" cx="100" cy="75" r="50" stroke="firebrick" fill="#ddd" stroke-width="3" />
<rect id="theRectangle" x="30" y="140" width="110" height="30" stroke="black" fill="#ddd" stroke-width="3" />
</svg>
<div id="status"></div>

Transform origin on SVG pattern not working on Firefox/Safari

I made a hexagonal grid with an SVG pattern.
To zoom in, I used transform's scale function, and to keep it scaling from the center I set transform-origin to the center of the page.
This is perfectly working on Chrome but not on Safari and Firefox.
How can I make it work on all browsers?
Here's what I made so far:
const pattern = document.getElementById('hexagons');
const center = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
};
const transformOrigin = `${center.x}px ${center.y}px`;
let zoom = 1;
const formatPatternTransform = (zoom) => `rotate(90) scale(${zoom})`;
function animate() {
if (zoom > 3)
return;
zoom += .005;
pattern.setAttribute('patternTransform', formatPatternTransform(zoom));
requestAnimationFrame(animate);
}
pattern.setAttribute('transform-origin', transformOrigin);
animate();
* {
margin: 0;
padding: 0;
}
svg {
background: #0a0a0a;
height: 100vh;
width: 100vw;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
why not simply scaling the whole SVG:
* {
margin: 0;
padding: 0;
}
svg {
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background: #0a0a0a;
animation:zoom 3s ease-out forwards
}
#keyframes zoom {
to {
transform:scale(3);
}
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
To avoid the lag you can keep you JS code:
let s = document.querySelector('svg');
let zoom = 1;
function animate() {
if (zoom > 3)
return;
zoom += .005;
s.style.transform = "scale(" + zoom + ")";
requestAnimationFrame(animate);
}
animate();
* {
margin: 0;
padding: 0;
}
svg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0a0a0a;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
You can easily zoom out too:
let s = document.querySelector('svg');
let zoom = 1;
function animate() {
if (zoom < 0.2)
return;
zoom -= .005;
s.style.transform = "scale(" + zoom + ")";
requestAnimationFrame(animate);
}
animate();
* {
margin: 0;
padding: 0;
}
svg {
position:fixed;
top:-300%;
left:-300%;
width:700%;
height:700%;
background: #0a0a0a;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
This is an alternative solution. Instead of using transform-origin you can center the <rect id="mosaic" around the origin of the svg canvas. In this case you will need a viewBox attribute: viewBox="-250 -250 500 500" and preserveAspectRatio="xMidYMid slice"
"xMidYMid (the default) - Force uniform scaling.
Align the midpoint X value of the element's viewBox with the midpoint X value of the viewport.
Align the midpoint Y value of the element's viewBox with the midpoint Y value of the viewport."
"slice - Scale the graphic such that:
aspect ratio is preserved
the entire viewport is covered by the viewBox
the viewBox is scaled down as much as possible, while still meeting the other criteria"
And this is the rectangle filled with the pattern:
<rect id="mosaic" x="-250" y="-250" width="500" height="500" fill="url(#hexagons)" />
Next comes a working example:
const pattern = document.getElementById('hexagons');
const center = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
};
//const transformOrigin = `${center.x}px ${center.y}px`;
let zoom = 1;
const formatPatternTransform = (zoom) => `rotate(90) scale(${zoom})`;
function animate() {
if (zoom > 3)
return;
zoom += .005;
pattern.setAttribute('patternTransform', formatPatternTransform(zoom));
requestAnimationFrame(animate);
}
//pattern.setAttribute('transform-origin', transformOrigin);
animate();
* {
margin: 0;
padding: 0;
}
svg {
background: #0a0a0a;
height: 100vh;
width: 100vw;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-250 -250 500 500" preserveAspectRatio="xMidYMid slice">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" x="-250" y="-250" width="500" height="500" fill="url(#hexagons)" />
</svg>

SVG text and image centered within a rectangle

I'm really not familiar with SVG's so I'm sorry if this is actually a fairly easy problem..
I'm creating an SVG:
<svg height="100%" width="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#da552f"></rect>
<image xlink:href="https://d30y9cdsu7xlg0.cloudfront.net/noun-svg/703414.svg?Expires=1481685113&Signature=hsa76aA6t5W6xisN8bYKk5t74cmOzTXmYUObaVwE0hUso99Gb4czprrsQAtkaC0aOQJBhNfAn8MjRpKyu8M~AzS5OS3rthGOLFqa3Pk2lCwAWjs-KtTa9fSo7w-sZSJwG6LDeRm5B6T5hYnoKQLibJzCtHvSdUYlp5XBUx1RNvs_&Key-Pair-Id=APKAI5ZVHAXN65CHVU2Q" transform="translate(-35.5,-31)" x="50%" y="50%" height="50px" width="50px"/>
<text fill="#ffffff" x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" font-size="48" font-family="Verdana">Kitty Cat</text>
</svg>
And as you can see both the image of the cat and the text are centered in the rectangle, but this isn't the desired effect I want.
I'd like the image to be next to the text and both of them be centered in the rectangle.. example:
How is this doable using SVGs? Is javascript required? Any help would be great! Thanks
Unlike HTML, SVG has no automatic layout of groups of elements.
You have two choices:
Cheat and put your image and text in HTML and use a <foreignObject> element to embed the HTML in your SVG. Although it is barely an SVG any more. And that only works in browsers.
Use Javascript to measure the text and then re-position it in the centre.
function reCentre() {
var svg = document.getElementById("mysvg");
var group = document.getElementById("centreMe");
// Get the bounding box of the image+text group
var groupBounds = group.getBBox();
// Get the size of the SVG on the page
var svgBounds = svg.getBoundingClientRect();
// Calculate new position for the group
var groupPosX = (svgBounds.width - groupBounds.width) / 2;
var groupPosY = (svgBounds.height - groupBounds.height) / 2;
// Calculate the difference between the groups current position
// and where it needs to be in order to be centred.
var dx = groupPosX - groupBounds.x;
var dy = groupPosY - groupBounds.y;
// Give the group a translate transform to move it to this new position
group.setAttribute("transform", "translate("+dx+","+dy+")");
}
// Initial centering
reCentre();
// Also recentre when window resizes
window.addEventListener("resize", reCentre);
<svg id="mysvg" height="100%" width="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#da552f"></rect>
<g id="centreMe">
<image xlink:href="https://d30y9cdsu7xlg0.cloudfront.net/noun-svg/703414.svg?Expires=1481685113&Signature=hsa76aA6t5W6xisN8bYKk5t74cmOzTXmYUObaVwE0hUso99Gb4czprrsQAtkaC0aOQJBhNfAn8MjRpKyu8M~AzS5OS3rthGOLFqa3Pk2lCwAWjs-KtTa9fSo7w-sZSJwG6LDeRm5B6T5hYnoKQLibJzCtHvSdUYlp5XBUx1RNvs_&Key-Pair-Id=APKAI5ZVHAXN65CHVU2Q" x="0" y="-50" height="50px" width="50px"/>
<text fill="#ffffff" x="80" y="0" font-size="48" font-family="Verdana">Kitty Cat</text>
</g>
</svg>
Edit the x and y attributes of the image tag until the cat face is where you would like it.
<svg height="100%" width="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#da552f"></rect>
<image xlink:href="https://d30y9cdsu7xlg0.cloudfront.net/noun-svg/703414.svg?Expires=1481685113&Signature=hsa76aA6t5W6xisN8bYKk5t74cmOzTXmYUObaVwE0hUso99Gb4czprrsQAtkaC0aOQJBhNfAn8MjRpKyu8M~AzS5OS3rthGOLFqa3Pk2lCwAWjs-KtTa9fSo7w-sZSJwG6LDeRm5B6T5hYnoKQLibJzCtHvSdUYlp5XBUx1RNvs_&Key-Pair-Id=APKAI5ZVHAXN65CHVU2Q" transform="translate(-35.5,-31)" x="25%" y="45%" height="50px" width="50px"/>
<text fill="#ffffff" x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" font-size="48" font-family="Verdana">Kitty Cat</text>
</svg>
you could use a webfont or an emoji instead of an image...
svg {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px
}
<svg viewBox="0 0 400 200">
<rect x="0" y="0" width="400" height="200" fill="pink" />
<text x="200" y="100" dominant-baseline="middle" text-anchor="middle" font-size="30" font-family="sans serif">
<tspan font-size="50">🐱</tspan>Kitty Cat</text>
</svg>

Scaling after rotation changes the position of rect element

Original rect, with a rotation:
<rect id="location_1" x="40" y="40" height="100" width="100" fill="red" stroke="2" stroke-width="2" transform="rotate(45, 90, 90)"></rect>
After scaling, the rotation center is changed based on the new bbox:
<rect id="location_1" x="40" y="40" height="200" width="200" fill="red" stroke="2" stroke-width="2" transform="rotate(45, 140, 140)"></rect>
After scaling of the rect, if we update the rotation center then the postion of the rect is changed. But if we do not update the center then it works as expected, till the other transformations are applied.
Scale as in updating width and height, not the scale transform
My question is how to scale keeping the position of the element same.?
JSFiddle with the situation
If clicked on Scale - No Update the position is not changed but when clicked on Scale - Update the position changes.
function scaleAndUpdate(id, update) {
var
elem = document.getElementById(id),
bbox, cx, cy;
elem.setAttribute('width', 200);
elem.setAttribute('height', 200);
if (update) {
bbox = elem.getBBox();
cx = bbox.x + (bbox.width / 2);
cy = bbox.y + (bbox.height / 2);
elem.setAttribute('transform', 'rotate(45, ' + cx + ', ' + cy + ')');
}
}
function reset(id) {
var
elem = document.getElementById(id);
elem.setAttribute('x', 40);
elem.setAttribute('y', 40);
elem.setAttribute('width', 100);
elem.setAttribute('height', 100);
elem.setAttribute('transform', 'rotate(45, 90, 90)');
}
<div>
<svg x="0" y="0" width="300" height="300" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="smallGrid" width="10" height="10" patternUnits="userSpaceOnUse">
<path d="M 10 0 L 0 0 0 10" fill="none" stroke="gray" stroke-width="0.5" />
</pattern>
<pattern id="grid" width="100" height="100" patternUnits="userSpaceOnUse">
<rect width="100" height="100" fill="url(#smallGrid)" />
<path d="M 100 0 L 0 0 0 100" fill="none" stroke="gray" stroke-width="1" />
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#grid)" style="pointer-events: none;"></rect>
<g id="locationGroup">
<rect id="location_1" x="40" y="40" height="100" width="100" fill="red" stroke="2" stroke-width="2" transform="rotate(45, 90, 90)"></rect>
<circle cx="90" cy="20" r="5" fill="black"></circle>
</g>
</svg>
<button onclick="scaleAndUpdate('location_1')">Scale - No Update</button>
<button onclick="scaleAndUpdate('location_1', true)">Scale - Update</button>
<button onclick="reset('location_1')">Reset</button>
</div>

How can I covert multiple svg's into a png as it is they are on html?

I want exact png of my svg displayed on page as an output, Is it possible?
I have my html code here :
<html>
<head>
<title>Vikas</title>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<svg width="50" height="50">
<circle cx="25" cy="25" r="25" fill="purple" />
</svg>
<svg width="50" height="50">
<circle cx="25" cy="25" r="25" fill="purple" />
</svg>
<svg width="100" height="100">
<circle cx="25" cy="25" r="25" fill="purple" />
</svg>
<svg width="400" height="110">
<rect width="300" height="100" style="fill:rgb(0,0,255);strokewidth:3;stroke:rgb(0,0,0)">
</svg>
</body>
</html>
There are some libraries to convert some part of the DOM to images.
This is one of them: https://github.com/tsayen/dom-to-image
Maybe you can find it useful
Try something like this example:
window.onload= function() {
domtoimage.toPng(document.getElementById('myDrawing'))
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
};
//Libraries here:
/*! dom-to-image 24-04-2016 */
!function(a){"use strict";function b(a,b){function c(a){return b.bgcolor&&(a.style.backgroundColor=b.bgcolor),b.width&&(a.style.width=b.width+"px"),b.height&&(a.style.height=b.height+"px"),b.style&&Object.keys(b.style).forEach(function(c){a.style[c]=b.style[c]}),a}return b=b||{},Promise.resolve(a).then(function(a){return g(a,b.filter,!0)}).then(h).then(i).then(c).then(function(c){return j(c,b.width||a.scrollWidth,b.height||a.scrollHeight)})}function c(a,b){return f(a,b||{}).then(function(b){return b.getContext("2d").getImageData(0,0,a.scrollWidth,a.scrollHeight).data})}function d(a,b){return f(a,b||{}).then(function(a){return a.toDataURL()})}function e(a,b){return f(a,b||{}).then(o.canvasToBlob)}function f(a,c){function d(a){var b=document.createElement("canvas");return b.width=c.width||a.scrollWidth,b.height=c.height||a.scrollHeight,b}return b(a,c).then(o.makeImage).then(o.delay(100)).then(function(b){var c=d(a);return c.getContext("2d").drawImage(b,0,0),c})}function g(a,b,c){function d(a){return a instanceof HTMLCanvasElement?o.makeImage(a.toDataURL()):a.cloneNode(!1)}function e(a,b,c){function d(a,b,c){var d=Promise.resolve();return b.forEach(function(b){d=d.then(function(){return g(b,c)}).then(function(b){b&&a.appendChild(b)})}),d}var e=a.childNodes;return 0===e.length?Promise.resolve(b):d(b,o.asArray(e),c).then(function(){return b})}function f(a,b){function c(){function c(a,b){function c(a,b){o.asArray(a).forEach(function(c){b.setProperty(c,a.getPropertyValue(c),a.getPropertyPriority(c))})}a.cssText?b.cssText=a.cssText:c(a,b)}c(window.getComputedStyle(a),b.style)}function d(){function c(c){function d(a,b,c){function d(a){var b=a.getPropertyValue("content");return a.cssText+" content: "+b+";"}function e(a){function b(b){return b+": "+a.getPropertyValue(b)+(a.getPropertyPriority(b)?" !important":"")}return o.asArray(a).map(b).join("; ")+";"}var f="."+a+":"+b,g=c.cssText?d(c):e(c);return document.createTextNode(f+"{"+g+"}")}var e=window.getComputedStyle(a,c),f=e.getPropertyValue("content");if(""!==f&&"none"!==f){var g=o.uid();b.className=b.className+" "+g;var h=document.createElement("style");h.appendChild(d(g,c,e)),b.appendChild(h)}}[":before",":after"].forEach(function(a){c(a)})}function e(){a instanceof HTMLTextAreaElement&&(b.innerHTML=a.value),a instanceof HTMLInputElement&&b.setAttribute("value",a.value)}function f(){b instanceof SVGElement&&(b.setAttribute("xmlns","http://www.w3.org/2000/svg"),b instanceof SVGRectElement&&["width","height"].forEach(function(a){var c=b.getAttribute(a);c&&b.style.setProperty(a,c)}))}return b instanceof Element?Promise.resolve().then(c).then(d).then(e).then(f).then(function(){return b}):b}return c||!b||b(a)?Promise.resolve(a).then(d).then(function(c){return e(a,c,b)}).then(function(b){return f(a,b)}):Promise.resolve()}function h(a){return q.resolveAll().then(function(b){var c=document.createElement("style");return a.appendChild(c),c.appendChild(document.createTextNode(b)),a})}function i(a){return r.inlineAll(a).then(function(){return a})}function j(a,b,c){return Promise.resolve(a).then(function(a){return a.setAttribute("xmlns","http://www.w3.org/1999/xhtml"),(new XMLSerializer).serializeToString(a)}).then(o.escapeXhtml).then(function(a){return'<foreignObject x="0" y="0" width="100%" height="100%">'+a+"</foreignObject>"}).then(function(a){return'<svg xmlns="http://www.w3.org/2000/svg" width="'+b+'" height="'+c+'">'+a+"</svg>"}).then(function(a){return"data:image/svg+xml;charset=utf-8,"+a})}function k(){function a(){var a="application/font-woff",b="image/jpeg";return{woff:a,woff2:a,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:b,jpeg:b,gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml"}}function b(a){var b=/\.([^\.\/]*?)$/g.exec(a);return b?b[1]:""}function c(c){var d=b(c).toLowerCase();return a()[d]||""}function d(a){return-1!==a.search(/^(data:)/)}function e(a){return new Promise(function(b){for(var c=window.atob(a.toDataURL().split(",")[1]),d=c.length,e=new Uint8Array(d),f=0;d>f;f++)e[f]=c.charCodeAt(f);b(new Blob([e],{type:"image/png"}))})}function f(a){return a.toBlob?new Promise(function(b){a.toBlob(b)}):e(a)}function g(a,b){var c=document.implementation.createHTMLDocument(),d=c.createElement("base");c.head.appendChild(d);var e=c.createElement("a");return c.body.appendChild(e),d.href=b,e.href=a,e.href}function h(){var a=0;return function(){function b(){return("0000"+(Math.random()*Math.pow(36,4)<<0).toString(36)).slice(-4)}return"u"+b()+a++}}function i(a){return new Promise(function(b,c){var d=new Image;d.onload=function(){b(d)},d.onerror=c,d.src=a})}function j(a){var b=3e4;return new Promise(function(c){function d(){if(4===g.readyState){if(200!==g.status)return void f("cannot fetch resource: "+a+", status: "+g.status);var b=new FileReader;b.onloadend=function(){var a=b.result.split(/,/)[1];c(a)},b.readAsDataURL(g.response)}}function e(){f("timeout of "+b+"ms occured while fetching resource: "+a)}function f(a){console.error(a),c("")}var g=new XMLHttpRequest;g.onreadystatechange=d,g.ontimeout=e,g.responseType="blob",g.timeout=b,g.open("GET",a,!0),g.send()})}function k(a,b){return"data:"+b+";base64,"+a}function l(a){return a.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1")}function m(a){return function(b){return new Promise(function(c){setTimeout(function(){c(b)},a)})}}function n(a){for(var b=[],c=a.length,d=0;c>d;d++)b.push(a[d]);return b}function o(a){return a.replace(/#/g,"%23").replace(/\n/g,"%0A")}return{escape:l,parseExtension:b,mimeType:c,dataAsUrl:k,isDataUrl:d,canvasToBlob:f,resolveUrl:g,getAndEncode:j,uid:h(),delay:m,asArray:n,escapeXhtml:o,makeImage:i}}function l(){function a(a){return-1!==a.search(e)}function b(a){for(var b,c=[];null!==(b=e.exec(a));)c.push(b[1]);return c.filter(function(a){return!o.isDataUrl(a)})}function c(a,b,c,d){function e(a){return new RegExp("(url\\(['\"]?)("+o.escape(a)+")(['\"]?\\))","g")}return Promise.resolve(b).then(function(a){return c?o.resolveUrl(a,c):a}).then(d||o.getAndEncode).then(function(a){return o.dataAsUrl(a,o.mimeType(b))}).then(function(c){return a.replace(e(b),"$1"+c+"$3")})}function d(d,e,f){function g(){return!a(d)}return g()?Promise.resolve(d):Promise.resolve(d).then(b).then(function(a){var b=Promise.resolve(d);return a.forEach(function(a){b=b.then(function(b){return c(b,a,e,f)})}),b})}var e=/url\(['"]?([^'"]+?)['"]?\)/g;return{inlineAll:d,shouldProcess:a,impl:{readUrls:b,inline:c}}}function m(){function a(){return b(document).then(function(a){return Promise.all(a.map(function(a){return a.resolve()}))}).then(function(a){return a.join("\n")})}function b(){function a(a){return a.filter(function(a){return a.type===CSSRule.FONT_FACE_RULE}).filter(function(a){return p.shouldProcess(a.style.getPropertyValue("src"))})}function b(a){var b=[];return a.forEach(function(a){try{o.asArray(a.cssRules||[]).forEach(b.push.bind(b))}catch(c){console.log("Error while reading CSS rules from "+a.href,c.toString())}}),b}function c(a){return{resolve:function(){var b=(a.parentStyleSheet||{}).href;return p.inlineAll(a.cssText,b)},src:function(){return a.style.getPropertyValue("src")}}}return Promise.resolve(o.asArray(document.styleSheets)).then(b).then(a).then(function(a){return a.map(c)})}return{resolveAll:a,impl:{readAll:b}}}function n(){function a(a){function b(b){return o.isDataUrl(a.src)?Promise.resolve():Promise.resolve(a.src).then(b||o.getAndEncode).then(function(b){return o.dataAsUrl(b,o.mimeType(a.src))}).then(function(b){return new Promise(function(c,d){a.onload=c,a.onerror=d,a.src=b})})}return{inline:b}}function b(c){function d(a){var b=a.style.getPropertyValue("background");return b?p.inlineAll(b).then(function(b){a.style.setProperty("background",b,a.style.getPropertyPriority("background"))}).then(function(){return a}):Promise.resolve(a)}return c instanceof Element?d(c).then(function(){return c instanceof HTMLImageElement?a(c).inline():Promise.all(o.asArray(c.childNodes).map(function(a){return b(a)}))}):Promise.resolve(c)}return{inlineAll:b,impl:{newImage:a}}}var o=k(),p=l(),q=m(),r=n(),s={toSvg:b,toPng:d,toBlob:e,toPixelData:c,impl:{fontFaces:q,images:r,util:o,inliner:p}};"undefined"!=typeof module?module.exports=s:a.domtoimage=s}(this);
/*! #source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs=saveAs||function(e){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var t=e.document,n=function(){return e.URL||e.webkitURL||e},o=t.createElementNS("http://www.w3.org/1999/xhtml","a"),r="download"in o,i=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},a=/Version\/[\d\.]+.*Safari/.test(navigator.userAgent),c=e.webkitRequestFileSystem,f=e.requestFileSystem||c||e.mozRequestFileSystem,u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},d="application/octet-stream",s=0,l=4e4,v=function(e){var t=function(){"string"==typeof e?n().revokeObjectURL(e):e.remove()};setTimeout(t,l)},p=function(e,t,n){t=[].concat(t);for(var o=t.length;o--;){var r=e["on"+t[o]];if("function"==typeof r)try{r.call(e,n||e)}catch(i){u(i)}}},w=function(e){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\ufeff",e],{type:e.type}):e},y=function(t,u,l){l||(t=w(t));var y,m,S,h=this,R=t.type,O=!1,g=function(){p(h,"writestart progress write writeend".split(" "))},b=function(){if(m&&a&&"undefined"!=typeof FileReader){var o=new FileReader;return o.onloadend=function(){var e=o.result;m.location.href="data:attachment/file"+e.slice(e.search(/[,;]/)),h.readyState=h.DONE,g()},o.readAsDataURL(t),void(h.readyState=h.INIT)}if((O||!y)&&(y=n().createObjectURL(t)),m)m.location.href=y;else{var r=e.open(y,"_blank");void 0===r&&a&&(e.location.href=y)}h.readyState=h.DONE,g(),v(y)},E=function(e){return function(){return h.readyState!==h.DONE?e.apply(this,arguments):void 0}},N={create:!0,exclusive:!1};return h.readyState=h.INIT,u||(u="download"),r?(y=n().createObjectURL(t),void setTimeout(function(){o.href=y,o.download=u,i(o),g(),v(y),h.readyState=h.DONE})):(e.chrome&&R&&R!==d&&(S=t.slice||t.webkitSlice,t=S.call(t,0,t.size,d),O=!0),c&&"download"!==u&&(u+=".download"),(R===d||c)&&(m=e),f?(s+=t.size,void f(e.TEMPORARY,s,E(function(e){e.root.getDirectory("saved",N,E(function(e){var n=function(){e.getFile(u,N,E(function(e){e.createWriter(E(function(n){n.onwriteend=function(t){m.location.href=e.toURL(),h.readyState=h.DONE,p(h,"writeend",t),v(e)},n.onerror=function(){var e=n.error;e.code!==e.ABORT_ERR&&b()},"writestart progress write abort".split(" ").forEach(function(e){n["on"+e]=h["on"+e]}),n.write(t),h.abort=function(){n.abort(),h.readyState=h.DONE},h.readyState=h.WRITING}),b)}),b)};e.getFile(u,{create:!1},E(function(e){e.remove(),n()}),E(function(e){e.code===e.NOT_FOUND_ERR?n():b()}))}),b)}),b)):void b())},m=y.prototype,S=function(e,t,n){return new y(e,t,n)};return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t,n){return n||(e=w(e)),navigator.msSaveOrOpenBlob(e,t||"download")}:(m.abort=function(){var e=this;e.readyState=e.DONE,p(e,"abort")},m.readyState=m.INIT=0,m.WRITING=1,m.DONE=2,m.error=m.onwritestart=m.onprogress=m.onwrite=m.onabort=m.onerror=m.onwriteend=null,S)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!=typeof define&&null!==define&&null!==define.amd&&define([],function(){return saveAs});
<script src="https://raw.githubusercontent.com/tsayen/dom-to-image/master/dist/dom-to-image.min.js"></script>
<html>
<head>
<title>Vikas</title>
</head>
<body>
<div id="myDrawing">
<canvas id="myCanvas" width="578" height="200"></canvas>
<svg width="50" height="50">
<circle cx="25" cy="25" r="25" fill="purple" />
</svg>
<svg width="50" height="50">
<circle cx="25" cy="25" r="25" fill="purple" />
</svg>
<svg width="100" height="100">
<circle cx="25" cy="25" r="25" fill="purple" />
</svg>
<svg width="400" height="110">
<rect width="300" height="100" style="fill:rgb(0,0,255);strokewidth:3;stroke:rgb(0,0,0)">
</svg>
</div>
</body>
</html>
(Please note that I pasted both libraries dom-to-image and FileSaver, in my javascript. You should include sepparated js files instead)
Also, I included a wrapping element with id="myDrawing"

Categories

Resources