Reputation: 1243
I would like to save and print my canvas "multiplied" so that the final result is an image 4 canvases wide and 2 canvases tall. I'm wondering if it is possible to either:
Why?
I tried scaling my canvas in my print dialog when I'd go to print it but I was only able to get it to print more than 6 or less than 9 per page. I also figure having one solid image would be cleaner.
Visuals
Here's what I'd like to save and print for:
Code
var activeCanvas, front, back, canvas1, canvas2;
$(document).ready(function() {
canvas1 = new fabric.Canvas('front');
canvas2 = new fabric.Canvas('back');
canvas1.setHeight(360);
canvas1.setWidth(208);
canvas2.setHeight(360);
canvas2.setWidth(208);
changeView(1);
var padding = 20;
canvas1.on('object:moving', onObjectMoving);
canvas2.on('object:moving', onObjectMoving);
function onObjectMoving(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);
}
};
});
function changeView(value) {
if (value == 1) {
activeCanvas = canvas1;
$('#front').parent().css('display', 'block');
$('#back').parent().css('display', 'none');
}
if (value == 2) {
activeCanvas = canvas2;
$('#front').parent().css('display', 'none');
$('#back').parent().css('display', 'block');
}
}
// Add Text
function dropText() {
var text = new fabric.Text('Hello', {
top: 20,
left: 20,
});
activeCanvas.add(text);
}
// Save
function download(url, name) {
// make the link. set the href and download. emulate dom click
$('<a>').attr({
href: url,
download: name
})[0].click();
}
function downloadFabric(canvas, name) {
// convert the canvas to a data url and download it.
download(activeCanvas.toDataURL({
multiplier: 2
}), name + '.png');
}
// Print
function printCanvas() {
var dataUrl = document.getElementById('activeCanvas').toDataURL();
var windowContent = '<!DOCTYPE html>';
windowContent += '<html>'
windowContent += '<head><title>Print canvas</title></head>';
windowContent += '<body>'
windowContent += '<img src="' + dataUrl + '" onload=window.print();window.close();>';
windowContent += '</body>';
windowContent += '</html>';
var printWin = window.open('', '', 'width=340,height=260');
printWin.document.open();
printWin.document.write(windowContent);
}
canvas {
border: 1px solid #dddddd;
margin-top: 10px;
border-radius: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<button onclick="changeView(1);">Front</button>
<button onclick="changeView(2);">Back</button>
<button onclick="dropText();">Add Text</button>
<button onclick="downloadFabric()">Save</button>
<button onclick="">Print</button>
<div style="text-align: center">
<canvas id="front"></canvas>
<canvas id="back"></canvas>
</div>
Upvotes: 4
Views: 363
Reputation:
push Run code snippet!
you should generate something similar and to work more on css for printing note this code isn't a final code you can use in production you need to put css values correctly for printing
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<style type="text/css">
.rTable {
display: table;
width: 100%;/* =208*4 */
}
.rTableRow {
display: table-row;
}
.rTableHeading {
display: table-header-group;
background-color: #ddd;
}
.rTableCell, .rTableHead {
display: table-cell;
padding: 3px 10px;
border: 1px solid #999999;
width:208pt;/*use values in pt !*/
height:360pt;
}
.rTableHeading {
display: table-header-group;
background-color: #ddd;
font-weight: bold;
}
.rTableFoot {
display: table-footer-group;
font-weight: bold;
background-color: #ddd;
}
.rTableBody {
display: table-row-group;
}
body{
margin:0;
}
</style>
<title>Document</title>
</head>
<body >
<!-- <script src="../js/jquery.js"></script>-->
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script> -->
<div class="rTable">
<div class="rTableRow">
<div class="rTableRow">
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
</div>
<div class="rTableRow">
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
<div class="rTableCell"><canvas id="front"></canvas><canvas id="back"></canvas></div>
</div>
</div>
</div>
<script type="text/javascript">
<!--
$('canvas#back').each(function(index) {
//console.log(index + ': ' + $(this).text());
context=$(this).get(0).getContext('2d');
context.font = 'italic 20pt Calibri';
context.fillText('Hello!', 20, 20);
});
//-->
</script>
</body>
</html>
Upvotes: 1
Reputation: 2600
I think the best solution would be to create a grid of 4x2 canvases, with all but the first being invisible initially. Then when you are about to print, clone the canvas - you can convert a canvas to JSON as follows:
var json = JSON.stringify(canvas);
And then load that JSON into as many canvases as you wish:
canvas2.loadFromJSON(json);
Here's a very simple fiddle. You'll need a bit of extra CSS to get the layout of your canvases right.
Upvotes: 3