3

I'm implementing client side download of some (High)charts that I have. What I'm doing now is getting the SVG source of the charts, creating a "canvas" element & drawing the SVG to said element, and then downloading the image using toBlob/Filesaver.js. See code below:

// draw the svg to a canvas
var c = document.createElement("canvas");
canvg(c, file);

// scrape the image from the canvas as png or jpg and download it in full quality
c.toBlob(function (blob) {
  saveAs(blob, fileName);
}, contentType, 1);

Right now the download works fine as expected, but it seems that the canvas element I created, c, has been attached to the window and sticks around even after the download finishes.

Calling c.remove() doesn't help. c.parentNode and c.parentElement are null (obviously since I haven't attached c to the DOM) so I can't call removeChild(c) on anything.

I'm wondering how can I remove/delete element c? Is c = undefined/null good enough? Is there a more elegant way?

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
nal88
  • 33
  • 4

2 Answers2

3

Once c goes out of scope, it should get garbage collected automatically, so as long as canvg doesn't keep an unnecessary reference to it.

To ensure c eventually becomes not referenceable anymore, put the whole code in an IIFE:

(() => {
  // draw the svg to a canvas
  var c = document.createElement("canvas");
  canvg(c, file);

  // scrape the image from the canvas as png or jpg and download it in full quality
  c.toBlob(function (blob) {
    saveAs(blob, fileName);
  }, contentType, 1);
})();

(otherwise, it'll stick around as window.c)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • This did the trick! I agree that `c` should have been garbage collected as long as canvg is not keeping a reference. But why would putting the logic inside an IIFE prevent that unnecessary reference? – nal88 May 21 '19 at 06:08
  • @nal88 Because variables initialized with `var` on the top level (eg inside a ` – CertainPerformance May 21 '19 at 07:31
0

Yes previous answer is right but you can also clear canvas, by setting the smallest size of it

(() => {
     var c = document.createElement("canvas");
      canvg(c, file);
      c.toBlob(function (blob) {
              saveAs(blob, fileName);
              c.width = c.height = 0;
      }, contentType, 1); 
})()
Alex Nikulin
  • 8,194
  • 4
  • 35
  • 37
  • Is there an added benefit to clearing the canvas before letting the garbage collector remove it? – nal88 May 21 '19 at 06:16
  • 1
    Smallest size is 0. Setting the size of a canvas which has an active context does trigger a lot of garbage (basically a new context + a new baking buffer). The GC will only kick when it will have to anyway. You won't win anything by doing this, quite the contrary. – Kaiido May 21 '19 at 06:35
  • @Kaiido if i will draw a white rectangle on it?) GC just will remove from memory after some time, and while it not be removed this canvas will be less sized – Alex Nikulin May 23 '19 at 04:21
  • White is 255,255,255,255 => the worse in terms of raw size... and once again, changing the size of your canvas just creates new trashes that should get collected too. Just leave the canvas as it is, makes sure no reference holds and let the browser do its job. – Kaiido May 23 '19 at 04:27