canvas 3D渲染时遇到的问题

lxf2023-12-22 00:00:01

因为最后渲染页面属于自己的定做的,因此这里根据直接引用 pdfjs-dist中的软件,只解决canvas 3D渲染一部分,其它功能在这个基础上自主订制,下边遇到的困难也就是在应用软件开展 canvas 3D渲染时遇到的问题

1、工程项目连接 pdfjs 的时候在安卓系统60版本号下3D渲染不成功,并出错

因为 pdfjs-dist 中词法较高,如带有 ||= 等高端词法,因此在使用过程中,需要大量的给pdfjs-dist开展 babel 再编译程序。

在webpack 里的rule下新增加下列一部分,应注意应用"@babel/preset-env"的时候需要设定 modulescommonjs,不然默认设置 auto的现象编译程序出来的编码是不能直接所使用的

{
  test: /.m?js$/,
  include: [
    path.resolve("node_modules/pdfjs-dist/"),
  ],
  use: {
    loader: "babel-loader",
    options: {
      presets: [
        [
          require("@babel/preset-env"),
          {
            modules: "commonjs"
          }
        ]
      ],
      plugins: ["@babel/plugin-transform-runtime"]
    }
  }
},

2、node条件下一部分型号应用 pdfjs 时没法3D渲染,如洪蒙 p30

认证的时候发现使用中提醒

structuredClone is not defined

发觉 structuredClone 的兼容模式很差,不知为什么上边配备的 babel 降权怎么没把这个词法给下降。

查询 github 官方网 issue ,发觉的确有这种情况,在使用过程中应用 pdfjs-dist/legacy/build下边相对应的文档就可以处理,官方文档里也有相对应的表明。

然后我就沉默了一下,发现这目录下可以解决兼容性问题,那样 难题1 是否也能通过这一问题改进,随后证明了一下,发觉真不可以,有一些词法仍然需要做 babel 解决,如 Private class fields等高端词法依然在该版本号软件下应用

3、node条件下应用 pdf.worker.js,无出错,亦无3D渲染

因为在 node 条件下可以将 pdf.worker.js 设为 pdfjsGlobalWorkerOptions.workerSrc 没法起效,因此这里要应用 pdf.worker.entry.js做为 workerSrc,相匹配 issue

这里留意采用的是 legacy中的或是 build中的需要和 pdfjs 提及的保持一致

4、容积难题

直接用软件时体积大,充分考虑应用min版本号时,pdf.work.entry 并没有相对应的min版本号,查看源码如下所示:

(typeof window !== "undefined"
  ? window
  : {}
).pdfjsWorker = require("./pdf.worker.js");

那我使用中是不是立即按上述方法调节,来减少 worker 的相对应的容积呢,现象能,整理资料发觉,重量的增加量基本上就在那 worker 体积上展现了

const pdfjsLib = require("pdfjs-dist/legacy/build/pdf.min.js");
pdfjsLib.GlobalWorkerOptions.workerSrc = (typeof window !== "undefined"
  ? window
  : {}
).pdfjsWorker = require("pdfjs-dist/legacy/build/pdf.worker.min.js");
原工程项目1119k
连接build版本3538k 2419k
连接 legacy 版本号4035k 3916k
worker min 版本号worker 非 min 版本号
连接build min 版本号2450k 1331k3657k 2538k
连接 legacy min 版本号2793k 1674k3735k 3616k

依据工程项目的兼容模式和容积要求,现阶段尝试使用 连接 legacy 的 min 版本号且 worker min 版本号

5、跨域问题

当 pdfjs 载入远程控制pdf时,免不了会有 CORS 跨域请求问题,3种解决方法,关键也是通过下载文件之后再浏览去解决

1、将 pdf 下载到当地,放进施工中开展当地引入,该方式不但提升工程项目容积,还没灵便

2、将 pdf 下载到静态资源服务器上,在施工中浏览静态资源网络服务器里的数据进行完成,该方式必须手动控制,较为低效能

3、根据启用网络服务器插口由服务器进行资源分享,待下载完了后通过网络服务器给予相对应的资源 ArrayBuffer 开展浏览,该方式非常灵活

根据我们工程项目的现况, 选了第三种方法

附则

实际上仿佛绝大多数难题都能在官方网表明中找到,只不过是遇到的困难可能会在文档里没说那样细,但细搜索下 issue 也是可以寻找相匹配解决方案

下边简单写个应用的事例吧

const pdfjsLib = require("pdfjs-dist/legacy/build/pdf.min.js");
pdfjsLib.GlobalWorkerOptions.workerSrc = (typeof window !== "undefined"
  ? window
  : {}
).pdfjsWorker = require("pdfjs-dist/legacy/build/pdf.worker.min.js");

function init(data) {
  // data能够为url,还可以为服务器端返回 arrayBuffer 或服务器端返回 base64,前面转 arrayBuffer
  try {
    const loadingTask = pdfjsLib.getDocument(data);
    this.pdf = await loadingTask.promise;
    this.pageNum = await this.pdf.numPages || 0;
    console.log('pageNum', this.pageNum)
    this.initCanvas();
    this.renderPdf(1);
  } catch (err) {
    this.onError({
      message: "pdf 文档加载失败",
      code: 1
    })
  }
}

function renderPdf(num = 1) {
    this.pdf.getPage(num).then((page) => {
      // 设定canvas有关的特性
      const canvas = document.getElementById("pdfCanvas_"   num);
      const ctx = canvas.getContext("2d", {
        alpha: false
      });
      const dpr = window.devicePixelRatio || 1;
      const bsr =
        ctx.webkitBackingStorePixelRatio ||
        ctx.mozBackingStorePixelRatio ||
        ctx.msBackingStorePixelRatio ||
        ctx.oBackingStorePixelRatio ||
        ctx.backingStorePixelRatio ||
        1;
      const ratio = dpr / bsr;
      const viewport = page.getViewport({ scale: this.pdfScale * ratio }); // 设定放大比例
      const viewRatio = viewport.height / viewport.width;
      canvas.width = viewport.width * ratio;
      canvas.height = viewport.height * ratio;
      canvas.style.width = (this.container.clientWidth - 20) * this.pdfScale   "px";
      canvas.style.height = (this.container.clientWidth - 20) * viewRatio * this.pdfScale   "px";
      ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
      const renderContext = {
        canvasContext: ctx,
        viewport: viewport
      };
      // 数据渲染到canvas画板上
      page.render(renderContext);
      if (this.pageNum > num) {
        setTimeout(() => {
          return this.renderPdf(num   1);
        });
      }
    });
  }
本站是一个以CSS、JavaScript、Vue、HTML为中心的前端开发技术网址。我们的使命是为众多前端工程师者提供全方位、全方位、好用的前端工程师专业知识和技术服务。 在网站上,大家可以学到最新前端开发技术,掌握前端工程师最新发布的趋势和良好实践。大家提供大量实例教程和实例,让大家可以快速上手前端工程师的关键技术和程序。 本站还提供了一系列好用的工具软件,帮助你更高效地开展前端工程师工作中。公司提供的一种手段和软件都要经过精心策划和改进,能够帮助你节约时间精力,提高研发效率。 此外,本站还拥有一个有活力的小区,你可以在社区里与其它前端工程师者沟通交流技术性、交流经验、处理问题。我们坚信,街道的能量能够帮助你能够更好地进步与成长。 在网站上,大家可以寻找你需要的一切前端工程师网络资源,使您成为一名更加出色的网页开发者。欢迎你添加我们的大家庭,一起探索前端工程师的无限潜能!