0

I am using KonvaJS in my project. I need to save the stage/canvas as an image(it would be great if exported image is high resolution image). KonvaJS has a function called stage.toDataURL() which returns canvas content as a Base64 string. The challenge with this function is that it only returns visible area of the canvas. I need to export entire canvas as image not only it's visible area. I tried with Canvas2Image but it is also saving only visible area not full canvas. Is there any way I can achieve it? Here's a plunkr to play with some poc(proof of concept) code.

var width = window.innerWidth;
var height = window.innerHeight;

var stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height
});

var layer = new Konva.Layer();

var rectX = stage.getWidth() / 2 - 50;
var rectY = stage.getHeight() / 2 - 25;

(function() {
  for (var i = 0; i < 50; i++) {
    layer.add(new Konva.Rect({
      x: i * 50,
      y: 0,
      width: 50,
      height: 10000,
      fill: Konva.Util.getRandomColor()
    }));
  }
})();

var box = new Konva.Rect({
  x: rectX,
  y: rectY,
  width: 100,
  height: 50,
  fill: '#00D2FF',
  stroke: 'black',
  strokeWidth: 4,
  draggable: true
});

box.on('mouseover', function() {
  document.body.style.cursor = 'pointer';
});

box.on('mouseout', function() {
  document.body.style.cursor = 'default';
});

layer.add(box);
layer.draw();
stage.add(layer);

function exportCanvas() {
  var dataURL = stage.toDataURL();
  window.open(dataURL);
}

document.getElementById('save').addEventListener('click', exportCanvas, false);
Hitesh Kumar
  • 3,508
  • 7
  • 40
  • 71
  • 1
    What are you using as the definition for "full canvas"? If you mean window.innerWidth and window.innerHeight, that is already working as-is. If you create a Rect that exceeds those boundaries (for example the height:10000 in your declaration), it will be cropped to the size of the canvas (in this case window.innerHeight). From what I can see, the plunkr is working as expected already. – binarymax Sep 23 '16 at 13:23
  • Ditto what @binarymax says: Any drawings that overflow the visible canvas are not actually rendered. So toDataURL fetches the whole visible canvas -- but never the undrawn overflow. ;-) If you want a 50x10000 canvas you can create one and then toDataURL will produce your "full" drawing – markE Sep 23 '16 at 13:33
  • @binarymax & markE Yes in my case it is exceeding the boundaries. I want to get those drawings as well which overflow the visible area. – Hitesh Kumar Sep 23 '16 at 13:52
  • @HiteshKumar in that case, you should be setting stage.height and stage.width to meet the full size requirements you need. For example, on line 7, set {height:10000} to be able to create a Rect of height 10000 that will be preserved. It is worth noting again that the 'visible area' as you describe, is really the 'entire area'. Just as a building has walls, the canvas has a set width and height, which cannot be exceeded when drawing. – binarymax Sep 23 '16 at 13:55
  • Gotcha, Thanks :) – Hitesh Kumar Sep 24 '16 at 04:45

1 Answers1

5

The best way to achieve this is to resize stage before export, then resize it back:

var oldSize = stage.size();

var exportSize = {
    width: 3000,
    height: 3000
};
stage.size(exportSize);
stage.draw();
var dataURL = stage.toDataURL(exportSize);
stage.size(oldSize);
stage.draw();

Demo: http://plnkr.co/edit/DiqsE7rZdDx3JIAyJZQK?p=preview

lavrton
  • 18,973
  • 4
  • 30
  • 63
  • 1
    Actually it is still better to call draw. – lavrton Sep 23 '16 at 18:37
  • Got it. Thank you very much. Now all I need to figure out is export of canvas as high resolution image. In POC code i have done simple drawing but in my actual project I have a background image on the canvas and some drawings on it. So when I export it, the requirement is it should be high resolution image(same as the background image). I am planning to resize the stage with image size and then export it. Please let me know if you have better approach for this. – Hitesh Kumar Sep 24 '16 at 05:04
  • 3
    toDataURL({pixelRatio: 2}) – lavrton Sep 25 '16 at 00:14