【问题标题】:How to multiply a canvases when saving and printing?保存和打印时如何乘以画布?
【发布时间】:2018-06-14 14:34:22
【问题描述】:

我想保存并打​​印“相乘”的画布,以便最终结果是 4 个画布宽和 2 个画布高的图像。我想知道是否有可能:

  • “将画布乘以 4 宽和 2 高”以得到结果
  • 让画布的大小为原始画布的 4 x 2,但只有原始画布大小的一部分可编辑,然后将该部分“复制/镜像”到画布的其余部分,以便它共创建 8 张图片。
  • 等;也许你会有更聪明的方法来实现这一点; 基本上我希望能够为同一张图片中的 8 张“编辑”一次

为什么?

当我要打印时,我尝试在打印对话框中缩放我的画布,但我只能让它每页打印超过 6 个或少于 9 个。我还认为拥有一张纯色图像会更干净。

视觉效果

这是我要保存和打印的内容:

代码

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>

【问题讨论】:

  • 也许您可以提供一张图片来说明预期的结果
  • 肯定会编辑!
  • 我重新考虑了我的问题并重写了它以试图更清楚。我还附上了一张我正在尝试保存和打印的照片。
  • 那么正面和背面呢?它们必须在纸张的一侧打印在一起(所以你必须将每一面乘以 4 次)?或者您可能只想在纸的一侧打印画布的一侧(因此您必须将每一面乘以 8 次)?
  • @Sam 理想情况下,后者使每一面都适合纸张的每一面

标签: javascript css canvas fabricjs


【解决方案1】:

我认为最好的解决方案是创建一个由 4x2 画布组成的网格,除了第一个画布之外,所有画布最初都是不可见的。然后,当您要打印时,克隆画布 - 您可以将画布转换为 JSON,如下所示:

var json = JSON.stringify(canvas);

然后将该 JSON 加载到任意数量的画布中:

canvas2.loadFromJSON(json);

Here's 一个非常简单的小提琴。您需要一些额外的 CSS 才能正确布局画布。

【讨论】:

  • 这看起来很有趣!一旦我拥有了所有的画布,我应该从那里去哪里?我能以某种方式结合这些吗?
  • 所以最初只有一个画布是可见的,这就是您编辑图像的地方。然后,当您要打印时,将内容复制到其他画布上,然后您应该在 4x2 网格中的屏幕上有 8 个相同的图像副本,如果您打印,则页面布局设置为横向并缩放到适合你的论文,你会得到想要的结果。
【解决方案2】:

push 运行代码 sn-p!

你应该生成类似的东西,并在 css 上工作更多以进行打印 请注意,此代码不是您可以在生产中使用的最终代码,您需要正确放置 css 值以进行打印

<!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>

【讨论】:

  • 附注还将它与@John M 的示例结合起来,您会更精确
  • 嗨,是的,这看起来像是我要尝试的路线。感谢您添加此@Constantin。我很感激!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-02
  • 2016-09-06
  • 2014-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多