What is OFD

OFD (Open Fixed-Layout Documents) Is an electronic document with a highly accurate and Fixed layout effect, and its presentation is independent of devices.

Similar to PDF files, it has the characteristics of independent format, fixed layout and solidified presentation. It can be said that OFD is the Chinese version of PDF, but its performance is better than that of its counterpart in many aspects. OFD has gradually begun to be used in the fields of electronic invoices, electronic documents, electronic certificates and so on.

The country is promoting OFD format for office documents.

In short, OFD is customized by our country, while PDF is made by American company.

At present, OFD is mainly used in government agencies, which cannot directly open files and requires professional OFD readers.

Ofd. js to realize the ofD file preview function

Ofd.js is an open source project JavaScript toolkit on Gitee. Here, I would like to thank the author.

The author’s Gitee address is as follows:

Gitee.com/Donal/ofd.j…

The installation

npm i ofd.js
Copy the code

The introduction of

import {parseOfdDocument, renderOfd} from "ofd.js";
Copy the code

The core code

// The ofd file can be a local file, binary file or URL. ScreenWidth can be the width of the screen
parseOfdDocument({
  ofd: file,
  success(res) {
    // Output div of ofd per page
    const divs = renderOfd(screenWidth, res);
    // Obtain information about the signature div. See demo for details
    for(let ele of document.getElementsByName('seal_img_div')) {
       this.addEventOnSealDiv(ele, JSON.parse(ele.dataset.sesSignature), JSON.parse(ele.dataset.signedInfo)); }},fail(error) {
    console.log(error)
  }
});
Copy the code

OFD Component code

<template>
  <a-modal :title="title" :visible="visible" @cancel="handleCancel" width="70%" :footer="null">
    <a-spin :spinning="loading" tip="Loading">
      <div class="page-box">
        <div class="option-list" v-if="ofdObj">
          <div class="scale-icon" style="margin-left: 10px" @click="plus">
            <! - zoom - >
            <a-icon type="plus-circle" />
          </div>
          <div class="scale-icon" @click="minus">
            <! Narrow -- -- -- >
            <a-icon type="minus-circle" />
          </div>
          <div class="scale-icon">
            <! -- Page 1 -->
            <a-icon type="step-backward" @click="firstPage" />
          </div>
          <div class="scale-icon" @click="prePage">
            <! -- Previous page -->
            <a-icon type="caret-left" />
          </div>
          <div class="scale-icon">
            <! -- Current page number and total page number -->
            {{ pageIndex }}/{{ pageCount }}
          </div>
          <div class="scale-icon" @click="nextPage">
            <! -- Next page -->
            <a-icon type="caret-right" />
          </div>
          <div class="scale-icon" @click="lastPage">
            <! -- Last page -->
            <a-icon type="step-forward" />
          </div>
        </div>
      </div>
      <div class="modal-box" id="ofd-preview-box">
        <! -- File area -->
        <div class="main-section" :class="{ 'background-shadow': loadOverFlag }" id="content" ref="contentDiv"></div>
      </div>
    </a-spin>
  </a-modal>
</template><script>
import { parseOfdDocument, renderOfd, renderOfdByScale, getPageScale, setPageScale } from 'ofd.js'export default {
  name: 'OfdPreview'.components: {},
  props: {
    title: {
      type: String.default: 'OFD File Preview ',},fileUrl: {
      type: String.default: ' ',}},data() {
    return {
      ofdObj: null.pageIndex: 1.pageCount: 0.scale: 0.loading: false.visible: false.loadOverFlag: false.screenWidth: 1000,}},watch: {},
  computed: {},
  methods: {
    showModal() {
      this.visible = true
      this.$nextTick(() = > {
        this.screenWidth = document.getElementById('ofd-preview-box').getBoundingClientRect().width - 30
        this.getOfdDocumentObj(this.fileUrl, this.screenWidth)
      })
    },
    handleCancel(e) {
      this.visible = false
    },
    getOfdDocumentObj(file, screenWidth) {
      let that = this
      this.loading = true
      parseOfdDocument({
        ofd: file,
        success(res) {
          that.ofdObj = res[0]
          that.pageCount = res[0].pages.length
          const divs = renderOfd(screenWidth, res[0])
          that.displayOfdDiv(divs)
          that.loadOverFlag = true
          that.loading = false
        },
        fail(error) {
          that.loading = false
          console.log('OFD failed to open ')}})},displayOfdDiv(divs) {
      this.scale = getPageScale()
      let contentDiv = document.getElementById('content')
      contentDiv.innerHTML = ' '
      for (const div of divs) {
        contentDiv.appendChild(div)
      }
    },
    plus() {
      setPageScale(++this.scale)
      const divs = renderOfdByScale(this.ofdObj)
      this.displayOfdDiv(divs)
    },
​
    minus() {
      setPageScale(--this.scale)
      const divs = renderOfdByScale(this.ofdObj)
      this.displayOfdDiv(divs)
    },
​
    prePage() {
      let contentDiv = document.getElementById('content')
      let ele = contentDiv.children.item(this.pageIndex - 2)
      if (ele) {
        ele.scrollIntoView(true)
        this.pageIndex = this.pageIndex - 1}},firstPage() {
      let contentDiv = document.getElementById('content')
      let ele = contentDiv.firstElementChild
      if (ele) {
        ele.scrollIntoView(true)
        this.pageIndex = 1}},nextPage() {
      let contentDiv = document.getElementById('content')
      let ele = contentDiv.children.item(this.pageIndex)
      if (ele) {
        ele.scrollIntoView(true) + +this.pageIndex
      }
    },
​
    lastPage() {
      let contentDiv = document.getElementById('content')
      let ele = contentDiv.lastElementChild
      if (ele) {
        ele.scrollIntoView(true)
        this.pageIndex = contentDiv.childElementCount
      }
    },
  },
  created() {},
  mounted(){},}</script>
<style lang="scss" scoped>
.wrapper{}.modal-box {
  width: 100%;
  height: 55vh;
  overflow: auto;
}
.main-section {
  width: 100%;
  padding-top: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  position: relative;
}
​
.background-shadow {
  background: # 808080;
}
​
.page-box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 50px;
  margin-bottom: 15px;
  .option-list {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%; }}.scale-icon {
  display: flex;
  cursor: pointer;
  justify-content: center;
  align-items: center;
  width: 33px;
  height: 28px;
  border-radius: 1px;
  font-weight: 500;
  font-size: 18px;
  color: # 333333;
  text-align: center;
  padding: 2px;
}
​
.scale-icon :hover {
  color: #1890ff;
}
​
.ant-spin-nested-loading > div > .ant-spin {
  max-height: auto ! important;
}
</style>
Copy the code