javascript - 如何以 100% 页面宽度打印 Canvas 图像?

标签 javascript css html canvas

我的元素需要打印出可以小于或大于页面宽度的 Canvas 图像。我希望打印输出在 Canvas 图像小于页面宽度时保持 Canvas 大小,在 Canvas 图像大于页面宽度时保持比例。我该如何实现这个目标?

以下是 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%;
    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 height="1000px" width="2000px" 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>

以下是 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%;
    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 height="400px" width="400px" 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>

最佳答案

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

<div class="canvas_container">
    <canvas height="1000px" width="2000px" 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 height="1000px" width="2000px" 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>

关于javascript - 如何以 100% 页面宽度打印 Canvas 图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46104406/

相关文章:

html - 当背景颜色应用于父元素时,CSS 开关输入文本不可见

javascript - 如何根据输入字段的值隐藏此表行 4 级以下

css - 如何测试CSS方向: auto as an english speaker

html - 段落中的不透明度变化会改变文本不透明度和背景不透明度

javascript - javascript mixins 中的构造函数和类属性

javascript - 如何在 Google Apps 脚本中访问 HTML 文件的脚本部分中的模板变量?

c# - 在运行时创建一组两个 Div

javascript - 获取 JavaScript 中元素的每个子元素的每个子元素

javascript - .val().trigger ('change' ) 实际上在做什么?

javascript - 字符数组未正确获取值