AoMao Editor (angular) 使用 window.print() 实现 html 导出 PDF 记录

news2024/12/1 0:40:04

目录

一、需求描述

二、使用 jspdf + html2canvas 导出遇到的问题

三、window.print() 导出具体实现 【api: toHtml】


一、需求描述

将 AoMao Editor 富文本插件中的内容导出为PDF。

二、使用 jspdf + html2canvas 导出遇到的问题

        试了很多插件,但 angular 能用的插件很少,网上比较多的方案是使用 html2canvas 截取内容后,再使用 jspdf 导出 PDF。

        这个方案的 优点 是:① 可以选定范围② 原样式输出,因为是以截图的方式导出,所以 amoao 文本引擎中渲染的样式也能导出(即页面展示什么,导出的PDF内容也是什么样);

        缺点 是:① 无法分页,因为 aomao 的内容是 h5 格式的,长度不定,且以截图方式截取,所以会存在一行文字被切开在两页上的情况(如图)

② 图片导出有问题,我用的 Chrome 浏览器,导出包含图片的文档内容时,图片会丢失,报错是跨域。但我图片服务器已经设置了跨域,查了半天还是报错,所以感觉是插件的问题。后面找到了一个改源码的帖子(html2canvas截图时 不能使用跨域图片的解决方案_node_modules中没有html2cannvas-CSDN博客),跟着改了源码,试了一下可以用,但就出现了下面的清晰度问题。【后面也试了一下其他浏览器,火狐浏览器不用改源码也可以导出图片,所以我也不清楚到底是哪里有问题】

③ 导出清晰度有问题,html2canvas 有一个参数 scale 设置缩放,默认是1,使用改了源码的 html2canvas 能导出所有图片,但导出的 PDF 会不清晰;当设置 scale = 2 时,导出的 PDF 变清晰了,但又出现了新的问题,文档中所有的图片不能都导出来(例如文档有 15张图,只能导出 10张,后面的就丢失了)

④ 导出的PDF无法复制,还是因为是截图的方式导出,所以导出的 PDF 内容无法复制。

三、window.print() 导出具体实现 【api: toHtml】

        找了半天,最终找到了一个使用 浏览器 原生方法导出 PDF 的方案: window.print()。

        这个方案的 优点 是:① 能分页,原本就是浏览器的打印方法,能分页应该很正常吧(如图)

② 图片导出没问题,因为是使用浏览器的加载方法,所以加载图片不存在跨域的问题,自然导出图片也没有问题。

        唯一的缺点是:无法指定范围,这个方法默认是导出当前页面的所有内容的,所以无法只导出页面中 aomao 文本插件的内容。

        但这个缺点是可以解决的!那就是把 aomao 文本插件的内容导出来,然后新建一个页面,把导出来的内容填充到新页面,再使用 window.print() 方法将新页面导出 PDF

实现如下:

public exportPdf() {
    const textContent = this.engine.model.toHTML();
    const pageStandard = ' <!DOCTYPE HTML><HTML><head><meta charset="UTF-8"><title>' + 
                          this.documentTitle + '</title></head>' + 
                          '<body><h1 style="padding: 0px 45px; margin-top: -10px;">' + this.documentTitle +'</h1>' +
                          '<div style="padding: 0px 55px;">' + textContent + '</div>' +
                          '</body></HTML>';
    let newWindow = window.open("", "_blank"); 
    newWindow.document.write(pageStandard); 
    newWindow.document.close(); 
    newWindow.print();
  }

代码解释:

① 使用 aomao 的 api toHTML 可以将文本插件的内容和样式导出来;

② 拼接一个基础的 html 页面,设置<title>,导出PDF的时候文件名默认就是设置的 title 名称;

③ window.open("", "_blank") 打开一个新页面,对原页面没有任何影响(网上有方案是在原页面上操作的,实测操作完会对原页面功能产生影响)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1165647.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NHANES | Roc曲线评估胰岛素抵抗替代物与育龄女性不孕症之间的关联

郑老师统计课程&#xff0c;欢迎点击报名&#xff1a;Nhanes公共数据库挖掘 课程 2023年10月12日&#xff0c;温州医科大学育英儿童医院附属第二医院妇产科学者在《BMC Public Health》&#xff08;三区&#xff0c;IF4.5&#xff09;发表题为&#xff1a;" Association b…

PXI-6608 185745H-02 PXI-6527 185633D-01

PXI-6608 185745H-02 PXI-6527 185633D-01 人工智能技术并不新鲜&#xff0c;但运行它的数据和计算却很新鲜 对于那些对人工智能技术历史感兴趣的人来说&#xff0c;一些今天正在使用的技术从20世纪50年代和60年代就已经存在了。 但是&#xff0c;如果人工智能已经存在了这么…

Linux学习第31天:Linux MISC 驱动实验:温故知新

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 学习是一个不断重复的过程。只有不断的使用、修正&#xff0c;才能越记越牢。将学习到的新的知识点应用到以往的项目经验中&#xff0c;才能不断提升自我&#x…

编译替换内核_设备树_驱动_IMX6ULL

前言&#xff1a; 使用的开发板为韦东山老师的 IMX6ULL 目录 为什么编译驱动程序之前要先编译内核&#xff1f; 1.驱动程序要用到内核文件&#xff1a; 2.编译驱动时用的内核、开发板上运行到内核&#xff0c;要一致&#xff1a; 3.更换板子上的内核后&#xff0c;板子上…

【使用Python编写游戏辅助工具】第五篇:打造交互式游戏工具界面:PySide6/PyQT高效构建GUI工具

前言 这里是【使用Python编写游戏辅助工具】的第五篇&#xff1a;打造交互式游戏工具界面&#xff1a;PySide6/PyQT高效构建GUI工具。本文主要介绍使用PySide6来实现构建GUI工具。 在前面&#xff0c;我们实现了两个实用的游戏辅助功能&#xff1a; 由键盘监听事件触发的鼠标连…

XSAN数据恢复-存储空间架构迁移时误格式化存储系统的XSAN数据恢复案例

XSAN数据恢复环境&#xff1a; 昆腾存储&#xff0c;MAC OS操作系统&#xff0c;存放视频类数据&#xff08;MXF、MOV等格式文件&#xff09;。 XSAN故障&检测&#xff1a; 将存储空间从XSAN架构迁移到STORNEXT架构后&#xff0c;存储空间中数据全部丢失。 故障存储中一共…

【3D图像分割】基于 Pytorch 的 VNet 3D 图像分割3(3D UNet 模型篇)

在本文中&#xff0c;主要是对3D UNet 进行一个学习和梳理。对于3D UNet 网上的资料和GitHub直接获取的代码很多&#xff0c;不需要自己从0开始。那么本文的目的是啥呢&#xff1f; 本文就是想拆解下其中的结构&#xff0c;看看对于一个3D的UNet&#xff0c;和2D的UNet&#x…

QCC TX 音频输入切换+提示声音

QCC TX 音频输入切换提示声音 QCC蓝牙芯片&#xff08;QCC3040 QCC3056 等等&#xff09;&#xff0c;AUX、I2S、USB输入 蓝牙音频输入&#xff0c;模拟输出是最常见的方式。 也可以再此基础上动态切换输入方式。 针对TX切换EQ,调节音量不能出提示声音问题&#xff0c;可以增…

Spring底层原理(五)

Spring底层原理(五) 本章内容 介绍Aware接口与InitializingBean接口、Bean的初始化与销毁、Scope Aware接口 作用:用于注入一些与容器相关的信息 类名作用BeanNameAware注入Bean的名称BeanFactoryAware注入BeanFactory容器ApplicationContextAware注入ApplicationContext容…

Pycharm 对容器中的 Python 程序断点远程调试

pycharm如何连接远程服务器的docker容器有两种方法&#xff1a; 第一种&#xff1a;pycharm通过ssh连接已在运行中的docker容器 第二种&#xff1a;pycharm连接docker镜像&#xff0c;pycharm运行代码再自动创建容器 本文是第一种方法的教程&#xff0c;第二种请点击以上的链接…

JavaScript中BOM与DOM

BOM window对象 所有的浏览器都支持window对象&#xff0c;他表示浏览器窗口&#xff0c; 所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。 全局变量是 window 对象的属性。全局函数是 window 对象的方法。 接下来要讲的HTML DOM 的 document 也是…

遥遥领先,免费开源的django4-vue3前后端分离项目

星域后台管理系统前端介绍 &#x1f33f;项目简介 本项目前端基于当下流行且常用的vue3作为主要技术栈进行开发&#xff0c;融合了typescript和element-plus-ui&#xff0c;提供暗黑模式和白昼模式两种主题以及全屏切换&#xff0c;开发bug少&#xff0c;简单易学&#xff0c…

攻略合集!游戏要领你一定要知道!

大家好&#xff01;作为游戏玩家&#xff0c;我们都希望在游戏中能够成为顶尖的高手。为了帮助大家更好地掌握游戏的要领&#xff0c;我要分享一些实用的攻略和技巧。 首先&#xff0c;不同游戏有不同的技巧和要领。对于《绝地求生》来说&#xff0c;我们需要注重观察和战略规划…

C++和 C 混合编程处理

原因是因为有很多功能是用 C 语言开发的&#xff0c;而 C是兼容 C 的&#xff0c;C应该能直接使用这些功能&#xff0c;那么我们把 C调用 C 实现的功能的这个做法&#xff0c;称为混合编程 但是用 C 开发的功能&#xff0c;很可能已经用 C 编译器编程成目标文件(或打包成库了)…

Zinx框架-游戏服务器开发001:zinx框架的安装

文章目录 1 zinx下载地址1.1 zinx框架的源码路径&#xff1a;1.2 安装好之后动态库的位置 2 Zinx框架运行的基本概况3 测试Zinx-框架的基本使用3.0 流程预览3.1 初始化框架3.2 标准输入回显标准输出的编写思路3.2.1 回显Echo3.2.2 写标准输入stdin通道类&#xff0c;用通道输入…

协同办公系统:企业提质增效的利器

随着科技的不断发展&#xff0c;企业对于提高工作效率、优化管理流程、降低成本的需求日益迫切。协同办公系统应运而生&#xff0c;成为了许多企业提质增效的利器。那么&#xff0c;协同办公系统究竟是如何帮助企业实现这些目标的呢&#xff1f;本文将从以下几个方面进行详细阐…

【基于MRA:自适应高频融合和注入系数优化:Pansharpening】

Pansharpening Based on Adaptive High-Frequency Fusion and Injection Coefficients Optimization &#xff08;基于自适应高频融合和注入系数优化的全色锐化&#xff09; 全色锐化的目的是将多光谱&#xff08;MS&#xff09;图像与全色&#xff08;PAN&#xff09;图像融…

【实战Flask API项目指南】之六 数据库集成 SQLAlchemy

实战Flask API项目指南之 数据库集成 本系列文章将带你深入探索实战Flask API项目指南&#xff0c;通过跟随小菜的学习之旅&#xff0c;你将逐步掌握 Flask 在实际项目中的应用。让我们一起踏上这个精彩的学习之旅吧&#xff01; 前言 在上一篇文章中&#xff0c;我们实现了…

私有化部署即时通讯软件WorkPlus,全面适配信创环境

对于企业而言&#xff0c;保护数据的安全至关重要。WorkPlus即时通讯软件允许企业在自己的服务器上部署一套私有化的聊天工具&#xff0c;确保数据完全受控于企业内部。通过私有化部署&#xff0c;企业可以有效地管理和保护敏感信息&#xff0c;防止数据泄露和滥用。 另外&…

React基础知识02

一、通过属性来传值&#xff08;props&#xff09; react中可以使用属性&#xff08;props&#xff09;可以传递给子组件&#xff0c;子组件可以使用这些属性值来控制其行为和呈现输出。 例子&#xff1a; // 1.1 父组件 import React, { useState } from react // 1.2引入子…