Print 2 sides of canvas (as the 4 x 2) instead of just the front and back of the editable canvas
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

Goal: Print 2 sides of canvas (as the 4 x 2) instead of just the front and back of the editable canvas

I'd like to have the Save as PNG and Print Canvases as PDF work in that it saves the end result of the preview (both sides). Here is an updated Codepen (kudos Wuddrum) of what I'm working with. Here's a gif to hopefully help demonstrate what I mean; the 4 x 2 should save/print twice—once for each side of each view. In other words, saving (2 images) and printing as pdf (2 separate pages) should result the way it does now, but 4 x 2 instead of just the single canvas.

My only criteria are that the other functionality remains working with the mainCanvas. Drop Text, for example. This is mainly because I'm trying to have this work with some other code that operates on the mainCanvas (aka active canvas / view).

I'm interested in seeing what you come up with! Please let me know if I can answer any questions that will help you produce a solution. I am willing to tip for extended edits and the like.

Thank you,

sharper

awarded to enderdba

Crowdsource coding tasks.

1 Solution

Winning solution

Check my solution below, it adds a function that recursively checks the width and height of all the canvases and makes an auxiliary canvas to help you get what you want to achieve. You just need to copy and paste.

EDIT: Heres the codepen forked from yours
https://codepen.io/enderdba/pen/RJzRKo

var mainCanvas,
  canvas1,
  canvas2,
  padding = 10,
  view = false;
var previewCanvas = [];
var previewCanvasCount = 8;

function dropText() {
  var text = new fabric.IText("text");
  mainCanvas.add(text);
}

function changeView(value) {
  if (view) {
    $viewText.textContent = "Back";
    mainCanvas = canvas1;
    $("#canvas1")
      .parent()
      .css("display", "");
    $("#canvas2")
      .parent()
      .css("display", "none");
  } else {
    $viewText.textContent = "Front";
    mainCanvas = canvas2;
    $("#canvas1")
      .parent()
      .css("display", "none");
    $("#canvas2")
      .parent()
      .css("display", "");
  }
  updatePreviewCanvas();
  view = !view;
}

function updatePreviewCanvas() {
  var json = JSON.stringify(mainCanvas);
  for (i = 1; i <= previewCanvasCount; i++) {
    previewCanvas[i].loadFromJSON(json);
  }
}

function onCanvasModified(option) {
  var ob = option.target;
  var index = mainCanvas.getObjects().indexOf(ob);
  ob.clone(function(obj) {
    for (i = 1; i <= previewCanvasCount; i++) {
      previewCanvas[i].insertAt(obj, index, true);
    }
  });
}

function togglePreviewCanvases() {
  $(".previewCanvasArea").toggleClass("invisible");
}

// Save as image
function download(url, name) {
  $("<a>")
    .attr({
      href: url,
      download: name
    })[0]
    .click();
}

function create42canvas(canvas){
  var canvasAux = document.createElement("canvas");
  console.log(canvasAux);
  canvasAux.width = ($(canvas).width() * 4);
  canvasAux.height = ($(canvas).height() * 2);
  console.log(canvasAux);
  var context = canvasAux.getContext('2d');
  console.log(context);
  var x = 0;
  var y = 0; 
  for(var i = 0; i < 8; i++){
    if(x == ($(canvas).width() * 4)){
      x = 0;
      y = $(canvas).height(); 
    }
    context.drawImage(canvas,x,y);
    x += ($(canvas).width());
  }
  return canvasAux;
}

function save() {
  mainCanvas.deactivateAll().renderAll();
  var c = document.getElementById("canvas1");
  c = create42canvas(c);
  var dataURL = c.toDataURL();
  var name = "image-front";
  download(dataURL, name + ".png");
  var c = document.getElementById("canvas2");
  c = create42canvas(c);
  var dataURL = c.toDataURL();
  var name = "image-back";
  var img=new Image();
img.src=dataURL;
 download(dataURL, name + ".png");
}

$(function() {
  $viewText = document.querySelector("#viewText");
  canvas1 = new fabric.Canvas("canvas1");
  canvas1.on("object:added", onCanvasModified);
  canvas1.on("object:modified", onCanvasModified);
  canvas1.on("object:scaling", onCanvasModified);
  canvas1.on("object:moving", onCanvasModified);
  canvas2 = new fabric.Canvas("canvas2");
  canvas2.on("object:added", onCanvasModified);
  canvas2.on("object:modified", onCanvasModified);
  canvas2.on("object:scaling", onCanvasModified);
  canvas2.on("object:moving", onCanvasModified);
  for (i = 1; i <= previewCanvasCount; i++) {
    $(".previewCanvasArea").append(
      '<canvas id="previewCanvas' +
        i +
        '" width="187.5" height="318.75"></canvas>'
    );
    previewCanvas[i] = new fabric.StaticCanvas("previewCanvas" + i);
  }
  changeView(1);

  // canvas2json
  $("#canvas2json").click(function() {
    var json = {};
    json.c1 = canvas1.toJSON(["selectable"]);
    json.c2 = canvas2.toJSON(["selectable"]);
    $("#myTextArea").text(JSON.stringify(json));
    var a = document.createElement("a");
    var file = new Blob([JSON.stringify(json)], {
      type: "text/plain"
    });
    a.href = URL.createObjectURL(file);
    a.download = "json.txt";
    a.click();
  });

  // load json2canvas
  $("#loadJson2Canvas").click(function() {
    var dataToLoad = JSON.parse($("#myTextArea").val());
    canvas1.loadFromJSON(dataToLoad.c1, canvas1.renderAll.bind(canvas1));
    canvas2.loadFromJSON(dataToLoad.c2, canvas2.renderAll.bind(canvas2));
  });

  $("#jsonload").change(function(e) {
    var file = e.target.files[0];
    if (!file) return;
    var reader = new FileReader();
    reader.onload = function(f) {
      var data = f.target.result;
      data = JSON.parse(data);

      canvas1.loadFromJSON(data.c1, canvas1.renderAll.bind(canvas1));
      canvas2.loadFromJSON(data.c2, canvas2.renderAll.bind(canvas2));
    };
    reader.readAsText(file);
  });
  $(this).val(null);

  // Bleed area
  mainCanvas.on("object:moving", function(e) {
    var obj = e.target;

    // if object is too big ignore
    if (
      obj.currentHeight > obj.canvas.height - padding * 2 ||
      obj.currentWidth > obj.canvas.width - padding * 2
    ) {
      return;
    }
    obj.setCoords();

    // top-left corner
    if (
      obj.getBoundingRect().top < padding ||
      obj.getBoundingRect().left < padding
    ) {
      obj.top = Math.max(
        obj.top,
        obj.top - obj.getBoundingRect().top + padding
      );
      obj.left = Math.max(
        obj.left,
        obj.left - obj.getBoundingRect().left + padding
      );
    }

    // bot-right corner
    if (
      obj.getBoundingRect().top + obj.getBoundingRect().height >
        obj.canvas.height - padding ||
      obj.getBoundingRect().left + obj.getBoundingRect().width >
        obj.canvas.width - padding
    ) {
      obj.top = Math.min(
        obj.top,
        obj.canvas.height -
          obj.getBoundingRect().height +
          obj.top -
          obj.getBoundingRect().top -
          padding
      );
      obj.left = Math.min(
        obj.left,
        obj.canvas.width -
          obj.getBoundingRect().width +
          obj.left -
          obj.getBoundingRect().left -
          padding
      );
    }
  });

  $("#save").click(save);

  // Print GOOD
  $("#print").click(function() {
    mainCanvas.deactivateAll().renderAll();
    var canvas1 = document.getElementById("canvas1");
    canvas1 = create42canvas(canvas1);
    var dataUrl1 = canvas1.toDataURL();
        var canvas2 = document.getElementById("canvas2");
    canvas2 = create42canvas(canvas2);
    var dataUrl2 = canvas2.toDataURL();
    var windowContent = "<!DOCTYPE html>";
    windowContent += "<html>";
    windowContent += "<head><title>Print</title>";
    windowContent +=
      "<style>@media print{.page-break{display:block; page-break-before:always;}}</style>";
    windowContent += "</head>";
    windowContent += "<body>";
    windowContent +=
      '<img src="' + dataUrl1 + '" onload=window.print();window.close();>';
    windowContent += '<div class="page-break"></div>';
    windowContent +=
      '<img src="' + dataUrl2 + '" onload=window.print();window.close();>';
    windowContent += "</body>";
    windowContent += "</html>";
    var printWin = window.open("", "", "width=748,height=636");
    printWin.document.open();
    printWin.document.write(windowContent);
  });
});
You're a godsend. Thank you for your help. :)
sharper 3 months ago
@Enderdba hey again I was going through the CodePen again and noticed that the front isn't being pushed the downloaded image or the print/save as PDF. They're going to the correct page, but as you can see here https://monosnap.com/direct/MShbYK596w6YVwdOHyj6CvW9ndpGSY there is some strange cutting/cropping of first page. Why might this be? Are you getting this too? Thanks
sharper 2 months ago
I tested it and its just happening with the save pdf, can you please send me a json to test it?
enderdba 2 months ago
Sure thing!. I tested it one more time and, oddly, it's doing it with both of them now (for me, I mean). Testing further, myself, too.
sharper 2 months ago