Jelajahi Sumber

update: Form外观改为图片显示

wzl 1 bulan lalu
induk
melakukan
49832dcff2

+ 3 - 0
packages/core/src/TextSelection.ts

@@ -209,11 +209,14 @@ export default class TextSelection {
   }
 
   async handleMouseMove(event: MouseEvent) {
+    if (this.isTargetInElement(event.target, '.redaction-confirm-dialog') || this.isTargetInElement(event.target, '.mask')) return
+
     const inPage = this.testPoint(event)
     if (!inPage || document.querySelector('.annotationContainer .outline-container')) {
       this.container?.classList.remove('text')
       return
     }
+
     const { x, y } = inPage
     const point = getInitialPoint({ x, y }, this.viewport, this.scale)
     const isText = await this.isTextAtPoint(point)

+ 29 - 14
packages/core/src/annotation/layer.js

@@ -64,6 +64,7 @@ class ComPDFAnnotationLayer {
     this.addMode = false
     this.toolMode = pageViewer.toolMode || ''
     this.managerArray = ['freetextManager', 'textManager', 'textFieldManager', 'checkBoxManager', 'radioButtonManager', 'pushButtonManager', 'listBoxManager', 'comboBoxManager', 'annotateManager', 'linkManager', 'signFieldManager', 'redactionManager']
+    this.ratio = window.devicePixelRatio || 1
 
     this.annotationStore = annotationStore
 
@@ -500,7 +501,8 @@ class ComPDFAnnotationLayer {
             scale: this.scale,
             eventBus: this.eventBus,
             layer: this,
-            highlight: this.annotationStore.highlightForm
+            highlight: this.annotationStore.highlightForm,
+            messageHandler: this.messageHandler
           })
           this.annotationsArray.push(textfield)
         }
@@ -513,7 +515,8 @@ class ComPDFAnnotationLayer {
             scale: this.scale,
             eventBus: this.eventBus,
             layer: this,
-            highlight: this.annotationStore.highlightForm
+            highlight: this.annotationStore.highlightForm,
+            messageHandler: this.messageHandler
           })
           this.annotationsArray.push(checkbox)
         }
@@ -526,7 +529,8 @@ class ComPDFAnnotationLayer {
             scale: this.scale,
             eventBus: this.eventBus,
             layer: this,
-            highlight: this.annotationStore.highlightForm
+            highlight: this.annotationStore.highlightForm,
+            messageHandler: this.messageHandler
           })
           this.annotationsArray.push(radiobutton)
         }
@@ -539,7 +543,8 @@ class ComPDFAnnotationLayer {
             scale: this.scale,
             eventBus: this.eventBus,
             layer: this,
-            highlight: this.annotationStore.highlightForm
+            highlight: this.annotationStore.highlightForm,
+            messageHandler: this.messageHandler
           })
           this.annotationsArray.push(pushbutton)
         }
@@ -552,7 +557,8 @@ class ComPDFAnnotationLayer {
             scale: this.scale,
             eventBus: this.eventBus,
             layer: this,
-            highlight: this.annotationStore.highlightForm
+            highlight: this.annotationStore.highlightForm,
+            messageHandler: this.messageHandler
           })
           this.annotationsArray.push(listbox)
         }
@@ -565,7 +571,8 @@ class ComPDFAnnotationLayer {
             scale: this.scale,
             eventBus: this.eventBus,
             layer: this,
-            highlight: this.annotationStore.highlightForm
+            highlight: this.annotationStore.highlightForm,
+            messageHandler: this.messageHandler
           })
           this.annotationsArray.push(combobox)
         }
@@ -578,7 +585,8 @@ class ComPDFAnnotationLayer {
             scale: this.scale,
             eventBus: this.eventBus,
             layer: this,
-            highlight: this.annotationStore.highlightLink
+            highlight: this.annotationStore.highlightLink,
+            messageHandler: this.messageHandler
           })
           this.annotationsArray.push(link)
         }
@@ -797,7 +805,8 @@ class ComPDFAnnotationLayer {
         scale: this.scale,
         eventBus: this.eventBus,
         layer: this,
-        highlight: this.highlightForm
+        highlight: this.highlightForm,
+        messageHandler: this.messageHandler
       })
       this.annotationsArray.push(textfield)
     } else if (annotation.type === 'checkbox' && !annotation.isDelete) {
@@ -809,7 +818,8 @@ class ComPDFAnnotationLayer {
         scale: this.scale,
         eventBus: this.eventBus,
         layer: this,
-        highlight: this.annotationStore.highlightForm
+        highlight: this.annotationStore.highlightForm,
+        messageHandler: this.messageHandler
       })
       this.annotationsArray.push(checkbox)
     } else if (annotation.type === 'radiobutton' && !annotation.isDelete) {
@@ -821,7 +831,8 @@ class ComPDFAnnotationLayer {
         scale: this.scale,
         eventBus: this.eventBus,
         layer: this,
-        highlight: this.annotationStore.highlightForm
+        highlight: this.annotationStore.highlightForm,
+        messageHandler: this.messageHandler
       })
       this.annotationsArray.push(radiobutton)
     } else if (annotation.type === 'pushbutton' && !annotation.isDelete) {
@@ -834,7 +845,8 @@ class ComPDFAnnotationLayer {
         eventBus: this.eventBus,
         layer: this,
         show,
-        highlight: this.annotationStore.highlightForm
+        highlight: this.annotationStore.highlightForm,
+        messageHandler: this.messageHandler
       })
       this.annotationsArray.push(pushbutton)
     } else if (annotation.type === 'listbox' && !annotation.isDelete) {
@@ -847,7 +859,8 @@ class ComPDFAnnotationLayer {
         eventBus: this.eventBus,
         layer: this,
         show,
-        highlight: this.annotationStore.highlightForm
+        highlight: this.annotationStore.highlightForm,
+        messageHandler: this.messageHandler
       })
       this.annotationsArray.push(listbox)
     } else if (annotation.type === 'combobox' && !annotation.isDelete) {
@@ -860,7 +873,8 @@ class ComPDFAnnotationLayer {
         eventBus: this.eventBus,
         layer: this,
         show,
-        highlight: this.annotationStore.highlightForm
+        highlight: this.annotationStore.highlightForm,
+        messageHandler: this.messageHandler
       })
       this.annotationsArray.push(combobox)
     } else if (annotation.type === 'link' && !annotation.isDelete) {
@@ -873,7 +887,8 @@ class ComPDFAnnotationLayer {
         eventBus: this.eventBus,
         layer: this,
         show,
-        highlight: this.annotationStore.highlightLink
+        highlight: this.annotationStore.highlightLink,
+        messageHandler: this.messageHandler
       })
       this.annotationsArray.push(link)
     } else if (annotation.type === 'signatureFields' && !annotation.isDelete) {

+ 70 - 8
packages/core/src/form/check_box.js

@@ -13,7 +13,8 @@ export default class CheckBox extends Base {
     eventBus,
     layer,
     show = false,
-    highlight
+    highlight,
+    messageHandler
   }) {
     super({
       container,
@@ -27,6 +28,7 @@ export default class CheckBox extends Base {
     })
 
     this.layer = layer
+    this.messageHandler = messageHandler
     this.hidden = true
     this.initial = false
     this.outline = null
@@ -54,7 +56,7 @@ export default class CheckBox extends Base {
     this.render()
   }
 
-  render () {
+  async render () {
     this.eventBus._on('setProperty', this.setProperty)
     this.eventBus._on('setHighlightForm', this.setHighlight)
 
@@ -84,10 +86,28 @@ export default class CheckBox extends Base {
     this.annotationContainer = annotationContainer
     this.annotationContainer.addEventListener('mousedown', this.handleClick.bind(this))
 
+    let shapeElement
+    shapeElement = createElement(
+      'div',
+      {
+        left: 0,
+        top: 0,
+        width: `${Math.abs(rect.width)}px`,
+        height: `${Math.abs(rect.height)}px`,
+        position: 'relative'
+      }
+    )
+    this.shapeElement = shapeElement
+
+    this.getImage()
+    this.annotationContainer.append(this.shapeElement)
+    this.container.append(this.annotationContainer)
+
     let borderElement
     borderElement = createElement(
       'div',
       {
+        position: 'absolute',
         left: 0,
         top: 0,
         display: 'flex',
@@ -99,10 +119,9 @@ export default class CheckBox extends Base {
         borderWidth: annotation.borderWidth | 1 + 'px',
         borderStyle: annotation.borderStyle,
         backgroundColor: annotation.backgroundColor,
-        position: 'relative'
+        opacity: 0
       }
     )
-
     this.borderElement = borderElement
 
     // creat shape svg
@@ -119,7 +138,6 @@ export default class CheckBox extends Base {
         height: `${rect.height / 2}px`
       }
     )
-
     this.svgElement = svgElement
 
     // 填充的图形
@@ -187,8 +205,7 @@ export default class CheckBox extends Base {
     }
 
     this.borderElement.append(this.svgElement)
-    this.annotationContainer.append(this.borderElement)
-    this.container.append(this.annotationContainer)
+    this.shapeElement.append(this.borderElement)
 
     this.outerLineContainer = document.createElement('div')
     this.outerLineContainer.className = 'outline-container'
@@ -419,7 +436,8 @@ export default class CheckBox extends Base {
   };
 
   calculate (start, end) {
-    const initRect = this.rectCalc({ start, end });
+    const initRect = this.rectCalc({ start, end })
+    this.initRect = initRect
     const actualBdWidth = (this.annotation.borderWidth || 2) * this.scale
 
     return {
@@ -537,6 +555,7 @@ export default class CheckBox extends Base {
         type: 'modify',
         annotation: annotation
       })
+      this.getImage()
     }
   }
 
@@ -772,6 +791,7 @@ export default class CheckBox extends Base {
         rect
       }
     })
+    this.getImage()
   }
 
   update ({ start, end }) {
@@ -878,6 +898,7 @@ export default class CheckBox extends Base {
         type: 'modify',
         annotation: updateAnnot
       })
+      this.getImage()
     }
   }
 
@@ -954,6 +975,7 @@ export default class CheckBox extends Base {
       type: 'modify',
       annotation: updateAnnot
     })
+    this.getImage()
   }
 
   judgeCheckboxIsOne (name) {
@@ -977,4 +999,44 @@ export default class CheckBox extends Base {
     this.highlight = bool
     this.annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
   }
+
+  async getImage() {
+    const rect = this.initRect
+    const imgRect = {
+      width: parseInt(rect.width * this.layer.ratio + 1),
+      height: parseInt(rect.height * this.layer.ratio + 1)
+    }
+
+    const imageArray = await this.messageHandler.sendWithPromise('GetRenderAnnot', {
+      annotPtr: this.annotation.annotPtr,
+      rect: this.annotation.rect,
+      scale: this.scale * this.layer.ratio
+    })
+
+    const canvas = document.createElement('canvas')
+    canvas.style.width = imgRect.width + 'px'
+    canvas.style.height = imgRect.height + 'px'
+    canvas.width = imgRect.width
+    canvas.height = imgRect.height
+    let drawContext = canvas.getContext("2d")
+    drawContext.clearRect(0, 0, canvas.width, canvas.height)
+    let imageData = drawContext.createImageData(imgRect.width, imgRect.height)
+    imageData.data.set(imageArray)
+    drawContext.putImageData(imageData, 0, 0)
+    const imgSrc = canvas.toDataURL("image/png", 1)
+
+    if (this.imgEle) {
+      this.imgEle.src = imgSrc
+    } else {
+      let imgEle = document.createElement('img')
+      imgEle.style.width = '100%'
+      imgEle.style.height = '100%'
+      imgEle.style.pointerEvents = 'none'
+
+      imgEle.src = imgSrc
+      this.imgEle = imgEle
+
+      this.shapeElement.append(this.imgEle)
+    }
+  }
 }

+ 68 - 15
packages/core/src/form/combo_box.js

@@ -1,5 +1,4 @@
 import Base from '../annotation/base';
-import { MARGIN_DISTANCE } from '../../constants'
 import { getActualPoint, getClickPoint, createSvg, createElement } from '../annotation/utils';
 import { onClickOutsideUp } from '../ui_utils'
 
@@ -14,7 +13,8 @@ export default class ComboBox extends Base {
     eventBus,
     layer,
     show = false,
-    highlight
+    highlight,
+    messageHandler
   }) {
     super({
       container,
@@ -28,6 +28,7 @@ export default class ComboBox extends Base {
     })
 
     this.layer = layer
+    this.messageHandler = messageHandler
     this.hidden = true
     this.initial = false
     this.outline = null
@@ -56,7 +57,7 @@ export default class ComboBox extends Base {
     this.render()
   }
 
-  render () {
+  async render () {
     this.eventBus._on('setProperty', this.setProperty)
     this.eventBus._on('changeSelectAvailable', this.changeSelectAvailable)
     this.eventBus._on('setHighlightForm', this.setHighlight)
@@ -106,7 +107,7 @@ export default class ComboBox extends Base {
     this.annotationContainer = annotationContainer
     this.annotationContainer.addEventListener('mousedown', this.handleClick.bind(this))
 
-    let borderElement = createElement(
+    let shapeElement = createElement(
       'div',
       {
         left: 0,
@@ -117,12 +118,18 @@ export default class ComboBox extends Base {
         overflow: 'hidden'
       }
     )
-
-    this.borderElement = borderElement
+    this.shapeElement = shapeElement
+    
+    this.getImage()
+    this.annotationContainer.append(this.shapeElement)
+    this.container.append(this.annotationContainer)
 
     let selectElement = createElement(
       'select',
       {
+        position: 'absolute',
+        left: 0,
+        top: 0,
         paddingLeft: '4px',
         width: `${Math.abs(rect.width)}px`,
         height: `${Math.abs(rect.height)}px`,
@@ -139,7 +146,8 @@ export default class ComboBox extends Base {
         fontWeight: annotation.isBold ? 'bold' : 'normal',
         fontStyle: annotation.isItalic ? 'italic' : 'normal',
         textOverflow: 'ellipsis',
-        whiteSpace: 'nowrap'
+        whiteSpace: 'nowrap',
+        opacity: 0
       }
     )
     if (this.layer.toolMode === 'form') {
@@ -163,7 +171,8 @@ export default class ComboBox extends Base {
         right: '4px',
         top: '50%',
         transform: 'translateY(-50%)',
-        pointerEvents: 'none'
+        pointerEvents: 'none',
+        opacity: 0
       }
     )
     const path = createSvg(
@@ -179,10 +188,8 @@ export default class ComboBox extends Base {
     this.svgElement = svgElement
     this.svgElement.append(path)
     
-    this.borderElement.append(this.svgElement)
-    this.borderElement.append(this.selectElement)
-    this.annotationContainer.append(this.borderElement)
-    this.container.append(this.annotationContainer)
+    this.shapeElement.append(this.svgElement)
+    this.shapeElement.append(this.selectElement)
 
     // 添加选项
     if (annotation.items && annotation.items.length > 0) {
@@ -429,7 +436,8 @@ export default class ComboBox extends Base {
   };
 
   calculate (start, end) {
-    const initRect = this.rectCalc({ start, end });
+    const initRect = this.rectCalc({ start, end })
+    this.initRect = initRect
     const actualBdWidth = (this.annotation.borderWidth || 1) * this.scale
 
     return {
@@ -759,6 +767,7 @@ export default class ComboBox extends Base {
         rect
       }
     })
+    this.getImage()
   }
 
   update ({ start, end }) {
@@ -775,8 +784,8 @@ export default class ComboBox extends Base {
     this.annotationContainer.style.width = `${rect.width}px`;
     this.annotationContainer.style.height = `${rect.height}px`;
 
-    this.borderElement.style.width = `${rect.width}px`;
-    this.borderElement.style.height = `${rect.height}px`;
+    this.shapeElement.style.width = `${rect.width}px`;
+    this.shapeElement.style.height = `${rect.height}px`;
 
     this.selectElement.style.width = `${rect.width}px`;
     this.selectElement.style.height = `${rect.height}px`;
@@ -982,6 +991,7 @@ export default class ComboBox extends Base {
         } else {
           annotationData.fontName = fontArr[fontName].normal
         }
+        delete props.fontName
       }
 
       const updateAnnot = Object.assign({}, annotationData, props)
@@ -991,6 +1001,7 @@ export default class ComboBox extends Base {
         type: 'modify',
         annotation: updateAnnot
       })
+      this.getImage()
     }
   }
 
@@ -1052,6 +1063,7 @@ export default class ComboBox extends Base {
       } else {
         annotationData.fontName = fontArr[fontName].normal
       }
+      delete props.fontName
     }
 
     const updateAnnot = Object.assign({}, annotationData, props)
@@ -1059,6 +1071,7 @@ export default class ComboBox extends Base {
       type: 'modify',
       annotation: updateAnnot
     })
+    this.getImage()
   }
 
   changeSelectAvailable () {
@@ -1082,4 +1095,44 @@ export default class ComboBox extends Base {
     this.highlight = bool
     this.annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
   }
+
+  async getImage() {
+    const rect = this.initRect
+    const imgRect = {
+      width: parseInt(rect.width * this.layer.ratio + 1),
+      height: parseInt(rect.height * this.layer.ratio + 1)
+    }
+
+    const imageArray = await this.messageHandler.sendWithPromise('GetRenderAnnot', {
+      annotPtr: this.annotation.annotPtr,
+      rect: this.annotation.rect,
+      scale: this.scale * this.layer.ratio
+    })
+
+    const canvas = document.createElement('canvas')
+    canvas.style.width = imgRect.width + 'px'
+    canvas.style.height = imgRect.height + 'px'
+    canvas.width = imgRect.width
+    canvas.height = imgRect.height
+    let drawContext = canvas.getContext("2d")
+    drawContext.clearRect(0, 0, canvas.width, canvas.height)
+    let imageData = drawContext.createImageData(imgRect.width, imgRect.height)
+    imageData.data.set(imageArray)
+    drawContext.putImageData(imageData, 0, 0)
+    const imgSrc = canvas.toDataURL("image/png", 1)
+
+    if (this.imgEle) {
+      this.imgEle.src = imgSrc
+    } else {
+      let imgEle = document.createElement('img')
+      imgEle.style.width = '100%'
+      imgEle.style.height = '100%'
+      imgEle.style.pointerEvents = 'none'
+
+      imgEle.src = imgSrc
+      this.imgEle = imgEle
+
+      this.shapeElement.append(this.imgEle)
+    }
+  }
 }

+ 66 - 13
packages/core/src/form/list_box.js

@@ -13,7 +13,8 @@ export default class ListBox extends Base {
     eventBus,
     layer,
     show = false,
-    highlight
+    highlight,
+    messageHandler
   }) {
     super({
       container,
@@ -27,6 +28,7 @@ export default class ListBox extends Base {
     })
 
     this.layer = layer
+    this.messageHandler = messageHandler
     this.hidden = true
     this.initial = false
     this.outline = null
@@ -55,7 +57,7 @@ export default class ListBox extends Base {
     this.render()
   }
 
-  render() {
+  async render() {
     this.eventBus._on('setProperty', this.setProperty)
     this.eventBus._on('changeSelectAvailable', this.changeSelectAvailable)
     this.eventBus._on('setHighlightForm', this.setHighlight)
@@ -100,8 +102,8 @@ export default class ListBox extends Base {
     annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
     this.annotationContainer = annotationContainer
     this.annotationContainer.addEventListener('mousedown', this.handleClick.bind(this))
-
-    let borderElement = createElement(
+    
+    let shapeElement = createElement(
       'div',
       {
         left: 0,
@@ -111,11 +113,18 @@ export default class ListBox extends Base {
         position: 'relative'
       }
     )
+    this.shapeElement = shapeElement
+
+    this.getImage()
+    this.annotationContainer.append(this.shapeElement)
+    this.container.append(this.annotationContainer)
 
-    this.borderElement = borderElement
     let selectElement = createElement(
       'div',
       {
+        position: 'absolute',
+        left: 0,
+        top: 0,
         width: `${Math.abs(rect.width)}px`,
         height: `${Math.abs(rect.height)}px`,
         borderColor: annotation.borderColor,
@@ -128,14 +137,12 @@ export default class ListBox extends Base {
         fontStyle: annotation.isItalic ? 'italic' : 'normal',
         fontFamily: annotation.fontName,
         color: annotation.color || '#001A4E',
-        overflow: 'auto'
+        overflow: 'auto',
+        opacity: 0
       }
     )
     this.selectElement = selectElement
-
-    this.borderElement.append(this.selectElement)
-    this.annotationContainer.append(this.borderElement)
-    this.container.append(this.annotationContainer)
+    this.shapeElement.append(this.selectElement)
 
     // 添加选项
     if (annotation.items && annotation.items.length > 0) {
@@ -394,7 +401,8 @@ export default class ListBox extends Base {
   };
 
   calculate(start, end) {
-    const initRect = this.rectCalc({ start, end });
+    const initRect = this.rectCalc({ start, end })
+    this.initRect = initRect
     const actualBdWidth = (this.annotation.borderWidth || 1) * this.scale
 
     return {
@@ -735,6 +743,7 @@ export default class ListBox extends Base {
         rect
       }
     })
+    this.getImage()
   }
 
   update({ start, end }) {
@@ -751,8 +760,8 @@ export default class ListBox extends Base {
     this.annotationContainer.style.width = `${rect.width}px`;
     this.annotationContainer.style.height = `${rect.height}px`;
 
-    this.borderElement.style.width = `${rect.width}px`;
-    this.borderElement.style.height = `${rect.height}px`;
+    this.shapeElement.style.width = `${rect.width}px`;
+    this.shapeElement.style.height = `${rect.height}px`;
 
     this.selectElement.style.width = `${rect.width}px`;
     this.selectElement.style.height = `${rect.height}px`;
@@ -966,6 +975,7 @@ export default class ListBox extends Base {
         } else {
           annotationData.fontName = fontArr[fontName].normal
         }
+        delete props.fontName
       }
 
       const updateAnnot = Object.assign({}, annotationData, props)
@@ -975,6 +985,7 @@ export default class ListBox extends Base {
         type: 'modify',
         annotation: updateAnnot
       })
+      this.getImage()
     }
   }
 
@@ -1036,6 +1047,7 @@ export default class ListBox extends Base {
       } else {
         annotationData.fontName = fontArr[fontName].normal
       }
+      delete props.fontName
     }
 
     const updateAnnot = Object.assign({}, annotationData, props)
@@ -1043,6 +1055,7 @@ export default class ListBox extends Base {
       type: 'modify',
       annotation: updateAnnot
     })
+    this.getImage()
   }
 
   changeSelectAvailable() {
@@ -1070,4 +1083,44 @@ export default class ListBox extends Base {
     this.highlight = bool
     this.annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
   }
+
+  async getImage() {
+    const rect = this.initRect
+    const imgRect = {
+      width: parseInt(rect.width * this.layer.ratio + 1),
+      height: parseInt(rect.height * this.layer.ratio + 1)
+    }
+
+    const imageArray = await this.messageHandler.sendWithPromise('GetRenderAnnot', {
+      annotPtr: this.annotation.annotPtr,
+      rect: this.annotation.rect,
+      scale: this.scale * this.layer.ratio
+    })
+
+    const canvas = document.createElement('canvas')
+    canvas.style.width = imgRect.width + 'px'
+    canvas.style.height = imgRect.height + 'px'
+    canvas.width = imgRect.width
+    canvas.height = imgRect.height
+    let drawContext = canvas.getContext("2d")
+    drawContext.clearRect(0, 0, canvas.width, canvas.height)
+    let imageData = drawContext.createImageData(imgRect.width, imgRect.height)
+    imageData.data.set(imageArray)
+    drawContext.putImageData(imageData, 0, 0)
+    const imgSrc = canvas.toDataURL("image/png", 1)
+
+    if (this.imgEle) {
+      this.imgEle.src = imgSrc
+    } else {
+      let imgEle = document.createElement('img')
+      imgEle.style.width = '100%'
+      imgEle.style.height = '100%'
+      imgEle.style.pointerEvents = 'none'
+
+      imgEle.src = imgSrc
+      this.imgEle = imgEle
+
+      this.shapeElement.append(this.imgEle)
+    }
+  }
 }

+ 147 - 19
packages/core/src/form/push_button.js

@@ -13,7 +13,8 @@ export default class PushButton extends Base {
     eventBus,
     layer,
     show = false,
-    highlight
+    highlight,
+    messageHandler
   }) {
     super({
       container,
@@ -27,6 +28,7 @@ export default class PushButton extends Base {
     })
 
     this.layer = layer
+    this.messageHandler = messageHandler
     this.hidden = true
     this.initial = false
     this.outline = null
@@ -54,7 +56,7 @@ export default class PushButton extends Base {
     this.render()
   }
 
-  render () {
+  async render () {
     this.eventBus._on('setProperty', this.setProperty)
     this.eventBus._on('setHighlightForm', this.setHighlight)
 
@@ -104,16 +106,18 @@ export default class PushButton extends Base {
         position: 'relative'
       }
     )
-
     this.shapeElement = shapeElement
 
+    this.getImage()
     this.annotationContainer.append(this.shapeElement)
-
     this.container.append(this.annotationContainer)
 
     this.buttonContainer = createElement(
       'a',
       {
+        position: 'absolute',
+        left: 0,
+        top: 0,
         display: 'flex',
         alignItems: 'center',
         justifyContent: 'center',
@@ -130,11 +134,13 @@ export default class PushButton extends Base {
         fontWeight: annotation.isBold ? 'bold' : 'normal',
         fontStyle: annotation.isItalic ? 'italic' : 'normal',
         overflow: 'hidden',
-        textDecoration: 'none'
+        textDecoration: 'none',
+        opacity: 0
       }
     )
     this.buttonContainer.innerHTML = annotation.title
     this.shapeElement.append(this.buttonContainer)
+
     this.buttonContainer.addEventListener('blur', this.onBlur)
     if (this.annotation.url) {
       this.buttonContainer.setAttribute('href', this.annotation.url)
@@ -372,7 +378,8 @@ export default class PushButton extends Base {
   };
 
   calculate (start, end) {
-    const initRect = this.rectCalc({ start, end });
+    const initRect = this.rectCalc({ start, end })
+    this.initRect = initRect
     const actualbdwidth = (this.annotation.borderWidth || 2) * this.scale
 
     return {
@@ -700,7 +707,7 @@ export default class PushButton extends Base {
       top: start.y,
       right: end.x,
       bottom: end.y
-     }
+    }
 
     this.eventBus.dispatch('annotationChange', {
       type: 'modify',
@@ -713,6 +720,7 @@ export default class PushButton extends Base {
         rect
       }
     })
+    this.getImage()
   }
 
   update ({ start, end }) {
@@ -877,6 +885,7 @@ export default class PushButton extends Base {
         } else {
           annotationData.fontName = fontArr[fontName].normal
         }
+        delete props.fontName
       }
 
       const updateAnnot = Object.assign({}, annotationData, props)
@@ -884,24 +893,32 @@ export default class PushButton extends Base {
         type: 'modify',
         annotation: updateAnnot
       })
+      console.log(updateAnnot)
+      this.getImage()
     }
   }
 
   setProperty (props) {
     if (props.name !== this.annotation.name) return
+    const annotation = this.annotation
 
+    let updatePropsNum = 0
     for (const key in props) {
       for (const item in this.annotation) {
         if (item === key && this.annotation[item] !== props[key]) {
           this.annotation[item] = props[key]
-          
+          updatePropsNum ++
+
           if (key === 'backgroundColor') {
             this.buttonContainer.style[key] = props[key]
+            if (props[key] === '') {
+              props.clearBackgroundColor = true
+            }
           }
           if (key === 'fontSize') {
             this.buttonContainer.style.fontSize = props[key] + 'px'
           }
-          if (key === 'textColor') {
+          if (key === 'color') {
             this.buttonContainer.style.color = props[key]
           }
           if (key === 'fontName') {
@@ -914,25 +931,136 @@ export default class PushButton extends Base {
             this.buttonContainer.setAttribute('href', this.annotation.url)
             this.buttonContainer.setAttribute('target', '_blank')
           }
+          if (key === 'fontStyle') {
+            const fontStyle = props[key]
+            if (fontStyle === 'boldItalic') {
+              this.buttonContainer.style.fontStyle = 'italic'
+              this.buttonContainer.style.fontWeight = 'bold'
+              annotation.isBold = true
+              annotation.isItalic = true
+            } else if (fontStyle === 'bold') {
+              this.buttonContainer.style.fontStyle = 'normal'
+              this.buttonContainer.style.fontWeight = 'bold'
+              annotation.isBold = true
+              annotation.isItalic = false
+            } else if (fontStyle === 'italic') {
+              this.buttonContainer.style.fontStyle = 'italic'
+              this.buttonContainer.style.fontWeight = 'normal'
+              annotation.isBold = false
+              annotation.isItalic = true
+            } else {
+              annotation.isItalic = false
+              annotation.isBold = false
+              this.buttonContainer.style.fontStyle = 'normal'
+              this.buttonContainer.style.fontWeight = 'normal'
+            }
+          }
         }
       }
     }
 
-    const annotation = {
-      operate: "mod-form",
-      pageIndex: this.page,
-      pagePtr: this.annotation.pagePtr,
-      annotPtr: this.annotation.annotPtr,
+    if (updatePropsNum > 0) {
+      const annotationData = {
+        operate: "mod-form",
+        name: this.annotation.name,
+        pageIndex: this.page,
+        pagePtr: this.annotation.pagePtr,
+        annotPtr: this.annotation.annotPtr,
+        pageHeight: this.viewport.rawDims.pageHeight
+      }
+      if ((props.destPage || props.url) && this.annotation.actionType !== '0') {
+        annotationData.actionType = this.annotation.actionType
+      }
+
+      const isFont = ['fontSize', 'fontName', 'color', 'fontStyle'].some(item => props[item])
+      if (isFont) {
+        annotationData.fontSize = annotation.fontSize
+        annotationData.color = annotation.color
+        const fontArr = {
+          Courier: {
+            normal: 'Courier',
+            bold: 'Courier-Bold',
+            italic: 'Courier-Oblique',
+            boldItalic: 'Courier-BoldOblique'
+          },
+          Helvetica: {
+            normal: 'Helvetica',
+            bold: 'Helvetica-Bold',
+            italic: 'Helvetica-Oblique',
+            boldItalic: 'Helvetica-BoldOblique'
+          },
+          Times: {
+            normal: 'Times',
+            bold: 'Times-Bold',
+            italic: 'Times-Italic',
+            boldItalic: 'Times-BoldItalic'
+          }
+        }
+
+        const fontName = annotation.fontName
+        if (annotation.isBold && annotation.isItalic) {
+          annotationData.fontName = fontArr[fontName].boldItalic
+        } else if (annotation.isBold) {
+          annotationData.fontName = fontArr[fontName].bold
+        } else if (annotation.isItalic) {
+          annotationData.fontName = fontArr[fontName].italic
+        } else {
+          annotationData.fontName = fontArr[fontName].normal
+        }
+        delete props.fontName
+      }
+
+      const updateAnnot = Object.assign({}, annotationData, props)
+      this.eventBus.dispatch('annotationChange', {
+        type: 'modify',
+        annotation: updateAnnot
+      })
+      this.getImage()
     }
-    const updateAnnot = Object.assign({}, annotation, props)
-    this.eventBus.dispatch('annotationChange', {
-      type: 'modify',
-      annotation: updateAnnot
-    })
   }
 
   setHighlight (bool) {
     this.highlight = bool
     this.annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
   }
+
+  async getImage() {
+    const rect = this.initRect
+    const imgRect = {
+      width: parseInt(rect.width * this.layer.ratio + 1),
+      height: parseInt(rect.height * this.layer.ratio + 1)
+    }
+
+    const imageArray = await this.messageHandler.sendWithPromise('GetRenderAnnot', {
+      annotPtr: this.annotation.annotPtr,
+      rect: this.annotation.rect,
+      scale: this.scale * this.layer.ratio
+    })
+
+    const canvas = document.createElement('canvas')
+    canvas.style.width = imgRect.width + 'px'
+    canvas.style.height = imgRect.height + 'px'
+    canvas.width = imgRect.width
+    canvas.height = imgRect.height
+    let drawContext = canvas.getContext("2d")
+    drawContext.clearRect(0, 0, canvas.width, canvas.height)
+    let imageData = drawContext.createImageData(imgRect.width, imgRect.height)
+    imageData.data.set(imageArray)
+    drawContext.putImageData(imageData, 0, 0)
+    const imgSrc = canvas.toDataURL("image/png", 1)
+
+    if (this.imgEle) {
+      this.imgEle.src = imgSrc
+    } else {
+      let imgEle = document.createElement('img')
+      imgEle.style.width = '100%'
+      imgEle.style.height = '100%'
+      imgEle.style.pointerEvents = 'none'
+
+      imgEle.src = imgSrc
+      this.imgEle = imgEle
+
+      this.shapeElement.append(this.imgEle)
+    }
+  }
 }

+ 71 - 9
packages/core/src/form/radio_button.js

@@ -13,7 +13,8 @@ export default class RadioButton extends Base {
     eventBus,
     layer,
     show = false,
-    highlight
+    highlight,
+    messageHandler
   }) {
     super({
       container,
@@ -27,6 +28,7 @@ export default class RadioButton extends Base {
     })
 
     this.layer = layer
+    this.messageHandler = messageHandler
     this.hidden = true
     this.initial = false
     this.outline = null
@@ -54,7 +56,7 @@ export default class RadioButton extends Base {
     this.render()
   }
 
-  render () {
+  async render () {
     this.eventBus._on('setProperty', this.setProperty)
     this.eventBus._on('setHighlightForm', this.setHighlight)
 
@@ -84,10 +86,28 @@ export default class RadioButton extends Base {
     this.annotationContainer = annotationContainer
     this.annotationContainer.addEventListener('mousedown', this.handleClick.bind(this))
 
+    let shapeElement
+    shapeElement = createElement(
+      'div',
+      {
+        left: 0,
+        top: 0,
+        width: `${Math.abs(rect.width)}px`,
+        height: `${Math.abs(rect.height)}px`,
+        position: 'relative'
+      }
+    )
+    this.shapeElement = shapeElement
+
+    this.getImage()
+    this.annotationContainer.append(this.shapeElement)
+    this.container.append(this.annotationContainer)
+    
     let borderElement
     borderElement = createElement(
       'div',
       {
+        position: 'absolute',
         left: 0,
         top: 0,
         display: 'flex',
@@ -100,10 +120,9 @@ export default class RadioButton extends Base {
         borderStyle: annotation.borderStyle,
         borderRadius: '100%',
         backgroundColor: annotation.backgroundColor,
-        position: 'relative'
+        opacity: 0
       }
     )
-
     this.borderElement = borderElement
 
     // creat shape svg
@@ -120,7 +139,6 @@ export default class RadioButton extends Base {
         height: `${rect.height / 2}px`
       }
     )
-
     this.svgElement = svgElement
 
     // 填充的图形
@@ -188,8 +206,7 @@ export default class RadioButton extends Base {
     }
 
     this.borderElement.append(this.svgElement)
-    this.annotationContainer.append(this.borderElement)
-    this.container.append(this.annotationContainer)
+    this.shapeElement.append(this.borderElement)
 
     this.outerLineContainer = document.createElement('div')
     this.outerLineContainer.className = 'outline-container'
@@ -420,7 +437,8 @@ export default class RadioButton extends Base {
   };
 
   calculate (start, end) {
-    const initRect = this.rectCalc({ start, end });
+    const initRect = this.rectCalc({ start, end })
+    this.initRect = initRect
     const actualBdWidth = (this.annotation.borderWidth || 2) * this.scale
 
     return {
@@ -540,6 +558,7 @@ export default class RadioButton extends Base {
         type: 'modify',
         annotation: annotation
       })
+      this.getImage()
     }
   }
 
@@ -762,7 +781,7 @@ export default class RadioButton extends Base {
       top: start.y,
       right: end.x,
       bottom: end.y
-     }
+    }
 
     this.eventBus.dispatch('annotationChange', {
       type: 'modify',
@@ -775,6 +794,7 @@ export default class RadioButton extends Base {
         rect
       }
     })
+    this.getImage()
   }
 
   update ({ start, end }) {
@@ -879,6 +899,7 @@ export default class RadioButton extends Base {
         type: 'modify',
         annotation: updateAnnot
       })
+      this.getImage()
     }
   }
 
@@ -958,6 +979,7 @@ export default class RadioButton extends Base {
       type: 'modify',
       annotation: updateAnnot
     })
+    this.getImage()
   }
 
   cancelSameGroupButton () {
@@ -994,4 +1016,44 @@ export default class RadioButton extends Base {
     this.highlight = bool
     this.annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
   }
+
+  async getImage() {
+    const rect = this.initRect
+    const imgRect = {
+      width: parseInt(rect.width * this.layer.ratio + 1),
+      height: parseInt(rect.height * this.layer.ratio + 1)
+    }
+
+    const imageArray = await this.messageHandler.sendWithPromise('GetRenderAnnot', {
+      annotPtr: this.annotation.annotPtr,
+      rect: this.annotation.rect,
+      scale: this.scale * this.layer.ratio
+    })
+
+    const canvas = document.createElement('canvas')
+    canvas.style.width = imgRect.width + 'px'
+    canvas.style.height = imgRect.height + 'px'
+    canvas.width = imgRect.width
+    canvas.height = imgRect.height
+    let drawContext = canvas.getContext("2d")
+    drawContext.clearRect(0, 0, canvas.width, canvas.height)
+    let imageData = drawContext.createImageData(imgRect.width, imgRect.height)
+    imageData.data.set(imageArray)
+    drawContext.putImageData(imageData, 0, 0)
+    const imgSrc = canvas.toDataURL("image/png", 1)
+
+    if (this.imgEle) {
+      this.imgEle.src = imgSrc
+    } else {
+      let imgEle = document.createElement('img')
+      imgEle.style.width = '100%'
+      imgEle.style.height = '100%'
+      imgEle.style.pointerEvents = 'none'
+
+      imgEle.src = imgSrc
+      this.imgEle = imgEle
+
+      this.shapeElement.append(this.imgEle)
+    }
+  }
 }

+ 69 - 10
packages/core/src/form/text_field.js

@@ -14,7 +14,8 @@ export default class TextField extends Base {
     eventBus,
     layer,
     show = false,
-    highlight
+    highlight,
+    messageHandler
   }) {
     super({
       container,
@@ -28,6 +29,7 @@ export default class TextField extends Base {
     })
 
     this.layer = layer
+    this.messageHandler = messageHandler
     this.hidden = true
     this.initial = false
     this.outline = null
@@ -112,11 +114,10 @@ export default class TextField extends Base {
         position: 'relative'
       }
     )
-
     this.shapeElement = shapeElement
 
+    this.getImage()
     this.annotationContainer.append(this.shapeElement)
-
     this.container.append(this.annotationContainer)
 
     // create text
@@ -353,7 +354,8 @@ export default class TextField extends Base {
   };
 
   calculate (start, end) {
-    const initRect = this.rectCalc({ start, end });
+    const initRect = this.rectCalc({ start, end })
+    this.initRect = initRect
     const actualBdWidth = (this.annotation.borderWidth || 1) * this.scale
 
     return {
@@ -460,6 +462,8 @@ export default class TextField extends Base {
       }, 0);
       this.textContainer.style.pointerEvents = 'auto'
       this.textContainer.style.cursor = 'text'
+      this.textContainer.style.opacity = ''
+      this.imgEle.style.opacity = 0
     }
   }
 
@@ -483,7 +487,7 @@ export default class TextField extends Base {
     this.eventBus._off('textfieldPropertyPanelChanged', this.handlePropertyPanel)
   }
 
-  handleBlur () {
+  async handleBlur () {
     if (this.annotation.contents !== this.textContainer.value) {
       this.annotation.contents = this.textContainer.value
       this.eventBus.dispatch('annotationChange', {
@@ -498,9 +502,12 @@ export default class TextField extends Base {
           contents: this.annotation.contents
         }
       })
+      this.getImage()
     }
     this.textContainer.style.pointerEvents = 'none'
     this.textContainer.style.cursor = 'pointer'
+    this.textContainer.style.opacity = 0
+    this.imgEle.style.opacity = ''
   }
 
   handleMouseDown (event) {
@@ -705,7 +712,7 @@ export default class TextField extends Base {
       top: start.y,
       right: end.x,
       bottom: end.y
-     }
+    }
 
     this.eventBus.dispatch('annotationChange', {
       type: 'modify',
@@ -883,6 +890,7 @@ export default class TextField extends Base {
         } else {
           annotationData.fontName = fontArr[fontName].normal
         }
+        delete props.fontName
       }
 
       const updateAnnot = Object.assign({}, annotationData, props)
@@ -890,6 +898,7 @@ export default class TextField extends Base {
         type: 'modify',
         annotation: updateAnnot
       })
+      this.getImage()
     }
   }
 
@@ -914,7 +923,10 @@ export default class TextField extends Base {
           width: '100%',
           height: '100%',
           outline: 'none',
-          border: 'none',
+          borderColor: this.annotation.borderColor,
+          borderStyle: this.annotation.borderStyle,
+          borderWidth: this.annotation.borderWidth + 'px',
+          borderRadius: 0,
           color: this.annotation.color,
           backgroundColor: this.annotation.backgroundColor,
           pointerEvents: 'none',
@@ -925,7 +937,8 @@ export default class TextField extends Base {
           fontSize: this.annotation.fontSize + 'px',
           fontWeight: this.annotation.isBold ? 'bold' : 'normal',
           fontStyle: this.annotation.isItalic ? 'italic' : 'normal',
-          fontFamily: this.annotation.fontName
+          fontFamily: this.annotation.fontName,
+          opacity: 0
         }
       )
       textContainer.innerHTML = this.annotation.contents
@@ -939,7 +952,10 @@ export default class TextField extends Base {
           width: '100%',
           height: '100%',
           outline: 'none',
-          border: 'none',
+          borderColor: this.annotation.borderColor,
+          borderStyle: this.annotation.borderStyle,
+          borderWidth: this.annotation.borderWidth + 'px',
+          borderRadius: 0,
           color: this.annotation.color,
           backgroundColor: this.annotation.backgroundColor,
           pointerEvents: 'none',
@@ -948,7 +964,8 @@ export default class TextField extends Base {
           fontSize: this.annotation.fontSize + 'px',
           fontWeight: this.annotation.isBold ? 'bold' : 'normal',
           fontStyle: this.annotation.isItalic ? 'italic' : 'normal',
-          fontFamily: this.annotation.fontName
+          fontFamily: this.annotation.fontName,
+          opacity: 0
         },
         { value: this.annotation.contents }
       )
@@ -1079,6 +1096,7 @@ export default class TextField extends Base {
       } else {
         annotationData.fontName = fontArr[fontName].normal
       }
+      delete props.fontName
     }
 
     const updateAnnot = Object.assign({}, annotationData, props)
@@ -1086,10 +1104,51 @@ export default class TextField extends Base {
       type: 'modify',
       annotation: updateAnnot
     })
+    this.getImage()
   }
 
   setHighlight (bool) {
     this.highlight = bool
     this.annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
   }
+
+  async getImage() {
+    const rect = this.initRect
+    const imgRect = {
+      width: parseInt(rect.width * this.layer.ratio + 1),
+      height: parseInt(rect.height * this.layer.ratio + 1)
+    }
+
+    const imageArray = await this.messageHandler.sendWithPromise('GetRenderAnnot', {
+      annotPtr: this.annotation.annotPtr,
+      rect: this.annotation.rect,
+      scale: this.scale * this.layer.ratio
+    })
+
+    const canvas = document.createElement('canvas')
+    canvas.style.width = imgRect.width + 'px'
+    canvas.style.height = imgRect.height + 'px'
+    canvas.width = imgRect.width
+    canvas.height = imgRect.height
+    let drawContext = canvas.getContext("2d")
+    drawContext.clearRect(0, 0, canvas.width, canvas.height)
+    let imageData = drawContext.createImageData(imgRect.width, imgRect.height)
+    imageData.data.set(imageArray)
+    drawContext.putImageData(imageData, 0, 0)
+    const imgSrc = canvas.toDataURL("image/png", 1)
+
+    if (this.imgEle) {
+      this.imgEle.src = imgSrc
+    } else {
+      let imgEle = document.createElement('img')
+      imgEle.style.width = '100%'
+      imgEle.style.height = '100%'
+      imgEle.style.pointerEvents = 'none'
+
+      imgEle.src = imgSrc
+      this.imgEle = imgEle
+
+      this.shapeElement.append(this.imgEle)
+    }
+  }
 }

+ 7 - 3
packages/core/src/worker/compdfkit_worker.js

@@ -626,14 +626,16 @@ class CPDFWorker {
         const textAlignmentInt = ALIGNMAP[textAlignment.toUpperCase()]
         Module._SetWidgetTextJustification(annotPtr, textAlignmentInt)
       }
-      if (annotation.isMultiLine) {
+      if (annotation.hasOwnProperty('isMultiLine')) {
         const { annotPtr, isMultiLine } = annotation
         Module._SetMultiLine(annotPtr, isMultiLine)
       }
       if (annotation.author) {
         setAnnotAuthor(annotation)
       }
-      Module._UpdateAnnotAp(annotation.annotPtr, 0)
+
+      if (annotation.operate === 'mod-form') Module._UpdateFormAp(annotation.annotPtr)
+      else Module._UpdateAnnotAp(annotation.annotPtr, 0)
     })
 
     messageHandler.on('FlattenPage', (data) => {
@@ -2233,7 +2235,9 @@ function createAnnotation(doc, pagePtr, annotation) {
     })
   }
 
-  Module._UpdateAnnotAp(annotPtr, 0)
+  if (annotation.operate === 'mod-form') Module._UpdateFormAp(annotation.annotPtr)
+  else Module._UpdateAnnotAp(annotation.annotPtr, 0)
+
   return {
     annotPtr
   }

+ 7 - 9
packages/webview/src/components/RightPanel/RightPanel.vue

@@ -148,7 +148,7 @@
           </div>
           <div class="content-block">
             <h2>{{ $t('rightPanel.defaultValue') }}</h2>
-            <textarea name="default-value" id="default-value" rows="3" v-model="property.contents"></textarea>
+            <textarea name="default-value" id="default-value" rows="3" v-model="property.contents" @change="onChangeContent"></textarea>
           </div>
           <div class="content-block">
             <div class="check-box" @click="property.isMultiLine = !property.isMultiLine">
@@ -357,13 +357,6 @@
     useDocument.setPropertyPanel({'textAlignment': newValue})
   })
   
-  watch(() => property.contents, (newValue, oldValue) => {
-    if (newValue === '') {
-      newValue = ' '
-    }
-    useDocument.setPropertyPanel({'contents': newValue})
-  })
-  
   watch(() => property.isMultiLine, (newValue, oldValue) => {
     useDocument.setPropertyPanel({'isMultiLine': newValue})
   })
@@ -377,7 +370,7 @@
   })
   
   watch(() => property.isChecked, (newValue, oldValue) => {
-    useDocument.setPropertyPanel({'isChecked': newValue})
+    useDocument.setPropertyPanel({'isChecked': +newValue})
   })
   
   watch(() => property.actionType, (newValue, oldValue) => {
@@ -429,6 +422,11 @@
     property.isChecked = !property.isChecked
   }
 
+  const onChangeContent = () => {
+    const value = property.contents === '' ? ' ' : property.contents
+    useDocument.setPropertyPanel({'contents': value})
+  }
+
   const toggleSeparate = (boolean) => {
     isOneRadioBtn.value = boolean
   }

+ 2 - 2
packages/webview/src/helpers/utils.js

@@ -42,6 +42,8 @@ const hslToRgb = (h, s, l) => {
 
 // 转换颜色 hsl / hex -> rgb
 const convertColor = (colorStr) => {
+  if (!colorStr) return null;
+
   if (colorStr.startsWith('#')) {
     const hexValues = colorStr.slice(1).match(/.{2}/g);
     if (hexValues) {
@@ -72,8 +74,6 @@ const convertColor = (colorStr) => {
       return {R, G, B};
     }
   }
-
-  return null;
 }
 
 // 判断两个颜色字符串在阈值外是否相同