window.print网页打印——打印htmlbody的实际高度,而不是看到的内容

Posted 胖鹅68

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了window.print网页打印——打印htmlbody的实际高度,而不是看到的内容相关的知识,希望对你有一定的参考价值。

文章目录

文章参考

  1. 原生js获取元素样式的简单方法

问题描述

  1. 工作中,想把网页中某段内容保存图片
  2. 想保存的这部分内容在网页中的某个div中,并且出现了滚动条,(不是窗口出现滚动条,是某个div有滚动条)
  3. 第一想法是使用chrome的保存图片的命令功能 —— 保存全屏、某个节点、当前可视区域三个功能,但是测试没有成功(这个功能只是针对显示在html节点的内容,因为节点高度固定,所以保存的图片就是我们看到的部分)
  4. 想到“网页打印功能”,将打印的内容保存为Pdf,还方便查找

使用chrome保存图片功能——验证问题3

测试代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div style="height: 200px;width: 200px;overflow: auto;">
    <div>dddddddd</div>
    <div>dddddddd</div>
    <div>此处省略一万行代码</div>
  </div>
</body>
</html>

测试结果

保存固定高度节点为图片的内容,如图

测试结论

这个功能只是针对显示在html节点的内容,因为节点高度固定,所以保存的图片就是我们看到的部分

使用浏览器打印功能为pdf

打印的API

  1. window.print()
  2. document.execCommand('print')

上面两种API 作用是一样的

通用JS代码——将网页总具体的某段保存为pdf

(function dayin(queryStr) 
    var userAgent = navigator.userAgent.toLowerCase() // 取得浏览器的userAgent字符串
    if (userAgent.indexOf('trident') > -1) 
      alert('请使用google或者360浏览器打印')
      return false
     else if (userAgent.indexOf('msie') > -1) 
      alert('请使用google或者360浏览器打印')
      return false
     else 
      // 其它浏览器使用lodop
      // var oldstr = window.document.body.outerHTML
      var printData = window.document.querySelector(queryStr).outerHTML // 获得 div 里的所有 html 数据,因为只有样式没有事件
      // window.document.body.innerHTML = printData
      const htmlObj = window.document.getElementsByTagName('html')[0]
      const bodyObj = window.document.getElementsByTagName('body')[0]
      // 缓存body、html的高度
      const beforeBodyHeightStyle = getComputedStyle(bodyObj).height
      const beforeHtmlHeightStyle = getComputedStyle(htmlObj).height
      // 缓存body、html是否隐藏起来了
      const beforeBodyOverflowStyle = getComputedStyle(bodyObj).overflow
      const beforeHtmlOverflowStyle = getComputedStyle(htmlObj).overflow
      console.log(beforeBodyOverflowStyle)
      // 防止 html 和 Body都设置了高度为100%,因为实际要打印的高度是所有内容,大于浏览器的高度100%的,而我们查看的内容和显示的内容都是浏览器的高度,并且有滚动条,这样就让我们有错觉,
      // 我们打印的内容是html的高度的内容,不是100%,有可能是小于100%,也可能大于100%的
      htmlObj.style.height = 'auto'
      bodyObj.style.height = 'auto'
      // 判断body是否隐藏不显示滚动条
      if (beforeBodyOverflowStyle === 'hidden') 
        bodyObj.style.overflow = 'auto'
      
      if (beforeHtmlOverflowStyle === 'hidden') 
        htmlObj.style.overflow = 'auto'
      

      //
      var targetDiv = document.createElement('div')
      const targetId = Math.floor(Math.random() * 10000000000000000)
      targetDiv.id = targetId
      targetDiv.innerHTML = printData // 将 HTML 代码作为字符串重新拷贝到 创建的div 中
      // document.getElementById('app').style.display = 'none'

      var docfrag = document.createDocumentFragment() // 创建一个fragment 对象
      // 将 body 下面的所有非 link 和 script 标签的全部都移动到 创建的 fragment 对象中
      for (let i = 0; i < bodyObj.childNodes.length; i++) 
        var node = bodyObj.childNodes[i]
        // 过滤 text 节点、script 节点
        if (
          node.nodeType === 1 &&
          node.nodeName !== 'LINK' &&
          node.nodeName !== 'SCRIPT'
        ) 
          console.log(node.nodeName)
          // 如果参数节点是 DOM 已经存在的节点,appendChild方法会将其从原来的位置,移动到新位置。
          docfrag.appendChild(node)
        
      
      bodyObj.append(targetDiv)
      // window.print()
      // 等价于
      window.document.execCommand('print')
      htmlObj.style.height = beforeHtmlHeightStyle
      bodyObj.style.height = beforeBodyHeightStyle
      if (beforeBodyOverflowStyle === 'hidden') 
        bodyObj.style.overflow = 'hidden'
      
      if (beforeHtmlOverflowStyle === 'hidden') 
        htmlObj.style.overflow = 'hidden'
      
      // 打印结束后,放开隐藏内容
      targetDiv.remove()
      var children = docfrag.childNodes // NodeList 接口
      console.log(children instanceof NodeList)
      children.forEach((node, i, list) => 
        console.log(node, i, list)
      )
      bodyObj.appendChild(docfrag)
    
  )("article.article");

打印的思路

  1. 将节点的代码缓存起来
  2. 将body内部的 非 LINK 和 非SCRIPT 节点 缓存起来,放到 新建的 fragment 节点中
  3. 将需要打印的代码创建为 一个DIV 节点,挂在 body 节点下面
  4. 检测是否固定了html和body的高度
  5. 检测是否将html和body设置了overflow:hidden
  6. 打印完成或者取消打印,将创建的打印节点删除,然后将新建的fragment 下的节点重新返回挂载到 body 节点下面

天坑——为什么我打印的时候只显示当前页

上面的代码我做了注释,再重复说明一下,下面的情况是我遇到的一种情况,具体情况具体分析

  1. 防止 html 和 Body都设置了高度为100%,因为实际要打印的高度是所有内容,大于浏览器的高度100%的,
  2. 而我们查看的内容和显示的内容都是浏览器的高度,并且有滚动条,这样就让我们有错觉,
  3. 结论:
    我们打印的内容是html的实际高度的内容,不是100%,有可能是小于100%,也可能大于100%的

样式在class中,如何获取DOM的样式?

问题描述:
在学习DOM的时候就看到通过ele.style来获取元素样式值,但是有时候获取的并非是节点的样式值,而是空值。

ele.style

a. 这是因为ele.style只能获取写在元素标签中的style属性里的样式值,
b. 无法获取到定义在<style></style>和通过<link href="css.css">加载进来的样式属性

var test = document.getElementById("test");
//获取节点的color
test.style.color;

getComputedStyle()

getComputedStyle是一个可以获取当前元素所有最终使用的CSS属性值。
window.getComputedStyle("元素", "伪类");

以上是关于window.print网页打印——打印htmlbody的实际高度,而不是看到的内容的主要内容,如果未能解决你的问题,请参考以下文章

网页打印问题:IE中window.print();打印图片预览时图片内容没有铺满纸张,使打印的效果总是很小???

ASP.Net怎么实现从网页上打印

网页打印

php部分:网页中报表的打印

打印网页中指定内容

react + antd 实现打印功能(踩了不少坑)