UNPKG

lichen-annotate-pdf

Version:

Annotation layer for pdf.js in vue fork of Aaron Leong pdf-annotate-vue

311 lines (287 loc) 8.52 kB
import PDFJSAnnotate from '../PDFJSAnnotate'; import { appendChild } from '../render/appendChild'; let MathLive = require('mathlive/dist/mathlive.mjs'); import { CUSTOM_KEYBOARD_LAYER } from '../UI/keyboardOptions.js'; // import { renderMathInDocument } from 'https://unpkg.com/mathlive/dist/mathlive.min.mjs'; // document.addEventListener("load", () => { // renderMathInDocument(); // }); import { BORDER_COLOR, findSVGAtPoint, getMetadata, convertToSvgPoint } from './utils'; let _enabled = false; let input; let mathField; let _textSize; let _textColor; /** * Handle document.mouseup event * * @param {Event} e The DOM event to handle */ function handleDocumentMouseup (e) { if (!findSVGAtPoint(e.clientX, e.clientY)) { console.log('deja un input || !findSVGAtPoint(e.clientX, e.clientY)') return; } if (!e.srcElement.classList.contains('annotationLayer')) { console.log('on a pas de annotationLayer') return; } input = document.createElement('input'); input.setAttribute('id', 'pdf-annotate-text-input'); input.setAttribute('placeholder', 'Insérer du texte ici...'); input.style.border = `3px solid ${BORDER_COLOR}`; input.style.borderRadius = '3px'; input.style.backgroundColor = 'rgba(255,255,255,0.85)'; input.style.position = 'absolute'; input.style.top = `${e.clientY}px`; input.style.left = `${e.clientX}px`; input.style.fontSize = `${_textSize}px`; input.style.zIndex = '999999'; input.style.padding = '5px'; input.addEventListener('blur', handleInputBlur); input.addEventListener('keyup', handleInputKeyup); document.body.appendChild(input); input.focus(); } function handleDocumentMathMouseup (e) { // on gère les maths // console.log('on est ici', input) if (!findSVGAtPoint(e.clientX, e.clientY)) { console.log('not find svg') return; } if (!e.srcElement.classList.contains('annotationLayer')) { return; } // on va chercker si un truc est déjà là const temp = window.document.getElementById('pdf-annotate-text-input') if (temp) { temp.remove(); } input = document.createElement('div'); input.setAttribute('id', 'pdf-annotate-text-input'); input.setAttribute('placeholder', 'Insérer du texte ici...'); input.style.border = `3px solid ${BORDER_COLOR}`; input.style.borderRadius = '3px'; input.style.backgroundColor = 'rgba(255,255,255,0.85)'; input.style.position = 'absolute'; input.style.top = `${e.clientY}px`; input.style.left = `${e.clientX}px`; input.style.fontSize = `${_textSize}px`; input.style.zIndex = '999999'; input.style.padding = '5px'; document.body.appendChild(input); mathField = MathLive.makeMathField('pdf-annotate-text-input', { locale: 'fr', customVirtualKeyboardLayers: CUSTOM_KEYBOARD_LAYER, customVirtualKeyboards: { 'custom-keyboard': { label: '123', tooltip: 'Numérique', layer: 'custom-layer' } }, virtualKeyboards: 'custom-keyboard symbols', virtualKeyboardMode: 'manual', onBlur: (test) => { handleMathBlur(); } }) } /** * Handle input.blur event */ function handleInputBlur () { saveText(); } function handleMathBlur () { saveMathText(); } /** * Handle input.keyup event * * @param {Event} e The DOM event to handle */ function handleInputKeyup (e) { if (e.keyCode === 27) { closeInput(); } else if (e.keyCode === 13) { saveText(); } } /** * Save a text annotation from input */ function saveText () { let value = (input.value) ? input.value.replace(/ +$/, '') : ''; if (value.length > 0) { let clientX = parseInt(input.style.left, 10); let clientY = parseInt(input.style.top, 10); let svg = findSVGAtPoint(clientX, clientY); if (!svg) { return; } let height = _textSize; let { documentId, pageNumber, viewport } = getMetadata(svg); let scale = 1 / viewport.scale; let rect = svg.getBoundingClientRect(); let pt = convertToSvgPoint([ clientX - rect.left, clientY - rect.top + height], svg, viewport); let annotation = { type: 'textbox', size: _textSize * scale, color: _textColor, content: value, x: pt[0], y: pt[1], rotation: -viewport.rotation }; PDFJSAnnotate.getStoreAdapter().addAnnotation(documentId, pageNumber, annotation) .then((annotation) => { appendChild(svg, annotation); }); } closeInput(); } async function saveMathText () { let value = (mathField.getValue()) ? mathField.getValue() : ''; // console.log('SAVE MATH TEXT', value) if (value.length > 0) { const SVGCODE = await mathToSvg(value) // console.log('LE SCG CORE', SVGCODE) let clientX = parseInt(input.style.left, 10); let clientY = parseInt(input.style.top, 10); let svg = findSVGAtPoint(clientX, clientY); if (!svg) { return; } let height = _textSize; let { documentId, pageNumber, viewport } = getMetadata(svg); let scale = 1 / viewport.scale; let rect = svg.getBoundingClientRect(); let pt = convertToSvgPoint([ clientX - rect.left, clientY - rect.top + height], svg, viewport); let annotation = { type: 'image', size: _textSize * scale, color: _textColor, html: SVGCODE, x: pt[0], y: pt[1], rotation: -viewport.rotation }; PDFJSAnnotate.getStoreAdapter().addAnnotation(documentId, pageNumber, annotation) .then((annotation) => { appendChild(svg, annotation); }); } MathLive.renderMathInDocument(); closeMathInput(); } function mathToSvg (formula) { return new Promise((resolve, reject) => { const fixedFormula = formula.replaceAll('\\mleft', '').replaceAll('\\mright?', '').replaceAll('\\mright', '') let wrapper = window.MathJax.tex2svg(fixedFormula, { em: 10, ex: 5, display: true }) let output = { svg: "", img: "" } let mjOut = wrapper.getElementsByTagName("svg")[0] // mjOut.setAttribute("xmlns", "http://www.w3.org/2000/svg") output.svg = mjOut.outerHTML var image = new Image() image.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(output.svg))); image.onload = function () { var canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; var context = canvas.getContext('2d'); context.drawImage(image, 0, 0); output.img = canvas.toDataURL('image/png'); resolve(output.img) } image.onerror = function () { reject() } }) } /** * Close the input */ function closeInput () { if (input) { input.removeEventListener('blur', handleInputBlur); input.removeEventListener('keyup', handleInputKeyup); document.body.removeChild(input); input = null; } } function closeMathInput () { // console.log('on close') if (input) { document.body.removeChild(input); let temp = document.getElementsByClassName('ML__virtual-keyboard-toggle'); if (temp[0]) { temp[0].remove() } input = null; mathField = null; } } /** * Set the text attributes * * @param {Number} textSize The size of the text * @param {String} textColor The color of the text */ export function setText (textSize = 16, textColor = '000000') { _textSize = parseInt(textSize, 10); _textColor = textColor; } /** * Enable text behavior */ export function enableText () { if (_enabled) { return; } _enabled = true; document.addEventListener('mouseup', handleDocumentMouseup); } /** * Disable text behavior */ export function disableText (val) { if (val) { _enabled = false; document.removeEventListener('mouseup', handleDocumentMouseup); } else { if (!_enabled) { return; } _enabled = false; document.removeEventListener('mouseup', handleDocumentMouseup); } } export function enableMathText () { if (_enabled) { return; } _enabled = true; document.addEventListener('mouseup', handleDocumentMathMouseup); } export function disableMathText (val) { if (val) { _enabled = false; document.removeEventListener('mouseup', handleDocumentMathMouseup); const temp = window.document.getElementById('pdf-annotate-text-input'); if (temp) { temp.remove(); } } else { if (!_enabled) { return; } _enabled = false; document.removeEventListener('mouseup', handleDocumentMathMouseup); const temp = window.document.getElementById('pdf-annotate-text-input'); if (temp) { temp.remove(); } } }