From 0bc91da0bbe51ae705de041d0518df1012dbb8de Mon Sep 17 00:00:00 2001 From: zadam Date: Mon, 15 Mar 2021 22:24:56 +0100 Subject: [PATCH] added possibility to zoom into images using mousewheel --- libraries/wheel-zoom.min.js | 1 + src/public/app/services/library_loader.js | 7 ++++- src/public/app/widgets/type_widgets/image.js | 29 +++++++++++++++++--- 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 libraries/wheel-zoom.min.js diff --git a/libraries/wheel-zoom.min.js b/libraries/wheel-zoom.min.js new file mode 100644 index 000000000..ed8aff2b1 --- /dev/null +++ b/libraries/wheel-zoom.min.js @@ -0,0 +1 @@ +(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):(a="undefined"==typeof globalThis?a||self:globalThis,a.WZoom=b())})(this,function(){'use strict';var n=Math.abs;function a(a){var b=a.getBoundingClientRect(),c=document,d=c.body,e=c.documentElement,f=window.pageYOffset||e.scrollTop||d.scrollTop,g=window.pageXOffset||e.scrollLeft||d.scrollLeft,h=e.clientTop||d.clientTop||0,i=e.clientLeft||d.clientLeft||0,j=b.top+f-h,k=b.left+g-i;return{top:j,left:k}}function b(a,b){if(a&&b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function c(a,b,c){var d=!!(3=this.options.maxScale&&(this.options.minScale=null),this.window.$element=this.content.$element.parentNode,"image"===this.options.type){var f=!1;this.content.$element.complete&&(this._init(),f=!0),f&&!0!==this.options.watchImageChange||c(this.content.$element,"load",this._init,!this.options.watchImageChange&&{once:!0})}else this._init()}function k(a){a.preventDefault(),this._transform(this._computeNewPosition(this._computeNewScale(a.deltaY),{x:f(a),y:g(a)}))}function l(a){var b=this;(this.isTouch&&1===a.touches.length||1===a.buttons)&&(this.clickExpired=!1,setTimeout(function(){return b.clickExpired=!0},150))}function m(a){this.clickExpired||(this._transform(this._computeNewPosition(1===this.direction?this.content.maxScale:this.content.minScale,{x:f(a),y:g(a)})),this.direction*=-1)}return h.prototype={constructor:h,window:null,content:null,isTouch:!1,isGrab:!1,events:null,moveTimer:null,options:{},coordinates:null,speed:null,_grabHandler:function(a){(this.isTouch&&1===a.touches.length||1===a.buttons)&&(!this.isTouch&&a.preventDefault(),this.isGrab=!0,this.coordinates={left:f(a),top:g(a)},this.speed={x:0,y:0},c(document,this.events.drop,this._dropHandler,this.events.options),c(document,this.events.move,this._moveHandler,this.events.options),"function"==typeof this.options.onGrab&&this.options.onGrab())},_dropHandler:function(a){this.isTouch||a.preventDefault(),this.isGrab=!1,d(document,this.events.drop,this._dropHandler),d(document,this.events.move,this._moveHandler),"function"==typeof this.options.onDrop&&this.options.onDrop()},_moveHandler:function(a){this.isTouch||a.preventDefault();var b=this.window,c=this.content,d=this.speed,e=this.coordinates,h=this.options;d.x=f(a)-e.left,d.y=g(a)-e.top,clearTimeout(this.moveTimer),this.moveTimer=setTimeout(function(){d.x=0,d.y=0},50);var j=c.currentLeft+d.x,k=c.currentTop+d.y,l=(c.currentWidth-b.originalWidth)/2+c.correctX,m=(c.currentHeight-b.originalHeight)/2+c.correctY;n(j)<=l&&(c.currentLeft=j),n(k)<=m&&(c.currentTop=k),i(c.$element,{left:c.currentLeft,top:c.currentTop,scale:c.currentScale}),e.left=f(a),e.top=g(a),"function"==typeof h.onMove&&h.onMove()},destroy:function(){for(var a in d(this.content.$element,this.events.grab,this._grabHandler,this.events.options),this)this.hasOwnProperty(a)&&(this[a]=null)}},j.prototype={constructor:j,_init:function(){this._prepare(),!0===this.options.dragScrollable&&(this.dragScrollable&&this.dragScrollable.destroy(),this.dragScrollable=new h(this.window,this.content,this.options.dragScrollableOptions)),c(this.content.$element,"wheel",this._wheelHandler),this.options.zoomOnClick&&(c(this.content.$element,this.events.down,this._downHandler,this.events.options),c(this.content.$element,this.events.up,this._upHandler,this.events.options))},_prepare:function(){var b=Math.max,c=Math.min,d=a(this.window.$element);this.window.originalWidth=this.window.$element.offsetWidth,this.window.originalHeight=this.window.$element.offsetHeight,this.window.positionLeft=d.left,this.window.positionTop=d.top,"image"===this.options.type?(this.content.originalWidth=this.options.width||this.content.$element.naturalWidth,this.content.originalHeight=this.options.height||this.content.$element.naturalHeight):(this.content.originalWidth=this.options.width||this.content.$element.offsetWidth,this.content.originalHeight=this.options.height||this.content.$element.offsetHeight),this.content.minScale=this.options.minScale||c(this.window.originalWidth/this.content.originalWidth,this.window.originalHeight/this.content.originalHeight),this.content.maxScale=this.options.maxScale,this.content.currentWidth=this.content.originalWidth*this.content.minScale,this.content.currentHeight=this.content.originalHeight*this.content.minScale,this.content.currentLeft=0,this.content.currentTop=0,this.content.currentScale=this.content.minScale,this.content.correctX=b(0,(this.window.originalWidth-this.content.currentWidth)/2),this.content.correctY=b(0,(this.window.originalHeight-this.content.currentHeight)/2),this.content.$element.style.transform="translate3d(0px, 0px, 0px) scale(".concat(this.content.minScale,")"),"function"==typeof this.options.prepare&&this.options.prepare()},_computeNewScale:function(a){this.direction=0>a?1:-1;var b=this.content,c=b.minScale,d=b.maxScale,e=b.currentScale,f=e+this.direction/this.options.speed;return fd&&(this.direction=-1),fd?d:f},_computeNewPosition:function(a,b){var c=b.x,d=b.y,e=this.window,f=this.content,g=f.originalWidth*a,h=f.originalHeight*a,i=document,j=i.body,k=i.documentElement,l=e.pageXOffset||k.scrollLeft||j.scrollLeft,m=e.pageYOffset||k.scrollTop||j.scrollTop,o=c+l-e.positionLeft,p=e.originalWidth/2-o,q=p+f.currentLeft,r=q*(g/f.currentWidth)-q+f.currentLeft;if(-1===this.direction&&(g-e.originalWidth)/2+f.correctXr?-1:1;r=((g-e.originalWidth)/2+f.correctX)*s}var t=d+m-e.positionTop,u=e.originalHeight/2-t,v=u+f.currentTop,w=v*(h/f.currentHeight)-v+f.currentTop;if(-1===this.direction&&(h-e.originalHeight)/2+f.correctYw?-1:1;w=((h-e.originalHeight)/2+f.correctY)*x}a===this.content.minScale&&(r=w=0);var y={currentLeft:f.currentLeft,newLeft:r,currentTop:f.currentTop,newTop:w,currentScale:f.currentScale,newScale:a};return f.currentWidth=g,f.currentHeight=h,f.currentLeft=r,f.currentTop=w,f.currentScale=a,y},_transform:function(a){a.currentLeft;var b=a.newLeft;a.currentTop;var c=a.newTop;a.currentScale;var d=a.newScale;this.content.$element.style.transform="translate3d(".concat(b,"px, ").concat(c,"px, 0px) scale(").concat(d,")"),"function"==typeof this.options.rescale&&this.options.rescale()},_zoom:function(b){var c=a(this.window.$element),d=this.window,e=document,f=e.body,g=e.documentElement,h=d.pageXOffset||g.scrollLeft||f.scrollLeft,i=d.pageYOffset||g.scrollTop||f.scrollTop;this._transform(this._computeNewPosition(this._computeNewScale(b),{x:c.left+this.window.originalWidth/2-h,y:c.top+this.window.originalHeight/2-i}))},prepare:function(){this._prepare()},zoomUp:function(){this._zoom(-1)},zoomDown:function(){this._zoom(1)},destroy:function(){for(var a in this.content.$element.style.transform="","image"===this.options.type&&d(this.content.$element,"load",this._init),d(this.window.$element,"wheel",this._wheelHandler),this.options.zoomOnClick&&(d(this.window.$element,this.events.down,this._downHandler,this.events.options),d(this.window.$element,this.events.up,this._upHandler,this.events.options)),this.dragScrollable&&this.dragScrollable.destroy(),this)this.hasOwnProperty(a)&&(this[a]=null)}},j.create=function(a,b){return new j(a,b)},j}); diff --git a/src/public/app/services/library_loader.js b/src/public/app/services/library_loader.js index bb276ac97..28bd7c18a 100644 --- a/src/public/app/services/library_loader.js +++ b/src/public/app/services/library_loader.js @@ -53,6 +53,10 @@ const KATEX = { css: [ "libraries/katex/katex.min.css" ] }; +const WHEEL_ZOOM = { + js: [ "libraries/wheel-zoom.min.js"] +}; + async function requireLibrary(library) { if (library.css) { library.css.map(cssUrl => requireCss(cssUrl)); @@ -101,5 +105,6 @@ export default { LINK_MAP, PRINT_THIS, CALENDAR_WIDGET, - KATEX + KATEX, + WHEEL_ZOOM } diff --git a/src/public/app/widgets/type_widgets/image.js b/src/public/app/widgets/type_widgets/image.js index 86d667bb1..bbd98fc45 100644 --- a/src/public/app/widgets/type_widgets/image.js +++ b/src/public/app/widgets/type_widgets/image.js @@ -1,6 +1,7 @@ import utils from "../../services/utils.js"; import toastService from "../../services/toast.js"; import TypeWidget from "./type_widget.js"; +import libraryLoader from "../../services/library_loader.js"; const TPL = `
@@ -10,13 +11,25 @@ const TPL = ` } .note-detail-image { - text-align: center; + height: 100%; + } + + .note-detail-image-wrapper { + position: relative; + display: flex; + align-items: center; + width: 100%; height: 100%; - overflow: auto; + overflow: hidden; + justify-content: center; } .note-detail-image-view { - max-width: 100%; + display: block; + width: auto; + height: auto; + align-self: center; + flex-shrink: 0; } @@ -32,7 +45,15 @@ class ImageTypeWidget extends TypeWidget { this.$widget = $(TPL); this.contentSized(); this.$imageWrapper = this.$widget.find('.note-detail-image-wrapper'); - this.$imageView = this.$widget.find('.note-detail-image-view'); + this.$imageView = this.$widget.find('.note-detail-image-view') + .attr("id", "image-view-" + utils.randomString(10)); + + libraryLoader.requireLibrary(libraryLoader.WHEEL_ZOOM).then(() => { + WZoom.create('#' + this.$imageView.attr("id"), { + maxScale: 10, + zoomOnClick: false + }); + }); } async doRefresh(note) {