HTML实现A4模板

前言

需要使用html实现打印前预览的界面,要求预览结果与打印效果相同
使用环境: bootstrapVue


一、A4模板效果

附实现效果(demo)
实现demo
应用流程为点击界面的预览按钮,弹出窗口为制作的A4界面。


二、制作A4模板

1.思考界面结构(以所附demo[A4.html]分析)

  • 模板分为头部,中间内容,底部footer三块内容(除去大标题),使用flex布局实现整个界面,因为中间的内容是不固定的,所以让它占据空间的最大内容,使用flex-grow:1占据空间,从而使布局分为上中下三块。
    代码结构如下(示例):
    	<!--代码实例中的css定义直接用的bootstrap的公共样式方便代码编写,观看直接,实际html不能直接用类名的,需要另外编写css-->
    	<div class="root d-flex flex-column">
    		<div class="header"></div>
    		<div class="content flex-grow-1"></div>
    		<div class="footer"></div>
    	</div>					
    

2. 限制页面大小

  • 需要将页面的大小限制在A4大小,因为用于打印,所以单位使用了mm,A4大小的宽高为(210mm,297mm)
    	/*这是将打印时的页面大小设置为A4大小,并保留好一定的边距*/
    	@page {
    	  /* size: 21cm 29.7cm; */
    	  font-size: 14pt;
    	  font-family: SimSun, 宋体, serif;
    	  color:black;
    	  line-height: 1.4;
    	  text-align: justify;
    	  margin:0;
    	  padding:0;
    	}
    
    	body{
    	  font-size: 14pt;  /*在打印中,字体大小使用pt单位*/
    	  font-family: "Times New Roman", Times, serif;
    	}
    	.root{
    	  /*需要将预览显示的界面限定在A4大小*/
    	  width:210mm;
    	  /*这个高度为什么不是A4的大小,是经过N次验证的方式得到的,唯一的目的就是为了保证预览和打印预览一致*/
    	  /*可能是我写的有一点问题,但是如果设置为297,那么显示就会出现问题*/
    	  height:340mm;
    	  /*上下不要设置padding,否则打印预览下面的footer就会往上走*/   
    	  padding: 0 24mm 0 24mm;
    	  /* margin-bottom: 24mm; */
    	  background-color: white;
    	}
    	/*下面两个样式是为了保证屏幕上预览和打印预览一致*/
    	@media screen{
    	  .content{
    	    width:210mm;
    	    height:340mm;
    	    /* padding-top:12mm; */
    	    display: flex;
    	    flex-direction: column;
    	  }
    	}
    	@media print{
    	  .content{
    	    width:210mm;
    	    height:340mm;
    	    padding-top:18mm;
    	    display: flex;
    	    flex-direction: column;
    	  }
    	}
    
  • 之后通过flex布局模式将内容排好版之后可使用浏览器打印功能预览打印结果,如果有打印部分有与html结构不同的地方,可能是因为浏览器的打印预设,可使用下面的方法自己设定样式
    	/*第一种*/
    	@media print{
    	/*这个方法用在需要编写的样式不是太多的情况下*/
    		.root{
    			/*这里面写需要的样式,这里的样式只在打印时才会用到*/
    		}
    	}
    	/*第二种*/
    	/*可单独编写一个文件专门用于打印的样式,如果需要编写的样式很多的情况下*/
    	1. 新建print.css
    	2. 引入文件
    		<link rel="stylesheet" href="../src/css/screen.css" media="screen">
      		<link rel="stylesheet" href="../src/css/print.css" media="print">
    

三、预览功能

点击预览 --> 弹出界面(界面居中),模板大小随着屏幕自适应,全部出现在界面上而不滚动 --> 点击下面的按钮关闭预览

  • 设置iframe,嵌入写好的模板

    代码结构如下(show.vue):

    html部分
    <!--通过变量值判断应该用什么样式-->
    <div
      :class="{
        'template-wrapper-show': isTemplateShow,
        'template-wrapper-hidden': !isTemplateShow
      }"
      class="text-center"
      id="template-wrapper"
    >
      <div
        class="d-flex flex-column justify-content-center align-items-center w-100 h-100"
      >
        <div id="iframe-wrapper" :style="iframeSize">
          <iframe
            src="./A4.html"
            frameborder="0"
            id="iframeId"
            :style="iframeStyle"
            name="iframeId"
            scrolling="no"
            class="iframe-content"
          >
            <p>您的浏览器不支持 iframe 标签。</p>
          </iframe>
        </div>
        <!--关闭按钮-->
        <div class="">
          <b-button
            variant="outline"
            size="lg"
            @click="
              () => {
                this.isTemplateShow = false;
              }
            "
          >
            <b-icon icon="x-circle" variant="white"></b-icon>
          </b-button>
        </div>
      </div>
    </div>
    
    
    

    通过样式变化来确定是否显示iframe(原本打算将iframe放在modal中,以此来控制显示,但是modal获取不到iframe的宽高,所以在控制高度方面不是很方便,因此使用原生的样式来写),控制的css如下:

    	.template-wrapper-hidden {
    		  /*设置absolute使得 visibility:hidden时不占据空间*/
    		  /* position: absolute; */
    		  /* visibility: hidden; */
    		  overflow: hidden;
    		  display: none;   /*到最后发现还是这个最好使*/
    	}
    	.template-wrapper-show {
    		/*设置一个遮罩层,占满屏幕*/
    		  position: fixed;
    		  top: 0;
    		  left: 0;
    		  right: 0;
    		  bottom: 0;
    		  background: rgba(0, 0, 0, 0.3);
    		/*让遮罩层位于屏幕的最上方*/
    		  z-index: 1000;
    	}
    	.iframe-content {
    		/*只为了能完全显示那个html界面*/
    		  width: 260mm;
    		  height: 360mm;
    		  transform-origin: left top;
    		  overflow: hidden;
    	}
    
  • 实现缩放(实现难点)

    1. 在页面加载的时候,需要获取到屏幕的大小,从而按比例缩小模板大小以整个显示在屏幕上
    2. 为了实现打印,模板的单位使用的是mm单位,而屏幕显示使用的是px单位,因此在计算时需要转换单位,计算的比例才有效
    3. 最后决定缩放的大小需要进行判断,因为要适配各个屏幕的大小。
    • 实现
    	// 1. 获取屏幕大小,在页面加载时调用获取屏幕的方法
    	//获取DPI
        js_getDPI() {
          var arrDPI = new Array();
          if (window.screen.deviceXDPI != undefined) {
            arrDPI[0] = window.screen.deviceXDPI;
            arrDPI[1] = window.screen.deviceYDPI;
          } else {
            var tmpNode = document.createElement("DIV");
            tmpNode.style.cssText =
              "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
            document.body.appendChild(tmpNode);
            arrDPI[0] = parseInt(tmpNode.offsetWidth);
            arrDPI[1] = parseInt(tmpNode.offsetHeight);
            tmpNode.parentNode.removeChild(tmpNode);
          }
          return arrDPI;
        },
        //方法来源于网络,用的现成的
    
    // 2. 转换单位
    	js_convertMm() {
          const dpiArray = this.js_getDPI();
          let templateArray = [];
          //转换的原理可以百度一下, 260和360是设置的div宽高
          let px = (260 * dpiArray[0]) / 25.4;
          let py = (360 * dpiArray[1]) / 25.4;
          templateArray[0] = px;
          templateArray[1] = py;
          return templateArray;
        },
    
    // 3. 计算缩放比
    	populateIframeScale() {
          const winWidth = window.innerWidth - 50;
          const winHeight = window.innerHeight - 50;
          let templateSize = this.js_convertMm();
          const widthScale = Number((winWidth / templateSize[0]).toFixed(2));
          const heightScale = Number((winHeight / templateSize[1]).toFixed(2));
          if (
            (widthScale <= 0.85 || heightScale <= 0.85) &&
            widthScale <= heightScale
          ) {
            return widthScale;
          } else if (
            (widthScale <= 0.85 || heightScale <= 0.85) &&
            widthScale > heightScale
          ) {
            return heightScale;
           //如果计算得到的比例大于0.85,则按0.85的缩放比显示,因为预览的下面还有关闭按钮,需要预留一定的空间
          } else if (widthScale > 0.85 && heightScale > 0.85) {
            return 0.85;
          }
          return 1;
        },
    	
    	//使用计算属性将计算出的缩放比例运用到iframe的样式上
    	conputed(){
    		iframeStyle() {
    	      let scale = this.populateIframeScale();
    	      return { transform: "scale(" + scale + ")" };
    	    }
    	}
    

四、实现打印

  • 实现打印就比较简单,使用js的方法就可以,记录一下
    	printTemplate() {
          //第一种打印;
          // let f = document.getElementById("iframeId");
          // f.contentWindow.focus();
          // f.contentWindow.print();
          //第二种打印;
          window.frames["iframeId"].focus();
          window.frames["iframeId"].print();
        },
    

五、 实现效果

  • 大屏显示预览
    在这里插入图片描述
  • 中屏显示效果
    在这里插入图片描述
  • 手机显示
    在这里插入图片描述
  • 横屏
    在这里插入图片描述

总结

  1. 记录了印象比较深的一些步骤点,可能有还有一些琐碎的点没有记录,如果有想到再来补充。
  2. 为保证预览和打印预览一致,对于高度的调节是比较麻烦的,如果设置的不好,则底下的footer后就会有一大段留白。
  • 6
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值