0

I have tried to export the png image from svg element using Blob. Here, when i click the anchor tag the image has been exported but there is no content because of asynchronous method(image.onload()) called after complete the click event. How to resolve this problem?

<body>
    <a id="export">Click To Export</a>
    <div id="container" width=500px height=200px>
        <svg id="myViewer" width="500px" height="200px" xmlns="http://www.w3.org/2000/svg">
            <rect x="50" y="20" width="150" height="150" style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9"
            />
        </svg>
    </div>
    <script>
        document.getElementById('export').onclick = function () {
            var tag = document.getElementById('export');
            tag.download = 'Sample' + "." + 'png';
            tag.href = getCanvaElement().toDataURL();
        }

        function getCanvaElement() {
            var svgText = document.getElementById("myViewer").outerHTML;
            var svg = new Blob([svgText], { type: "image/svg+xml;charset=utf-8" });
            var domURL = self.URL || self.webkitURL || self;
            var url = domURL.createObjectURL(svg);
            var element = document.createElement('canvas');
            var ctx = element.getContext("2d");
            var image = new Image;
            image.onload = function () {
                ctx.drawImage(this, 0, 0);
                domURL.revokeObjectURL(url);
            };
            image.src = url;
            return element;
        }
    </script>
</body>

Sample Link: http://jsfiddle.net/kyjs655r/347/

Robert Longson
  • 118,664
  • 26
  • 252
  • 242
Akbar Basha
  • 1,168
  • 1
  • 16
  • 38
  • 1
    Your first line is going to get you few down votes. We close question as people who knows the real issue are more likely to get a more suited duplicate. So please do not ask us what and what not to do. Also please try to write your problem clearly. – Rajesh Oct 09 '17 at 05:36
  • I'm going to have to go ahead and mark this as a duplicate anyway, sorry. There are already many explanations how to deal with asynchronous function calls – Patrick Hund Oct 09 '17 at 05:40

1 Answers1

2

You can use Promise constructor and async/await, resolve() <canvas> element within <img> load event

 document.getElementById('export').onclick = async function() {
   var tag = document.getElementById('export');
   tag.download = 'Sample' + "." + 'png';
   const canvas = await getCanvaElement();
   tag.href = canvas.toDataURL();
 }

 function getCanvaElement() {
   return new Promise(resolve => {
     var svgText = document.getElementById("myViewer").outerHTML;
     var svg = new Blob([svgText], {
       type: "image/svg+xml;charset=utf-8"
     });
     var domURL = self.URL || self.webkitURL || self;
     var url = domURL.createObjectURL(svg);
     var element = document.createElement('canvas');
     var ctx = element.getContext("2d");
     var image = new Image;
     image.onload = function() {
       ctx.drawImage(this, 0, 0);
       domURL.revokeObjectURL(url);
       resolve(element)
     };
     image.src = url;
   })
 }

jsfiddle http://jsfiddle.net/kyjs655r/351/

guest271314
  • 1
  • 15
  • 104
  • 177