Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Tool to display magnification of document

115 views
Skip to first unread message

Matt Parizeau

unread,
Dec 11, 2018, 5:13:39 PM12/11/18
to pdfnet-w...@googlegroups.com
Q:

How can I create a tool that display the area in the document around the mouse pointer magnified?

A:

Here is some example code that you can run inside a config file. It creates a rectangle that follows the mouse that displays the magnified area. You can tweak the magnifyZoom and magnifySize to change the properties of this magnified area.

var getAnnotCanvas = function(annotCanvas, pageIndex, zoom, rotation) {
  var docViewer = readerControl.docViewer;
  var pageData = docViewer.getDocument().getPageInfo(pageIndex);

  var page = {};
  if (rotation === 1 || rotation === 3) {
    page.width = pageData.height;
    page.height = pageData.width;
  } else {
    page.width = pageData.width;
    page.height = pageData.height;
  }

  var ctx = annotCanvas.getContext('2d');

  var t = window.GetPageMatrix(zoom, 0, page);
  ctx.setTransform(t.m_a, t.m_b, t.m_c, t.m_d, t.m_h, t.m_v);
  return docViewer.getAnnotationManager().drawAnnotations({
    pageNumber: pageIndex + 1,
    overrideCanvas: annotCanvas,
    namespace: 'magnify'
  });
}

var updateAnnotations = function(pageIndex) {
  if (!pageCanvases[pageIndex]) {
    return;
  }

  return pageCanvases[pageIndex].then(function(canvas) {
    var tempCanvas = tempCanvases[pageIndex].canvas;
    canvas.width = canvas.width;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(tempCanvas, 0, 0);

    return getAnnotCanvas(canvas, pageIndex, magnifyZoom, tempCanvases[pageIndex].rotation);
  });
};



var pageCanvases = {};
var tempCanvases = {};

var getPageCanvas = function(pageIndex) {
  if (pageCanvases[pageIndex]) {
    return pageCanvases[pageIndex];
  }

  pageCanvases[pageIndex] = new Promise(function(resolve) {
    var docViewer = readerControl.docViewer;
    var rotation = getPageRotation(pageIndex);
    var adjustmentRotation = (4 - rotation) % 4;

    var doc = docViewer.getDocument();
    doc.loadCanvasAsync({
      pageIndex: pageIndex,
      zoom: magnifyZoom,
      pageRotation: adjustmentRotation,
      drawComplete: function(canvas) {
        resolve(canvas);

        var tempCanvas = document.createElement('canvas');
        tempCanvas.width = canvas.width;
        tempCanvas.height = canvas.height;
        var tempCtx = tempCanvas.getContext('2d');
        tempCtx.drawImage(canvas, 0, 0);

        tempCanvases[pageIndex] = {
          canvas: tempCanvas,
          rotation: adjustmentRotation
        };
        updateAnnotations(pageIndex);
      }
    });
  });
  return pageCanvases[pageIndex];
};

var getPageRotation = function(pageIndex) {
  return docViewer.getCompleteRotation(pageIndex + 1) - docViewer.getRotation(pageIndex + 1)
};

var getPageCoordinate = function(mousePoint) {
  var docViewer = readerControl.docViewer;
  var displayMode = docViewer.getDisplayModeManager().getDisplayMode();

  var pageRange = displayMode.getSelectedPages(mousePoint, mousePoint);
  var pageIndex = (pageRange.first === null) ? pageRange.last : pageRange.first;
  if (pageIndex === null) {
    return null;
  }
  var pageCoordinate = displayMode.windowToPage(mousePoint, pageIndex);

  return {
    x: pageCoordinate.x,
    y: pageCoordinate.y,
    pageIndex: pageIndex
  };
};

var magnifyZoom = 2;
var magnifySize = 100;
var displayCanvas = document.createElement('canvas');
displayCanvas.width = magnifySize;
displayCanvas.height = magnifySize;
displayCanvas.style.position = 'fixed';
displayCanvas.style.pointerEvents = 'none';
displayCanvas.style.top = 0;
displayCanvas.style.left = 0;
displayCanvas.style.zIndex = 100;

var displayCtx = displayCanvas.getContext('2d');


var MagnifyTool = function() {
  Tools.Tool.apply(this, arguments);
  this.appendedElement = false;
};
MagnifyTool.prototype = new Tools.Tool();

MagnifyTool.prototype.switchIn = function() {
  displayCanvas.style.display = 'block';

  if (!this.appendedElement) {
    this.appendedElement = true;

    var documentContainer = document.querySelector('.DocumentContainer');
    documentContainer.appendChild(displayCanvas);

    documentContainer.addEventListener('mousemove', function(e) {
      // make the canvas follow the mouse cursor
      if (typeof e.clientX !== 'undefined') {
        displayCanvas.style.left = e.clientX - (magnifySize / 2) + 'px';
        displayCanvas.style.top = e.clientY - (magnifySize / 2) + 'px';
      }
    }, false);

    documentContainer.addEventListener('scroll', function(e) {
      // hide when scrolling
      displayCanvas.style.display = 'none';
    });
  }
};

MagnifyTool.prototype.switchOut = function() {
  displayCanvas.style.display = 'none';
};

MagnifyTool.prototype.mouseMove = function(e) {
  Tools.Tool.prototype.mouseMove.apply(this, arguments);

  var pageCoordinate = getPageCoordinate(this.getMouseLocation(e));

  if (pageCoordinate) {
    // position and draw magnified canvas
    getPageCanvas(pageCoordinate.pageIndex).then(function(canvas) {
      var x = Math.round(pageCoordinate.x * magnifyZoom) - (magnifySize / 2);
      var y = Math.round(pageCoordinate.y * magnifyZoom) - (magnifySize / 2);

      displayCtx.drawImage(canvas, x, y, magnifySize, magnifySize, 0, 0, magnifySize, magnifySize);
      var pageRotation = readerControl.docViewer.getCompleteRotation(pageCoordinate.pageIndex + 1) * 90;
      displayCanvas.style.transform = 'rotate(' + pageRotation + 'deg)';
      displayCanvas.style.display = 'block';
    });
  } else {
    // hide if we're outside the page
    displayCanvas.style.display = 'none';
  }
};

$(document).on('viewerLoaded', function() {
  var annotManager = readerControl.docViewer.getAnnotationManager();
  annotManager.on('annotationChanged', function(e, annotations) {
    // whenever annotations change update the canvases for the corresponding pages
    _.uniq(annotations.map(function(annot) {
      return annot['PageNumber'] - 1;
    })).forEach(function(pageIndex) {
      updateAnnotations(pageIndex);
    });
  });

  readerControl.registerTool({
    toolName: 'MagnifyTool',
    toolObject: new MagnifyTool(readerControl.docViewer),
    buttonImage: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">' +
      '<path d="M0 0h24v24H0z" fill="none"/>' +
      '<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>' +
    '</svg>',
    buttonName: 'MagnifyToolButton',
    tooltip: 'Magnify'
  });

  readerControl.setHeaderItems(function(header) {
    var magnifyToolButton = {
      type: 'toolButton',
      toolName: 'MagnifyTool'
    };
    header.get('freeHandToolGroupButton').insertBefore(magnifyToolButton);
  });
});

Reply all
Reply to author
Forward
0 new messages