如何以 100% 的页面宽度打印画布图像?

Posted

技术标签:

【中文标题】如何以 100% 的页面宽度打印画布图像?【英文标题】:How to print a canvas image at 100% page width? 【发布时间】:2018-02-16 16:01:18 【问题描述】:

我的项目需要打印出可以小于或大于页面宽度的画布图像。如果画布图像小于页面宽度,我希望打印输出保持画布大小,如果画布图像大于页面宽度则缩放。我该如何做到这一点?

这是一个画布图像对于打印页面来说太大的示例(需要缩小以适应):

var canvas = document.getElementById("canvas1");

var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html height:100%; overflow:hidden;
#main-container height:100%; padding:; margin:0;
display: flex;
flex-direction: column;



body height:100%; padding:0; margin:0; 
display: flex;
flex-direction: column;


header 
  background:aqua;
flex: 0 0 100px;

section background:blue;
flex: 1;
display: flex;
flex-direction: row;
  overflow:auto;

article 
  background:blanchedalmond;
flex: 3;

nav 
  background:coral;
flex: 1;
order: -1;
  /*start flex settings*/
  display:flex;
  flex-direction: column;
  justify-content: space-betweeen;
  -webkit-justify-content: space-between;
  
 /*end flex settings*/


.nav-bottom-container 
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;


.nav-item-top
  overflow-y:auto;


.nav-bottom-item-left 
  background:deeppink;
  order:1;
  border-color:red;
  border-style: solid;
  flex-grow:1;
  cursor: pointer;
  text-align:center;

.nav-bottom-item-right 
  background:dodgerblue;
  order:0;
  border-color:blue;
  border-style: solid;
  flex-grow:1;
  cursor: pointer;
  text-align:center;


aside background:#ddd;
flex: 0 0 200px;

footer background:#888;
flex: 0 0 100px;


.item-text
  font-size:1vmax;
  padding:1em;

canvas border: 1px solid black; 

#container 
    display: flex;           /* establish flex container */
    flex-direction: column;  /* make main axis vertical */
    justify-content: center; /* center items vertically, in this case */
    align-items: center;     /* center items horizontally, in this case */
  cursor:move;


.print-this-only
  




@media print 
  html,
  body 
    height:100%;
    overflow:hidden;
   display:block;
    background-color: yellow;
  
  .print-this-only 
    background-color: yellow;
    /*
            height: 100%;
    
            width: 100%;
            position: fixed;*/
    top: 0;
    left: 0;
    margin: 0;
  
  .no-print,
  .no-print * 
    display: none !important;
  
  .printOnly 
    display: block;
  
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title> Shrink Canvas to Fit Printed Page </title>
</head>

<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">
  
  <div id="main-container">
  
	<header class="no-print">fixed height header <button onclick="window.print();" class="no-print">Print Canvas</button></header>
	<section>
		<article id="id"><div id="container" >
  <div id="container"  class="print-this-only"style="position:relative">
    
<canvas   id="canvas1">
</canvas>
     
        <img src="http://s.cdpn.io/3/kiwi.svg" 
       style="position: absolute; 
              left: 0px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />
      
        <img src="http://s.cdpn.io/3/kiwi.svg" 
       style="position: absolute; 
              left: 150px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />
      
      
        <img src="http://s.cdpn.io/3/kiwi.svg" 
       style="position: absolute; 
              left: 1700px; 
              top:150px;
              z-index: 2;
              width: 100px;
       " />
      </>
      
</div></article>
		<nav class="no-print">
     
      
      <div class="nav-item-top">
        <div class="item-text">
          sample
        </div>
         <div class="item-text">
         sample this is a much longer sample text it goes on for a little bit here and there.
        </div>
        
          <div class="item-text">
          this is the end of the line and the end of the universe.
        </div>
        <div ng-show=vm.showNav>Right</div>
        <div ng-hide=vm.showNav>Left</div>
      
      
      </div>
      <div class="nav-bottom-container">
         <div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
      <div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>
   
      </div>
    </nav>
	
	</section>
  </div>


</body>
</html>

这是一个画布小于页面宽度并适当缩放的示例:

var canvas = document.getElementById("canvas1");

var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html height:100%; overflow:hidden;
#main-container height:100%; padding:; margin:0;
display: flex;
flex-direction: column;



body height:100%; padding:0; margin:0; 
display: flex;
flex-direction: column;


header 
  background:aqua;
flex: 0 0 100px;

section background:blue;
flex: 1;
display: flex;
flex-direction: row;
  overflow:auto;

article 
  background:blanchedalmond;
flex: 3;

nav 
  background:coral;
flex: 1;
order: -1;
  /*start flex settings*/
  display:flex;
  flex-direction: column;
  justify-content: space-betweeen;
  -webkit-justify-content: space-between;
  
 /*end flex settings*/


.nav-bottom-container 
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;


.nav-item-top
  overflow-y:auto;


.nav-bottom-item-left 
  background:deeppink;
  order:1;
  border-color:red;
  border-style: solid;
  flex-grow:1;
  cursor: pointer;
  text-align:center;

.nav-bottom-item-right 
  background:dodgerblue;
  order:0;
  border-color:blue;
  border-style: solid;
  flex-grow:1;
  cursor: pointer;
  text-align:center;


aside background:#ddd;
flex: 0 0 200px;

footer background:#888;
flex: 0 0 100px;


.item-text
  font-size:1vmax;
  padding:1em;

canvas border: 1px solid black; 

#container 
    display: flex;           /* establish flex container */
    flex-direction: column;  /* make main axis vertical */
    justify-content: center; /* center items vertically, in this case */
    align-items: center;     /* center items horizontally, in this case */
  cursor:move;


.print-this-only
  




@media print 
  html,
  body 
    height:100%;
    overflow:hidden;
   display:block;
    background-color: yellow;
  
  .print-this-only 
    background-color: yellow;
    /*
            height: 100%;
    
            width: 100%;
            position: fixed;*/
    top: 0;
    left: 0;
    margin: 0;
  
  .no-print,
  .no-print * 
    display: none !important;
  
  .printOnly 
    display: block;
  
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title> Shrink Canvas to Fit Printed Page </title>
</head>

<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">
  
  <div id="main-container">
  
	<header class="no-print">fixed height header <button onclick="window.print();" class="no-print">Print Canvas</button></header>
	<section>
		<article id="id"><div id="container" >
  <div id="container"  class="print-this-only"style="position:relative">
    
<canvas   id="canvas1">
</canvas>
     
        <img src="http://s.cdpn.io/3/kiwi.svg" 
       style="position: absolute; 
              left: 0px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />
      
        <img src="http://s.cdpn.io/3/kiwi.svg" 
       style="position: absolute; 
              left: 150px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />
      
      
        <img src="http://s.cdpn.io/3/kiwi.svg" 
       style="position: absolute; 
              left: 200px; 
              top:150px;
              z-index: 2;
              width: 100px;
       " />
      </>
      
</div></article>
		<nav class="no-print">
     
      
      <div class="nav-item-top">
        <div class="item-text">
          sample
        </div>
         <div class="item-text">
         sample this is a much longer sample text it goes on for a little bit here and there.
        </div>
        
          <div class="item-text">
          this is the end of the line and the end of the universe.
        </div>
        <div ng-show=vm.showNav>Right</div>
        <div ng-hide=vm.showNav>Left</div>
      
      
      </div>
      <div class="nav-bottom-container">
         <div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
      <div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>
   
      </div>
    </nav>
	
	</section>
  </div>


</body>
</html>

【问题讨论】:

【参考方案1】:

在您的打印样式中,您可以将overflow: hidden 添加到.print-this-only 并将其添加到canvas

.print-this-only canvas 
    max-width:100%;
    max-height: 100%;
    display: block;

现在您可以约束canvas。请注意,对于画布中的 第三个​​ 图像,您有 left: 1700px(在下面的演示中将其更改为 right: 0) - 这些图像的 位置值 需要是以 百分比 表示 缩放 是正确的。

var canvas = document.getElementById("canvas1");

var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html 
  height: 100%;
  overflow: hidden;


#main-container 
  height: 100%;
  padding: ;
  margin: 0;
  display: flex;
  flex-direction: column;


body 
  height: 100%;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;


header 
  background: aqua;
  flex: 0 0 100px;


section 
  background: blue;
  flex: 1;
  display: flex;
  flex-direction: row;
  overflow: auto;


article 
  background: blanchedalmond;
  flex: 3;


nav 
  background: coral;
  flex: 1;
  order: -1;
  /*start flex settings*/
  display: flex;
  flex-direction: column;
  justify-content: space-betweeen;
  -webkit-justify-content: space-between;
  /*end flex settings*/


.nav-bottom-container 
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;


.nav-item-top 
  overflow-y: auto;


.nav-bottom-item-left 
  background: deeppink;
  order: 1;
  border-color: red;
  border-style: solid;
  flex-grow: 1;
  cursor: pointer;
  text-align: center;


.nav-bottom-item-right 
  background: dodgerblue;
  order: 0;
  border-color: blue;
  border-style: solid;
  flex-grow: 1;
  cursor: pointer;
  text-align: center;


aside 
  background: #ddd;
  flex: 0 0 200px;


footer 
  background: #888;
  flex: 0 0 100px;


.item-text 
  font-size: 1vmax;
  padding: 1em;


canvas 
  border: 1px solid black;


#container 
  display: flex;
  /* establish flex container */
  flex-direction: column;
  /* make main axis vertical */
  justify-content: center;
  /* center items vertically, in this case */
  align-items: center;
  /* center items horizontally, in this case */
  cursor: move;


.print-this-only 

@media print 
  html,
  body 
    height: 100%;
    width: 100%;
    margin: 0;
    overflow: hidden;
    display: block;
    background-color: yellow;
  
  .print-this-only 
    background-color: yellow;
    top: 0;
    left: 0;
    margin: 0;
    overflow: hidden;
    /* ADDED */
  
  /* ADDED */
  .print-this-only canvas 
    max-width: 100%;
    max-height: 100%;
    display: block;
  
  .no-print,
  .no-print * 
    display: none !important;
  
  .printOnly 
    display: block;
  
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title> Shrink Canvas to Fit Printed Page </title>
</head>

<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">

  <div id="main-container">

    <header class="no-print">fixed height header <button onclick="window.print()" class="no-print">Print Canvas</button></header>
    <section>
      <article id="id">
        <div id="container">
          <div id="container" class="print-this-only" style="position:relative">

            <canvas   id="canvas1">
</canvas>

            <img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute; 
              left: 0px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />

            <img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute; 
              left: 150px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />


            <img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute; 
              right: 0; 
              top:150px;
              z-index: 2;
              width: 100px;
       " />
          </div>

        </div>
      </article>
      <nav class="no-print">


        <div class="nav-item-top">
          <div class="item-text">
            sample
          </div>
          <div class="item-text">
            sample this is a much longer sample text it goes on for a little bit here and there.
          </div>

          <div class="item-text">
            this is the end of the line and the end of the universe.
          </div>
          <div ng-show=vm.showNav>Right</div>
          <div ng-hide=vm.showNav>Left</div>


        </div>
        <div class="nav-bottom-container">
          <div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
          <div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>

        </div>
      </nav>

    </section>
  </div>
</body>

</html>

较小的canvas 的相同演示:

var canvas = document.getElementById("canvas1");

var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html 
  height: 100%;
  overflow: hidden;


#main-container 
  height: 100%;
  padding: ;
  margin: 0;
  display: flex;
  flex-direction: column;


body 
  height: 100%;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;


header 
  background: aqua;
  flex: 0 0 100px;


section 
  background: blue;
  flex: 1;
  display: flex;
  flex-direction: row;
  overflow: auto;


article 
  background: blanchedalmond;
  flex: 3;


nav 
  background: coral;
  flex: 1;
  order: -1;
  /*start flex settings*/
  display: flex;
  flex-direction: column;
  justify-content: space-betweeen;
  -webkit-justify-content: space-between;
  /*end flex settings*/


.nav-bottom-container 
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;


.nav-item-top 
  overflow-y: auto;


.nav-bottom-item-left 
  background: deeppink;
  order: 1;
  border-color: red;
  border-style: solid;
  flex-grow: 1;
  cursor: pointer;
  text-align: center;


.nav-bottom-item-right 
  background: dodgerblue;
  order: 0;
  border-color: blue;
  border-style: solid;
  flex-grow: 1;
  cursor: pointer;
  text-align: center;


aside 
  background: #ddd;
  flex: 0 0 200px;


footer 
  background: #888;
  flex: 0 0 100px;


.item-text 
  font-size: 1vmax;
  padding: 1em;


canvas 
  border: 1px solid black;


#container 
  display: flex;
  /* establish flex container */
  flex-direction: column;
  /* make main axis vertical */
  justify-content: center;
  /* center items vertically, in this case */
  align-items: center;
  /* center items horizontally, in this case */
  cursor: move;


.print-this-only 

@media print 
  html,
  body 
    height: 100%;
    width: 100%;
    margin: 0;
    overflow: hidden;
    display: block;
    background-color: yellow;
  
  .print-this-only 
    background-color: yellow;
    top: 0;
    left: 0;
    margin: 0;
    overflow: hidden;
    /* ADDED */
  
  /* ADDED */
  .print-this-only canvas 
    max-width: 100%;
    max-height: 100%;
    display: block;
  
  .no-print,
  .no-print * 
    display: none !important;
  
  .printOnly 
    display: block;
  
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title> Shrink Canvas to Fit Printed Page </title>
</head>

<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">

  <div id="main-container">

    <header class="no-print">fixed height header <button onclick="window.print();" class="no-print">Print Canvas</button></header>
    <section>
      <article id="id">
        <div id="container">
          <div id="container" class="print-this-only" style="position:relative">

            <canvas   id="canvas1">
</canvas>

            <img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute; 
              left: 0px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />

            <img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute; 
              left: 150px; 
              top:0px;
              z-index: 2;
              width: 100px;
       " />


            <img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute; 
              left: 200px; 
              top:150px;
              z-index: 2;
              width: 100px;
       " />
          </div>

        </div>
      </article>
      <nav class="no-print">


        <div class="nav-item-top">
          <div class="item-text">
            sample
          </div>
          <div class="item-text">
            sample this is a much longer sample text it goes on for a little bit here and there.
          </div>

          <div class="item-text">
            this is the end of the line and the end of the universe.
          </div>
          <div ng-show=vm.showNav>Right</div>
          <div ng-hide=vm.showNav>Left</div>


        </div>
        <div class="nav-bottom-container">
          <div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
          <div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>

        </div>
      </nav>

    </section>
  </div>


</body>

</html>

【讨论】:

【参考方案2】:

一种方法是将canvas 包装到容器中,而不是以父元素宽度的百分比计算所有内容。所以首先在 HTML 中:

<div class="canvas_container">
    <canvas   id="canvas1"></canvas>
</div>

比添加CSS:

@media print 
    #container 
        display: block; /* Cannot be flex here */
    
    .canvas_container 
        max-width: 100%;
        padding-bottom: 50%; /* Canvas is 2000x1000, this will set the height to 50% of width */
        position: relative;
    
    canvas
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        width: 100%;
    

比您的每个图像位置都必须以百分比为单位,宽度也必须以百分比为单位:

<img src="http://s.cdpn.io/3/kiwi.svg" 
    style="
        position: absolute; 
        left: 0; 
        top: 0;
        z-index: 2;
        width: 5%;
    "
/>

<img src="http://s.cdpn.io/3/kiwi.svg" 
    style="
        position: absolute; 
        left: 7%; 
        top: 0;
        z-index: 2;
        width: 5%;
    "
/>

<img src="http://s.cdpn.io/3/kiwi.svg" 
    style="
        position: absolute; 
        left: 85%; 
        top: 15%;
        z-index: 2;
        width: 5%;
    "
/>

完整代码如下:

<html xmlns="http://www.w3.org/1999/xhtml">

    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title> Shrink Canvas to Fit Printed Page </title>
        <style>
            html 
                height: 100%;
                overflow: hidden;
            
            
            #main-container 
                height: 100%;
                padding: ;
                margin: 0;
                display: flex;
                flex-direction: column;
            
            
            * 
                box-sizing: border-box;
            
            
            body 
                height: 100%;
                padding: 0;
                margin: 0;
                display: flex;
                flex-direction: column;
            
            
            header 
                background: aqua;
                flex: 0 0 100px;
            
            
            section 
                background: blue;
                flex: 1;
                display: flex;
                flex-direction: row;
                overflow: auto;
            
            
            article 
                background: blanchedalmond;
                flex: 3;
            
            
            nav 
                background: coral;
                flex: 1;
                order: -1;
                /*start flex settings*/
                display: flex;
                flex-direction: column;
                justify-content: space-betweeen;
                -webkit-justify-content: space-between;
                /*end flex settings*/
            
            
            .nav-bottom-container 
                display: flex;
                flex-direction: row;
                flex-wrap: nowrap;
                align-items: flex-start;
            
            
            .nav-item-top 
                overflow-y: auto;
            
            
            .nav-bottom-item-left 
                background: deeppink;
                order: 1;
                border-color: red;
                border-style: solid;
                flex-grow: 1;
                cursor: pointer;
                text-align: center;
            
            
            .nav-bottom-item-right 
                background: dodgerblue;
                order: 0;
                border-color: blue;
                border-style: solid;
                flex-grow: 1;
                cursor: pointer;
                text-align: center;
            
            
            aside 
                background: #ddd;
                flex: 0 0 200px;
            
            
            footer 
                background: #888;
                flex: 0 0 100px;
            
            
            .item-text 
                font-size: 1vmax;
                padding: 1em;
            
            
            canvas 
                border: 1px solid black;
            
            
            #container 
                display: flex;
                /* establish flex container */
                flex-direction: column;
                /* make main axis vertical */
                justify-content: center;
                /* center items vertically, in this case */
                align-items: center;
                /* center items horizontally, in this case */
                cursor: move;
            
            
            .print-this-only 
            
            @media print 
                html,
                body 
                    height: 100%;
                    overflow: hidden;
                    display: block;
                    background-color: yellow;
                
                #container 
                    display: block;
                
                .canvas_container 
                    max-width: 100%;
                    padding-bottom: 50%;
                    position: relative;
                
                canvas 
                    position: absolute;
                    left: 0;
                    top: 0;
                    right: 0;
                    bottom: 0;
                    width: 100%;
                
                .print-this-only 
                    background-color: yellow;
                    /*
            height: 100%;
    
            width: 100%;
            position: fixed;*/
                    top: 0;
                    left: 0;
                    margin: 0;
                
                .no-print,
                .no-print * 
                    display: none !important;
                
                .printOnly 
                    display: block;
                
            

        </style>

    </head>

    <body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">

        <div id="main-container">

            <header class="no-print">fixed height header
                <button onclick="window.print();" class="no-print">Print Canvas</button>
            </header>
            <section>
                <article id="id">
                    <div id="container">
                        <div id="container" class="print-this-only" style="position:relative">

                            <div class="canvas_container">
                                <canvas   id="canvas1"></canvas>
                            </div>

                            <img src="http://s.cdpn.io/3/kiwi.svg" style="
			position: absolute; 
			left: 0; 
			top: 0;
			z-index: 2;
			width: 5%;
		" />

                            <img src="http://s.cdpn.io/3/kiwi.svg" style="
			position: absolute; 
			left: 7%; 
			top: 0;
			z-index: 2;
			width: 5%;
		" />

                            <img src="http://s.cdpn.io/3/kiwi.svg" style="
			position: absolute; 
			left: 85%; 
			top: 15%;
			z-index: 2;
			width: 5%;
		" />


                        </div>
                </article>
                <nav class="no-print">


                    <div class="nav-item-top">
                        <div class="item-text">
                            sample
                        </div>
                        <div class="item-text">
                            sample this is a much longer sample text it goes on for a little bit here and there.
                        </div>

                        <div class="item-text">
                            this is the end of the line and the end of the universe.
                        </div>
                        <div ng-show=vm.showNav>Right</div>
                        <div ng-hide=vm.showNav>Left</div>


                    </div>
                    <div class="nav-bottom-container">
                        <div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
                        <div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>

                    </div>
                </nav>

            </section>
            </div>

            <script>
                var canvas = document.getElementById("canvas1");

                var ctx = canvas.getContext("2d");
                ctx.fillStyle = "blue";
                ctx.fillRect(0, 0, canvas.width, canvas.height);

            </script>
    </body>

</html>

【讨论】:

以上是关于如何以 100% 的页面宽度打印画布图像?的主要内容,如果未能解决你的问题,请参考以下文章

设置织物js画布的100%高度和宽度

水平滚动页面上 100% 宽度的图像

背景图像不会 100% 向右移动 [重复]

如何使图像自动调整大小,使宽度为 100% 并相应调整高度?

打印 css:适合一页

如何将图像从固定尺寸动画到全屏?