vue-zoomer
Advanced tools
Comparing version 0.3.9 to 0.3.10
@@ -1,385 +0,8 @@ | ||
// vue-zoomer v0.3.9 - Jarvis Niu | ||
// vue-zoomer v0.3.10 - Jarvis Niu | ||
// https://github.com/jarvisniu/vue-zoomer | ||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
/* esm.sh - esbuild bundle(lodash@4.17.20/debounce) esnext production */ | ||
if (typeof global === "undefined") var global = window;var ce=Object.create,S=Object.defineProperty,se=Object.getPrototypeOf,ue=Object.prototype.hasOwnProperty,be=Object.getOwnPropertyNames,le=Object.getOwnPropertyDescriptor,ge=e=>S(e,"__esModule",{value:!0}),a=(e,r)=>()=>(r||(r={exports:{}},e(r.exports,r)),r.exports),de=(e,r,n)=>{if(ge(e),r&&typeof r=="object"||typeof r=="function")for(let i of be(r))!ue.call(e,i)&&i!=="default"&&S(e,i,{get:()=>r[i],enumerable:!(n=le(r,i))||n.enumerable});return e},me=e=>e&&e.__esModule?e:de(S(e!=null?ce(se(e)):{},"default",{value:e,enumerable:!0}),e),x=a((rr,E)=>{function pe(e){var r=typeof e;return e!=null&&(r=="object"||r=="function")}E.exports=pe;}),N=a((tr,L)=>{var ye=typeof global=="object"&&global&&global.Object===Object&&global;L.exports=ye;}),O=a((nr,G)=>{var Te=N(),je=typeof self=="object"&&self&&self.Object===Object&&self,Se=Te||je||Function("return this")();G.exports=Se;}),w=a((ir,R)=>{var xe=O(),Oe=function(){return xe.Date.now()};R.exports=Oe;}),v=a((or,P)=>{var ve=O(),qe=ve.Symbol;P.exports=qe;}),$=a((ar,W)=>{var C=v(),M=Object.prototype,he=M.hasOwnProperty,Ie=M.toString,m=C?C.toStringTag:void 0;function _e(e){var r=he.call(e,m),n=e[m];try{e[m]=void 0;var i=!0;}catch(b){}var c=Ie.call(e);return i&&(r?e[m]=n:delete e[m]),c}W.exports=_e;}),B=a((fr,A)=>{var ke=Object.prototype,Ee=ke.toString;function Le(e){return Ee.call(e)}A.exports=Le;}),H=a((cr,F)=>{var U=v(),Ne=$(),Ge=B(),Re="[object Null]",we="[object Undefined]",D=U?U.toStringTag:void 0;function Pe(e){return e==null?e===void 0?we:Re:D&&D in Object(e)?Ne(e):Ge(e)}F.exports=Pe;}),z=a((sr,X)=>{function We(e){return e!=null&&typeof e=="object"}X.exports=We;}),K=a((ur,J)=>{var Ce=H(),Me=z(),$e="[object Symbol]";function Ae(e){return typeof e=="symbol"||Me(e)&&Ce(e)==$e}J.exports=Ae;}),Z=a((br,Q)=>{var V=x(),Be=K(),Y=0/0,Fe=/^\s+|\s+$/g,Ue=/^[-+]0x[0-9a-f]+$/i,De=/^0b[01]+$/i,He=/^0o[0-7]+$/i,Xe=parseInt;function ze(e){if(typeof e=="number")return e;if(Be(e))return Y;if(V(e)){var r=typeof e.valueOf=="function"?e.valueOf():e;e=V(r)?r+"":r;}if(typeof e!="string")return e===0?e:+e;e=e.replace(Fe,"");var n=De.test(e);return n||He.test(e)?Xe(e.slice(2),n?2:8):Ue.test(e)?Y:+e}Q.exports=ze;}),te=a((lr,ee)=>{var Je=x(),q=w(),re=Z(),Ke="Expected a function",Qe=Math.max,Ve=Math.min;function Ye(e,r,n){var i,c,b,u,o,s,l=0,h=!1,g=!1,y=!0;if(typeof e!="function")throw new TypeError(Ke);r=re(r)||0,Je(n)&&(h=!!n.leading,g="maxWait"in n,b=g?Qe(re(n.maxWait)||0,r):b,y="trailing"in n?!!n.trailing:y);function T(t){var f=i,d=c;return i=c=void 0,l=t,u=e.apply(d,f),u}function ie(t){return l=t,o=setTimeout(p,r),h?T(t):u}function oe(t){var f=t-s,d=t-l,k=r-f;return g?Ve(k,b-d):k}function I(t){var f=t-s,d=t-l;return s===void 0||f>=r||f<0||g&&d>=b}function p(){var t=q();if(I(t))return _(t);o=setTimeout(p,oe(t));}function _(t){return o=void 0,y&&i?T(t):(i=c=void 0,u)}function ae(){o!==void 0&&clearTimeout(o),l=0,i=s=c=o=void 0;}function fe(){return o===void 0?u:_(q())}function j(){var t=q(),f=I(t);if(i=arguments,c=this,s=t,f){if(o===void 0)return ie(s);if(g)return clearTimeout(o),o=setTimeout(p,r),T(s)}return o===void 0&&(o=setTimeout(p,r)),u}return j.cancel=ae,j.flush=fe,j}ee.exports=Ye;}),ne=me(te()),Ze=ne.default; | ||
/** | ||
* lodash (Custom Build) <https://lodash.com/> | ||
* Build: `lodash modularize exports="npm" -o ./` | ||
* Copyright jQuery Foundation and other contributors <https://jquery.org/> | ||
* Released under MIT license <https://lodash.com/license> | ||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> | ||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors | ||
*/ | ||
/** Used as the `TypeError` message for "Functions" methods. */ | ||
var FUNC_ERROR_TEXT = 'Expected a function'; | ||
/** Used as references for various `Number` constants. */ | ||
var NAN = 0 / 0; | ||
/** `Object#toString` result references. */ | ||
var symbolTag = '[object Symbol]'; | ||
/** Used to match leading and trailing whitespace. */ | ||
var reTrim = /^\s+|\s+$/g; | ||
/** Used to detect bad signed hexadecimal string values. */ | ||
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; | ||
/** Used to detect binary string values. */ | ||
var reIsBinary = /^0b[01]+$/i; | ||
/** Used to detect octal string values. */ | ||
var reIsOctal = /^0o[0-7]+$/i; | ||
/** Built-in method references without a dependency on `root`. */ | ||
var freeParseInt = parseInt; | ||
/** Detect free variable `global` from Node.js. */ | ||
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; | ||
/** Detect free variable `self`. */ | ||
var freeSelf = typeof self == 'object' && self && self.Object === Object && self; | ||
/** Used as a reference to the global object. */ | ||
var root = freeGlobal || freeSelf || Function('return this')(); | ||
/** Used for built-in method references. */ | ||
var objectProto = Object.prototype; | ||
/** | ||
* Used to resolve the | ||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) | ||
* of values. | ||
*/ | ||
var objectToString = objectProto.toString; | ||
/* Built-in method references for those with the same name as other `lodash` methods. */ | ||
var nativeMax = Math.max, | ||
nativeMin = Math.min; | ||
/** | ||
* Gets the timestamp of the number of milliseconds that have elapsed since | ||
* the Unix epoch (1 January 1970 00:00:00 UTC). | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 2.4.0 | ||
* @category Date | ||
* @returns {number} Returns the timestamp. | ||
* @example | ||
* | ||
* _.defer(function(stamp) { | ||
* console.log(_.now() - stamp); | ||
* }, _.now()); | ||
* // => Logs the number of milliseconds it took for the deferred invocation. | ||
*/ | ||
var now = function() { | ||
return root.Date.now(); | ||
}; | ||
/** | ||
* Creates a debounced function that delays invoking `func` until after `wait` | ||
* milliseconds have elapsed since the last time the debounced function was | ||
* invoked. The debounced function comes with a `cancel` method to cancel | ||
* delayed `func` invocations and a `flush` method to immediately invoke them. | ||
* Provide `options` to indicate whether `func` should be invoked on the | ||
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked | ||
* with the last arguments provided to the debounced function. Subsequent | ||
* calls to the debounced function return the result of the last `func` | ||
* invocation. | ||
* | ||
* **Note:** If `leading` and `trailing` options are `true`, `func` is | ||
* invoked on the trailing edge of the timeout only if the debounced function | ||
* is invoked more than once during the `wait` timeout. | ||
* | ||
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred | ||
* until to the next tick, similar to `setTimeout` with a timeout of `0`. | ||
* | ||
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) | ||
* for details over the differences between `_.debounce` and `_.throttle`. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 0.1.0 | ||
* @category Function | ||
* @param {Function} func The function to debounce. | ||
* @param {number} [wait=0] The number of milliseconds to delay. | ||
* @param {Object} [options={}] The options object. | ||
* @param {boolean} [options.leading=false] | ||
* Specify invoking on the leading edge of the timeout. | ||
* @param {number} [options.maxWait] | ||
* The maximum time `func` is allowed to be delayed before it's invoked. | ||
* @param {boolean} [options.trailing=true] | ||
* Specify invoking on the trailing edge of the timeout. | ||
* @returns {Function} Returns the new debounced function. | ||
* @example | ||
* | ||
* // Avoid costly calculations while the window size is in flux. | ||
* jQuery(window).on('resize', _.debounce(calculateLayout, 150)); | ||
* | ||
* // Invoke `sendMail` when clicked, debouncing subsequent calls. | ||
* jQuery(element).on('click', _.debounce(sendMail, 300, { | ||
* 'leading': true, | ||
* 'trailing': false | ||
* })); | ||
* | ||
* // Ensure `batchLog` is invoked once after 1 second of debounced calls. | ||
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); | ||
* var source = new EventSource('/stream'); | ||
* jQuery(source).on('message', debounced); | ||
* | ||
* // Cancel the trailing debounced invocation. | ||
* jQuery(window).on('popstate', debounced.cancel); | ||
*/ | ||
function debounce(func, wait, options) { | ||
var lastArgs, | ||
lastThis, | ||
maxWait, | ||
result, | ||
timerId, | ||
lastCallTime, | ||
lastInvokeTime = 0, | ||
leading = false, | ||
maxing = false, | ||
trailing = true; | ||
if (typeof func != 'function') { | ||
throw new TypeError(FUNC_ERROR_TEXT); | ||
} | ||
wait = toNumber(wait) || 0; | ||
if (isObject(options)) { | ||
leading = !!options.leading; | ||
maxing = 'maxWait' in options; | ||
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; | ||
trailing = 'trailing' in options ? !!options.trailing : trailing; | ||
} | ||
function invokeFunc(time) { | ||
var args = lastArgs, | ||
thisArg = lastThis; | ||
lastArgs = lastThis = undefined; | ||
lastInvokeTime = time; | ||
result = func.apply(thisArg, args); | ||
return result; | ||
} | ||
function leadingEdge(time) { | ||
// Reset any `maxWait` timer. | ||
lastInvokeTime = time; | ||
// Start the timer for the trailing edge. | ||
timerId = setTimeout(timerExpired, wait); | ||
// Invoke the leading edge. | ||
return leading ? invokeFunc(time) : result; | ||
} | ||
function remainingWait(time) { | ||
var timeSinceLastCall = time - lastCallTime, | ||
timeSinceLastInvoke = time - lastInvokeTime, | ||
result = wait - timeSinceLastCall; | ||
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; | ||
} | ||
function shouldInvoke(time) { | ||
var timeSinceLastCall = time - lastCallTime, | ||
timeSinceLastInvoke = time - lastInvokeTime; | ||
// Either this is the first call, activity has stopped and we're at the | ||
// trailing edge, the system time has gone backwards and we're treating | ||
// it as the trailing edge, or we've hit the `maxWait` limit. | ||
return (lastCallTime === undefined || (timeSinceLastCall >= wait) || | ||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); | ||
} | ||
function timerExpired() { | ||
var time = now(); | ||
if (shouldInvoke(time)) { | ||
return trailingEdge(time); | ||
} | ||
// Restart the timer. | ||
timerId = setTimeout(timerExpired, remainingWait(time)); | ||
} | ||
function trailingEdge(time) { | ||
timerId = undefined; | ||
// Only invoke if we have `lastArgs` which means `func` has been | ||
// debounced at least once. | ||
if (trailing && lastArgs) { | ||
return invokeFunc(time); | ||
} | ||
lastArgs = lastThis = undefined; | ||
return result; | ||
} | ||
function cancel() { | ||
if (timerId !== undefined) { | ||
clearTimeout(timerId); | ||
} | ||
lastInvokeTime = 0; | ||
lastArgs = lastCallTime = lastThis = timerId = undefined; | ||
} | ||
function flush() { | ||
return timerId === undefined ? result : trailingEdge(now()); | ||
} | ||
function debounced() { | ||
var time = now(), | ||
isInvoking = shouldInvoke(time); | ||
lastArgs = arguments; | ||
lastThis = this; | ||
lastCallTime = time; | ||
if (isInvoking) { | ||
if (timerId === undefined) { | ||
return leadingEdge(lastCallTime); | ||
} | ||
if (maxing) { | ||
// Handle invocations in a tight loop. | ||
timerId = setTimeout(timerExpired, wait); | ||
return invokeFunc(lastCallTime); | ||
} | ||
} | ||
if (timerId === undefined) { | ||
timerId = setTimeout(timerExpired, wait); | ||
} | ||
return result; | ||
} | ||
debounced.cancel = cancel; | ||
debounced.flush = flush; | ||
return debounced; | ||
} | ||
/** | ||
* Checks if `value` is the | ||
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) | ||
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 0.1.0 | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is an object, else `false`. | ||
* @example | ||
* | ||
* _.isObject({}); | ||
* // => true | ||
* | ||
* _.isObject([1, 2, 3]); | ||
* // => true | ||
* | ||
* _.isObject(_.noop); | ||
* // => true | ||
* | ||
* _.isObject(null); | ||
* // => false | ||
*/ | ||
function isObject(value) { | ||
var type = typeof value; | ||
return !!value && (type == 'object' || type == 'function'); | ||
} | ||
/** | ||
* Checks if `value` is object-like. A value is object-like if it's not `null` | ||
* and has a `typeof` result of "object". | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 4.0.0 | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`. | ||
* @example | ||
* | ||
* _.isObjectLike({}); | ||
* // => true | ||
* | ||
* _.isObjectLike([1, 2, 3]); | ||
* // => true | ||
* | ||
* _.isObjectLike(_.noop); | ||
* // => false | ||
* | ||
* _.isObjectLike(null); | ||
* // => false | ||
*/ | ||
function isObjectLike(value) { | ||
return !!value && typeof value == 'object'; | ||
} | ||
/** | ||
* Checks if `value` is classified as a `Symbol` primitive or object. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 4.0.0 | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`. | ||
* @example | ||
* | ||
* _.isSymbol(Symbol.iterator); | ||
* // => true | ||
* | ||
* _.isSymbol('abc'); | ||
* // => false | ||
*/ | ||
function isSymbol(value) { | ||
return typeof value == 'symbol' || | ||
(isObjectLike(value) && objectToString.call(value) == symbolTag); | ||
} | ||
/** | ||
* Converts `value` to a number. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 4.0.0 | ||
* @category Lang | ||
* @param {*} value The value to process. | ||
* @returns {number} Returns the number. | ||
* @example | ||
* | ||
* _.toNumber(3.2); | ||
* // => 3.2 | ||
* | ||
* _.toNumber(Number.MIN_VALUE); | ||
* // => 5e-324 | ||
* | ||
* _.toNumber(Infinity); | ||
* // => Infinity | ||
* | ||
* _.toNumber('3.2'); | ||
* // => 3.2 | ||
*/ | ||
function toNumber(value) { | ||
if (typeof value == 'number') { | ||
return value; | ||
} | ||
if (isSymbol(value)) { | ||
return NAN; | ||
} | ||
if (isObject(value)) { | ||
var other = typeof value.valueOf == 'function' ? value.valueOf() : value; | ||
value = isObject(other) ? (other + '') : other; | ||
} | ||
if (typeof value != 'string') { | ||
return value === 0 ? value : +value; | ||
} | ||
value = value.replace(reTrim, ''); | ||
var isBinary = reIsBinary.test(value); | ||
return (isBinary || reIsOctal.test(value)) | ||
? freeParseInt(value.slice(2), isBinary ? 2 : 8) | ||
: (reIsBadHex.test(value) ? NAN : +value); | ||
} | ||
var lodash_debounce = debounce; | ||
/** | ||
* Detect double tap events | ||
@@ -684,3 +307,3 @@ * # Deals with: | ||
}, | ||
onInteractionEnd: lodash_debounce(function () { | ||
onInteractionEnd: Ze(function () { | ||
this.limit(); | ||
@@ -878,142 +501,130 @@ this.panLocked = this.scale === 1; | ||
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier | ||
/* server only */ | ||
, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { | ||
if (typeof shadowMode !== 'boolean') { | ||
createInjectorSSR = createInjector; | ||
createInjector = shadowMode; | ||
shadowMode = false; | ||
} // Vue.extend constructor export interop. | ||
var options = typeof script === 'function' ? script.options : script; // render functions | ||
if (template && template.render) { | ||
options.render = template.render; | ||
options.staticRenderFns = template.staticRenderFns; | ||
options._compiled = true; // functional template | ||
if (isFunctionalTemplate) { | ||
options.functional = true; | ||
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { | ||
if (typeof shadowMode !== 'boolean') { | ||
createInjectorSSR = createInjector; | ||
createInjector = shadowMode; | ||
shadowMode = false; | ||
} | ||
} // scopedId | ||
if (scopeId) { | ||
options._scopeId = scopeId; | ||
} | ||
var hook; | ||
if (moduleIdentifier) { | ||
// server build | ||
hook = function hook(context) { | ||
// 2.3 injection | ||
context = context || // cached call | ||
this.$vnode && this.$vnode.ssrContext || // stateful | ||
this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional | ||
// 2.2 with runInNewContext: true | ||
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { | ||
context = __VUE_SSR_CONTEXT__; | ||
} // inject component styles | ||
if (style) { | ||
style.call(this, createInjectorSSR(context)); | ||
} // register component module identifier for async chunk inference | ||
if (context && context._registeredComponents) { | ||
context._registeredComponents.add(moduleIdentifier); | ||
} | ||
}; // used by ssr in case component is cached and beforeCreate | ||
// never gets called | ||
options._ssrRegister = hook; | ||
} else if (style) { | ||
hook = shadowMode ? function () { | ||
style.call(this, createInjectorShadow(this.$root.$options.shadowRoot)); | ||
} : function (context) { | ||
style.call(this, createInjector(context)); | ||
}; | ||
} | ||
if (hook) { | ||
if (options.functional) { | ||
// register for functional component in vue file | ||
var originalRender = options.render; | ||
options.render = function renderWithStyleInjection(h, context) { | ||
hook.call(context); | ||
return originalRender(h, context); | ||
}; | ||
} else { | ||
// inject component registration as beforeCreate hook | ||
var existing = options.beforeCreate; | ||
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; | ||
// Vue.extend constructor export interop. | ||
const options = typeof script === 'function' ? script.options : script; | ||
// render functions | ||
if (template && template.render) { | ||
options.render = template.render; | ||
options.staticRenderFns = template.staticRenderFns; | ||
options._compiled = true; | ||
// functional template | ||
if (isFunctionalTemplate) { | ||
options.functional = true; | ||
} | ||
} | ||
} | ||
return script; | ||
// scopedId | ||
if (scopeId) { | ||
options._scopeId = scopeId; | ||
} | ||
let hook; | ||
if (moduleIdentifier) { | ||
// server build | ||
hook = function (context) { | ||
// 2.3 injection | ||
context = | ||
context || // cached call | ||
(this.$vnode && this.$vnode.ssrContext) || // stateful | ||
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional | ||
// 2.2 with runInNewContext: true | ||
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { | ||
context = __VUE_SSR_CONTEXT__; | ||
} | ||
// inject component styles | ||
if (style) { | ||
style.call(this, createInjectorSSR(context)); | ||
} | ||
// register component module identifier for async chunk inference | ||
if (context && context._registeredComponents) { | ||
context._registeredComponents.add(moduleIdentifier); | ||
} | ||
}; | ||
// used by ssr in case component is cached and beforeCreate | ||
// never gets called | ||
options._ssrRegister = hook; | ||
} | ||
else if (style) { | ||
hook = shadowMode | ||
? function (context) { | ||
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); | ||
} | ||
: function (context) { | ||
style.call(this, createInjector(context)); | ||
}; | ||
} | ||
if (hook) { | ||
if (options.functional) { | ||
// register for functional component in vue file | ||
const originalRender = options.render; | ||
options.render = function renderWithStyleInjection(h, context) { | ||
hook.call(context); | ||
return originalRender(h, context); | ||
}; | ||
} | ||
else { | ||
// inject component registration as beforeCreate hook | ||
const existing = options.beforeCreate; | ||
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; | ||
} | ||
} | ||
return script; | ||
} | ||
var normalizeComponent_1 = normalizeComponent; | ||
var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); | ||
const isOldIE = typeof navigator !== 'undefined' && | ||
/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); | ||
function createInjector(context) { | ||
return function (id, style) { | ||
return addStyle(id, style); | ||
}; | ||
return (id, style) => addStyle(id, style); | ||
} | ||
var HEAD; | ||
var styles = {}; | ||
let HEAD; | ||
const styles = {}; | ||
function addStyle(id, css) { | ||
var group = isOldIE ? css.media || 'default' : id; | ||
var style = styles[group] || (styles[group] = { | ||
ids: new Set(), | ||
styles: [] | ||
}); | ||
if (!style.ids.has(id)) { | ||
style.ids.add(id); | ||
var code = css.source; | ||
if (css.map) { | ||
// https://developer.chrome.com/devtools/docs/javascript-debugging | ||
// this makes source maps inside style tags work properly in Chrome | ||
code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 | ||
code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; | ||
const group = isOldIE ? css.media || 'default' : id; | ||
const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] }); | ||
if (!style.ids.has(id)) { | ||
style.ids.add(id); | ||
let code = css.source; | ||
if (css.map) { | ||
// https://developer.chrome.com/devtools/docs/javascript-debugging | ||
// this makes source maps inside style tags work properly in Chrome | ||
code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; | ||
// http://stackoverflow.com/a/26603875 | ||
code += | ||
'\n/*# sourceMappingURL=data:application/json;base64,' + | ||
btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + | ||
' */'; | ||
} | ||
if (!style.element) { | ||
style.element = document.createElement('style'); | ||
style.element.type = 'text/css'; | ||
if (css.media) | ||
style.element.setAttribute('media', css.media); | ||
if (HEAD === undefined) { | ||
HEAD = document.head || document.getElementsByTagName('head')[0]; | ||
} | ||
HEAD.appendChild(style.element); | ||
} | ||
if ('styleSheet' in style.element) { | ||
style.styles.push(code); | ||
style.element.styleSheet.cssText = style.styles | ||
.filter(Boolean) | ||
.join('\n'); | ||
} | ||
else { | ||
const index = style.ids.size - 1; | ||
const textNode = document.createTextNode(code); | ||
const nodes = style.element.childNodes; | ||
if (nodes[index]) | ||
style.element.removeChild(nodes[index]); | ||
if (nodes.length) | ||
style.element.insertBefore(textNode, nodes[index]); | ||
else | ||
style.element.appendChild(textNode); | ||
} | ||
} | ||
if (!style.element) { | ||
style.element = document.createElement('style'); | ||
style.element.type = 'text/css'; | ||
if (css.media) style.element.setAttribute('media', css.media); | ||
if (HEAD === undefined) { | ||
HEAD = document.head || document.getElementsByTagName('head')[0]; | ||
} | ||
HEAD.appendChild(style.element); | ||
} | ||
if ('styleSheet' in style.element) { | ||
style.styles.push(code); | ||
style.element.styleSheet.cssText = style.styles.filter(Boolean).join('\n'); | ||
} else { | ||
var index = style.ids.size - 1; | ||
var textNode = document.createTextNode(code); | ||
var nodes = style.element.childNodes; | ||
if (nodes[index]) style.element.removeChild(nodes[index]); | ||
if (nodes.length) style.element.insertBefore(textNode, nodes[index]);else style.element.appendChild(textNode); | ||
} | ||
} | ||
} | ||
var browser = createInjector; | ||
/* script */ | ||
@@ -1023,3 +634,3 @@ const __vue_script__ = script; | ||
/* template */ | ||
var __vue_render__ = function() { | ||
var __vue_render__ = function () { | ||
var _vm = this; | ||
@@ -1042,4 +653,4 @@ var _h = _vm.$createElement; | ||
touchend: _vm.onTouchEnd, | ||
touchmove: _vm.onTouchMove | ||
} | ||
touchmove: _vm.onTouchMove, | ||
}, | ||
}, | ||
@@ -1052,3 +663,3 @@ [ | ||
2 | ||
) | ||
), | ||
] | ||
@@ -1063,7 +674,7 @@ ) | ||
if (!inject) return | ||
inject("data-v-33e6a267_0", { source: ".vue-zoomer[data-v-33e6a267] {\n overflow: hidden;\n}\n.zoomer[data-v-33e6a267] {\n transform-origin: 50% 50%;\n width: 100%;\n height: 100%;\n}\n.zoomer > img[data-v-33e6a267] {\n vertical-align: top;\n user-drag: none;\n -webkit-user-drag: none;\n -moz-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
inject("data-v-e532c06e_0", { source: "\n.vue-zoomer[data-v-e532c06e] {\n overflow: hidden;\n}\n.zoomer[data-v-e532c06e] {\n transform-origin: 50% 50%;\n width: 100%;\n height: 100%;\n}\n.zoomer > img[data-v-e532c06e] {\n /* remove the 4px gap below the image */\n vertical-align: top;\n user-drag: none;\n -webkit-user-drag: none;\n -moz-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
}; | ||
/* scoped */ | ||
const __vue_scope_id__ = "data-v-33e6a267"; | ||
const __vue_scope_id__ = "data-v-e532c06e"; | ||
/* module identifier */ | ||
@@ -1079,3 +690,3 @@ const __vue_module_identifier__ = undefined; | ||
const __vue_component__ = /*#__PURE__*/normalizeComponent_1( | ||
const __vue_component__ = /*#__PURE__*/normalizeComponent( | ||
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, | ||
@@ -1088,3 +699,3 @@ __vue_inject_styles__, | ||
false, | ||
browser, | ||
createInjector, | ||
undefined, | ||
@@ -1325,3 +936,3 @@ undefined | ||
/* template */ | ||
var __vue_render__$1 = function() { | ||
var __vue_render__$1 = function () { | ||
var _vm = this; | ||
@@ -1335,6 +946,6 @@ var _h = _vm.$createElement; | ||
class: { | ||
anim: _vm.autoSliding && !_vm.isPointerDown | ||
anim: _vm.autoSliding && !_vm.isPointerDown, | ||
}, | ||
style: { | ||
"background-color": _vm.backgroundColor | ||
"background-color": _vm.backgroundColor, | ||
}, | ||
@@ -1348,9 +959,9 @@ on: { | ||
touchend: _vm.onTouchEnd, | ||
touchmove: function($event) { | ||
touchmove: function ($event) { | ||
$event.preventDefault(); | ||
return _vm.onTouchMove($event) | ||
} | ||
} | ||
return _vm.onTouchMove.apply(null, arguments) | ||
}, | ||
}, | ||
}, | ||
_vm._l(3, function(n, i) { | ||
_vm._l(3, function (n, i) { | ||
return _c( | ||
@@ -1374,10 +985,10 @@ "v-zoomer", | ||
"double-click-to-zoom": _vm.doubleClickToZoom, | ||
"mouse-wheel-to-zoom": _vm.mouseWheelToZoom | ||
"mouse-wheel-to-zoom": _vm.mouseWheelToZoom, | ||
}, | ||
on: { | ||
"update:zoomed": function($event) { | ||
"update:zoomed": function ($event) { | ||
_vm.currentZoomed = $event; | ||
}, | ||
swipe: _vm.onImageSwipe | ||
} | ||
swipe: _vm.onImageSwipe, | ||
}, | ||
}, | ||
@@ -1390,16 +1001,16 @@ [ | ||
width: "100%", | ||
height: "100%" | ||
height: "100%", | ||
}, | ||
attrs: { | ||
src: _vm.list[_vm.selIndex + i - 1], | ||
draggable: "false" | ||
draggable: "false", | ||
}, | ||
on: { | ||
load: function($event) { | ||
load: function ($event) { | ||
return _vm.onImageLoad(_vm.selIndex + i - 1, $event) | ||
}, | ||
dragstart: _vm.onImageDragStart | ||
} | ||
dragstart: _vm.onImageDragStart, | ||
}, | ||
}) | ||
: _vm._e() | ||
: _vm._e(), | ||
] | ||
@@ -1417,7 +1028,7 @@ ) | ||
if (!inject) return | ||
inject("data-v-ea62d372_0", { source: ".vue-zoomer-gallery[data-v-ea62d372] {\n position: relative;\n overflow: hidden;\n user-select: none;\n min-width: 100px;\n min-height: 100px;\n}\n.vue-zoomer-gallery > *[data-v-ea62d372] {\n display: inline-block;\n}\n.vue-zoomer-gallery.anim .slide[data-v-ea62d372] {\n transition: left 0.4s;\n}\n.slide[data-v-ea62d372] {\n position: absolute;\n top: 0;\n object-fit: contain;\n width: 100%;\n height: 100%;\n -webkit-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
inject("data-v-fc52b35c_0", { source: "\n.vue-zoomer-gallery[data-v-fc52b35c] {\n position: relative;\n overflow: hidden;\n user-select: none;\n min-width: 100px;\n min-height: 100px;\n}\n.vue-zoomer-gallery > *[data-v-fc52b35c] {\n display: inline-block;\n}\n.vue-zoomer-gallery.anim .slide[data-v-fc52b35c] {\n transition: left 0.4s;\n}\n.slide[data-v-fc52b35c] {\n position: absolute;\n top: 0;\n object-fit: contain;\n width: 100%;\n height: 100%;\n -webkit-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
}; | ||
/* scoped */ | ||
const __vue_scope_id__$1 = "data-v-ea62d372"; | ||
const __vue_scope_id__$1 = "data-v-fc52b35c"; | ||
/* module identifier */ | ||
@@ -1433,3 +1044,3 @@ const __vue_module_identifier__$1 = undefined; | ||
const __vue_component__$1 = /*#__PURE__*/normalizeComponent_1( | ||
const __vue_component__$1 = /*#__PURE__*/normalizeComponent( | ||
{ render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }, | ||
@@ -1442,3 +1053,3 @@ __vue_inject_styles__$1, | ||
false, | ||
browser, | ||
createInjector, | ||
undefined, | ||
@@ -1453,4 +1064,7 @@ undefined | ||
}, | ||
// for locally register | ||
Zoomer: __vue_component__, | ||
Gallery: __vue_component__$1, | ||
}; | ||
export default index; |
@@ -1,1447 +0,1061 @@ | ||
// vue-zoomer v0.3.9 - Jarvis Niu | ||
// vue-zoomer v0.3.10 - Jarvis Niu | ||
// https://github.com/jarvisniu/vue-zoomer | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = global || self, global.VueZoomer = factory()); | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = global || self, global.VueZoomer = factory()); | ||
}(this, (function () { 'use strict'; | ||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
/* esm.sh - esbuild bundle(lodash@4.17.20/debounce) esnext production */ | ||
if (typeof global === "undefined") var global = window;var ce=Object.create,S=Object.defineProperty,se=Object.getPrototypeOf,ue=Object.prototype.hasOwnProperty,be=Object.getOwnPropertyNames,le=Object.getOwnPropertyDescriptor,ge=e=>S(e,"__esModule",{value:!0}),a=(e,r)=>()=>(r||(r={exports:{}},e(r.exports,r)),r.exports),de=(e,r,n)=>{if(ge(e),r&&typeof r=="object"||typeof r=="function")for(let i of be(r))!ue.call(e,i)&&i!=="default"&&S(e,i,{get:()=>r[i],enumerable:!(n=le(r,i))||n.enumerable});return e},me=e=>e&&e.__esModule?e:de(S(e!=null?ce(se(e)):{},"default",{value:e,enumerable:!0}),e),x=a((rr,E)=>{function pe(e){var r=typeof e;return e!=null&&(r=="object"||r=="function")}E.exports=pe;}),N=a((tr,L)=>{var ye=typeof global=="object"&&global&&global.Object===Object&&global;L.exports=ye;}),O=a((nr,G)=>{var Te=N(),je=typeof self=="object"&&self&&self.Object===Object&&self,Se=Te||je||Function("return this")();G.exports=Se;}),w=a((ir,R)=>{var xe=O(),Oe=function(){return xe.Date.now()};R.exports=Oe;}),v=a((or,P)=>{var ve=O(),qe=ve.Symbol;P.exports=qe;}),$=a((ar,W)=>{var C=v(),M=Object.prototype,he=M.hasOwnProperty,Ie=M.toString,m=C?C.toStringTag:void 0;function _e(e){var r=he.call(e,m),n=e[m];try{e[m]=void 0;var i=!0;}catch(b){}var c=Ie.call(e);return i&&(r?e[m]=n:delete e[m]),c}W.exports=_e;}),B=a((fr,A)=>{var ke=Object.prototype,Ee=ke.toString;function Le(e){return Ee.call(e)}A.exports=Le;}),H=a((cr,F)=>{var U=v(),Ne=$(),Ge=B(),Re="[object Null]",we="[object Undefined]",D=U?U.toStringTag:void 0;function Pe(e){return e==null?e===void 0?we:Re:D&&D in Object(e)?Ne(e):Ge(e)}F.exports=Pe;}),z=a((sr,X)=>{function We(e){return e!=null&&typeof e=="object"}X.exports=We;}),K=a((ur,J)=>{var Ce=H(),Me=z(),$e="[object Symbol]";function Ae(e){return typeof e=="symbol"||Me(e)&&Ce(e)==$e}J.exports=Ae;}),Z=a((br,Q)=>{var V=x(),Be=K(),Y=0/0,Fe=/^\s+|\s+$/g,Ue=/^[-+]0x[0-9a-f]+$/i,De=/^0b[01]+$/i,He=/^0o[0-7]+$/i,Xe=parseInt;function ze(e){if(typeof e=="number")return e;if(Be(e))return Y;if(V(e)){var r=typeof e.valueOf=="function"?e.valueOf():e;e=V(r)?r+"":r;}if(typeof e!="string")return e===0?e:+e;e=e.replace(Fe,"");var n=De.test(e);return n||He.test(e)?Xe(e.slice(2),n?2:8):Ue.test(e)?Y:+e}Q.exports=ze;}),te=a((lr,ee)=>{var Je=x(),q=w(),re=Z(),Ke="Expected a function",Qe=Math.max,Ve=Math.min;function Ye(e,r,n){var i,c,b,u,o,s,l=0,h=!1,g=!1,y=!0;if(typeof e!="function")throw new TypeError(Ke);r=re(r)||0,Je(n)&&(h=!!n.leading,g="maxWait"in n,b=g?Qe(re(n.maxWait)||0,r):b,y="trailing"in n?!!n.trailing:y);function T(t){var f=i,d=c;return i=c=void 0,l=t,u=e.apply(d,f),u}function ie(t){return l=t,o=setTimeout(p,r),h?T(t):u}function oe(t){var f=t-s,d=t-l,k=r-f;return g?Ve(k,b-d):k}function I(t){var f=t-s,d=t-l;return s===void 0||f>=r||f<0||g&&d>=b}function p(){var t=q();if(I(t))return _(t);o=setTimeout(p,oe(t));}function _(t){return o=void 0,y&&i?T(t):(i=c=void 0,u)}function ae(){o!==void 0&&clearTimeout(o),l=0,i=s=c=o=void 0;}function fe(){return o===void 0?u:_(q())}function j(){var t=q(),f=I(t);if(i=arguments,c=this,s=t,f){if(o===void 0)return ie(s);if(g)return clearTimeout(o),o=setTimeout(p,r),T(s)}return o===void 0&&(o=setTimeout(p,r)),u}return j.cancel=ae,j.flush=fe,j}ee.exports=Ye;}),ne=me(te()),Ze=ne.default; | ||
/** | ||
* lodash (Custom Build) <https://lodash.com/> | ||
* Build: `lodash modularize exports="npm" -o ./` | ||
* Copyright jQuery Foundation and other contributors <https://jquery.org/> | ||
* Released under MIT license <https://lodash.com/license> | ||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> | ||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors | ||
*/ | ||
/** | ||
* Detect double tap events | ||
* # Deals with: | ||
* - Time intervals between taps | ||
* - Swipe will stop the taps | ||
* # Usage: | ||
* let tapDetector = new TapDetector() | ||
* tapDetector.attach(this.$el) // in mounted | ||
* tapDetector.detach(this.$el) // in destroy | ||
* tapDetector.onSingle(callback) | ||
* tapDetector.onDouble(callback) | ||
*/ | ||
/** Used as the `TypeError` message for "Functions" methods. */ | ||
var FUNC_ERROR_TEXT = 'Expected a function'; | ||
function TapDetector () { | ||
/** Used as references for various `Number` constants. */ | ||
var NAN = 0 / 0; | ||
// Callbacks ----------------------------------------------------------------- | ||
/** `Object#toString` result references. */ | ||
var symbolTag = '[object Symbol]'; | ||
let singleTapCallbacks = []; | ||
let doubleTapCallbacks = []; | ||
/** Used to match leading and trailing whitespace. */ | ||
var reTrim = /^\s+|\s+$/g; | ||
function triggerCallbacks (cbList, arg) { | ||
cbList.forEach(cbItem => { | ||
cbItem.call(null, arg); | ||
}); | ||
} | ||
/** Used to detect bad signed hexadecimal string values. */ | ||
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; | ||
this.onSingleTap = function (cb) { | ||
if (typeof cb === 'function' && !singleTapCallbacks.includes(cb)) { | ||
singleTapCallbacks.push(cb); | ||
} | ||
}; | ||
this.onDoubleTap = function (cb) { | ||
if (typeof cb === 'function' && !doubleTapCallbacks.includes(cb)) { | ||
doubleTapCallbacks.push(cb); | ||
} | ||
}; | ||
/** Used to detect binary string values. */ | ||
var reIsBinary = /^0b[01]+$/i; | ||
this.attach = function (dom) { | ||
if (!(dom instanceof Element)) { | ||
console.error('TapDetector.attach: arg must be an Element'); | ||
return | ||
} | ||
dom.addEventListener('touchstart', onTouchStart); | ||
dom.addEventListener('touchmove', onTouchMove); | ||
dom.addEventListener('touchend', onTouchEnd); | ||
dom.addEventListener('mousedown', onMouseDown); | ||
dom.addEventListener('mouseup', onMouseUp); | ||
dom.addEventListener('mousemove', onMouseMove); | ||
}; | ||
/** Used to detect octal string values. */ | ||
var reIsOctal = /^0o[0-7]+$/i; | ||
this.detach = function (dom) { | ||
dom.removeEventListener('touchstart', onTouchStart); | ||
dom.removeEventListener('touchmove', onTouchMove); | ||
dom.removeEventListener('touchend', onTouchEnd); | ||
dom.removeEventListener('mousedown', onMouseDown); | ||
dom.removeEventListener('mouseup', onMouseUp); | ||
dom.removeEventListener('mousemove', onMouseMove); | ||
}; | ||
/** Built-in method references without a dependency on `root`. */ | ||
var freeParseInt = parseInt; | ||
// Main logic ---------------------------------------------------------------- | ||
/** Detect free variable `global` from Node.js. */ | ||
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; | ||
// in touch mode mouse events will be disabled. Otherwise touches will | ||
// trigger both touchend end mouseup, i.e. one touch triggers two onPointerUp. | ||
let isTouchMode = false; | ||
let lastTapTimestamp = 0; | ||
let tappedCount = 0; | ||
let touchMovedLength = 0; | ||
let lastPointerX = 0; | ||
let lastPointerY = 0; | ||
/** Detect free variable `self`. */ | ||
var freeSelf = typeof self == 'object' && self && self.Object === Object && self; | ||
function onTouchStart (ev) { | ||
isTouchMode = true; | ||
// console.log('onTouchStart') | ||
if (ev.touches.length === 1) { | ||
onPointerDown(ev.touches[0].clientX, ev.touches[0].clientY); | ||
} | ||
} | ||
function onTouchEnd (ev) { | ||
// console.log('onTouchEnd') | ||
if (ev.touches.length === 0) { | ||
onPointerUp(); | ||
} | ||
} | ||
function onTouchMove (ev) { | ||
// console.log('onTouchMove', ev) | ||
if (ev.touches.length === 1) { | ||
onPointerMove(ev.touches[0].clientX, ev.touches[0].clientY); | ||
} | ||
} | ||
/** Used as a reference to the global object. */ | ||
var root = freeGlobal || freeSelf || Function('return this')(); | ||
function onMouseDown (ev) { | ||
if (isTouchMode) return | ||
/** Used for built-in method references. */ | ||
var objectProto = Object.prototype; | ||
// console.log('onMouseDown') | ||
onPointerDown(ev.clientX, ev.clientY); | ||
} | ||
function onMouseUp (ev) { | ||
if (isTouchMode) return | ||
/** | ||
* Used to resolve the | ||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) | ||
* of values. | ||
*/ | ||
var objectToString = objectProto.toString; | ||
// console.log('onMouseUp') | ||
onPointerUp(); | ||
} | ||
function onMouseMove (ev) { | ||
if (isTouchMode) return | ||
/* Built-in method references for those with the same name as other `lodash` methods. */ | ||
var nativeMax = Math.max, | ||
nativeMin = Math.min; | ||
// console.log('onMouseMove', ev) | ||
if (ev.button === 0) { | ||
onPointerMove(ev.clientX, ev.clientY); | ||
} | ||
} | ||
/** | ||
* Gets the timestamp of the number of milliseconds that have elapsed since | ||
* the Unix epoch (1 January 1970 00:00:00 UTC). | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 2.4.0 | ||
* @category Date | ||
* @returns {number} Returns the timestamp. | ||
* @example | ||
* | ||
* _.defer(function(stamp) { | ||
* console.log(_.now() - stamp); | ||
* }, _.now()); | ||
* // => Logs the number of milliseconds it took for the deferred invocation. | ||
*/ | ||
var now = function() { | ||
return root.Date.now(); | ||
}; | ||
function onPointerDown (x, y) { | ||
lastPointerX = x; | ||
lastPointerY = y; | ||
touchMovedLength = 0; | ||
} | ||
function onPointerUp () { | ||
let currTimeStamp = Date.now(); | ||
// console.log('touchMovedLength', touchMovedLength) | ||
if (touchMovedLength < 10) { | ||
// Only when no sliding two far is considered as a valid tap | ||
if (currTimeStamp - lastTapTimestamp < 300) { | ||
tappedCount += 1; | ||
} else { | ||
tappedCount = 1; | ||
} | ||
lastTapTimestamp = Date.now(); | ||
// console.log('tappedCount', tappedCount) | ||
triggerCallbacks(singleTapCallbacks, { | ||
clientX: lastPointerX, | ||
clientY: lastPointerY, | ||
}); | ||
if (tappedCount === 2) { | ||
triggerCallbacks(doubleTapCallbacks, { | ||
clientX: lastPointerX, | ||
clientY: lastPointerY, | ||
}); | ||
tappedCount = 0; // clear count on maximum tap count | ||
} | ||
} | ||
touchMovedLength = 0; | ||
} | ||
function onPointerMove (x, y) { | ||
let deltaX = lastPointerX - x; | ||
let deltaY = lastPointerY - y; | ||
let length = Math.sqrt(deltaX * deltaX + deltaY * deltaY); | ||
// console.log('onTouchMove length', length) | ||
touchMovedLength += length; | ||
lastPointerX = x; | ||
lastPointerY = y; | ||
} | ||
} | ||
/** | ||
* Creates a debounced function that delays invoking `func` until after `wait` | ||
* milliseconds have elapsed since the last time the debounced function was | ||
* invoked. The debounced function comes with a `cancel` method to cancel | ||
* delayed `func` invocations and a `flush` method to immediately invoke them. | ||
* Provide `options` to indicate whether `func` should be invoked on the | ||
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked | ||
* with the last arguments provided to the debounced function. Subsequent | ||
* calls to the debounced function return the result of the last `func` | ||
* invocation. | ||
* | ||
* **Note:** If `leading` and `trailing` options are `true`, `func` is | ||
* invoked on the trailing edge of the timeout only if the debounced function | ||
* is invoked more than once during the `wait` timeout. | ||
* | ||
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred | ||
* until to the next tick, similar to `setTimeout` with a timeout of `0`. | ||
* | ||
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) | ||
* for details over the differences between `_.debounce` and `_.throttle`. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 0.1.0 | ||
* @category Function | ||
* @param {Function} func The function to debounce. | ||
* @param {number} [wait=0] The number of milliseconds to delay. | ||
* @param {Object} [options={}] The options object. | ||
* @param {boolean} [options.leading=false] | ||
* Specify invoking on the leading edge of the timeout. | ||
* @param {number} [options.maxWait] | ||
* The maximum time `func` is allowed to be delayed before it's invoked. | ||
* @param {boolean} [options.trailing=true] | ||
* Specify invoking on the trailing edge of the timeout. | ||
* @returns {Function} Returns the new debounced function. | ||
* @example | ||
* | ||
* // Avoid costly calculations while the window size is in flux. | ||
* jQuery(window).on('resize', _.debounce(calculateLayout, 150)); | ||
* | ||
* // Invoke `sendMail` when clicked, debouncing subsequent calls. | ||
* jQuery(element).on('click', _.debounce(sendMail, 300, { | ||
* 'leading': true, | ||
* 'trailing': false | ||
* })); | ||
* | ||
* // Ensure `batchLog` is invoked once after 1 second of debounced calls. | ||
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); | ||
* var source = new EventSource('/stream'); | ||
* jQuery(source).on('message', debounced); | ||
* | ||
* // Cancel the trailing debounced invocation. | ||
* jQuery(window).on('popstate', debounced.cancel); | ||
*/ | ||
function debounce(func, wait, options) { | ||
var lastArgs, | ||
lastThis, | ||
maxWait, | ||
result, | ||
timerId, | ||
lastCallTime, | ||
lastInvokeTime = 0, | ||
leading = false, | ||
maxing = false, | ||
trailing = true; | ||
// | ||
if (typeof func != 'function') { | ||
throw new TypeError(FUNC_ERROR_TEXT); | ||
} | ||
wait = toNumber(wait) || 0; | ||
if (isObject(options)) { | ||
leading = !!options.leading; | ||
maxing = 'maxWait' in options; | ||
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; | ||
trailing = 'trailing' in options ? !!options.trailing : trailing; | ||
} | ||
var script = { | ||
props: { | ||
minScale: { type: Number, default: 1 }, | ||
maxScale: { type: Number, default: 5 }, | ||
zoomed: { type: Boolean, default: false }, | ||
resetTrigger: { type: Number, default: 1e5 }, | ||
aspectRatio: { type: Number, default: 1 }, | ||
backgroundColor: { type: String, default: 'transparent' }, | ||
pivot: { type: String, default: 'cursor' }, // other options: image-center | ||
zoomingElastic: { type: Boolean, default: true }, | ||
limitTranslation: { type: Boolean, default: true }, | ||
doubleClickToZoom: { type: Boolean, default: true }, | ||
mouseWheelToZoom: { type: Boolean, default: true }, | ||
}, | ||
data () { | ||
return { | ||
// Container sizes, used to determin the initial zoomer size. | ||
// Need to reactive to window resizing. | ||
containerWidth: 1, | ||
containerHeight: 1, | ||
containerLeft: 0, | ||
containerTop: 0, | ||
// Store values: Interactions will at last change these values. | ||
// After rotation or resize, these values will keep still. | ||
// These three values are all relative to the container size. | ||
translateX: 0, | ||
animTranslateX: 0, | ||
translateY: 0, | ||
animTranslateY: 0, | ||
scale: 1, | ||
animScale: 1, | ||
// Mouse states | ||
lastFullWheelTime: 0, | ||
lastWheelTime: 0, | ||
lastWheelDirection: 'y', | ||
isPointerDown: false, | ||
pointerPosX: -1, | ||
pointerPosY: -1, | ||
twoFingerInitDist: 0, | ||
panLocked: true, | ||
// Others | ||
raf: null, | ||
tapDetector: null, | ||
} | ||
}, | ||
computed: { | ||
wrapperStyle () { | ||
let translateX = this.containerWidth * this.animTranslateX; | ||
let translateY = this.containerHeight * this.animTranslateY; | ||
return { | ||
transform: [ | ||
`translate(${ translateX }px, ${ translateY }px)`, | ||
`scale(${ this.animScale })`, | ||
].join(' ') | ||
} | ||
}, | ||
}, | ||
watch: { | ||
scale (val) { | ||
if (val !== 1) { | ||
this.$emit('update:zoomed', true); | ||
this.panLocked = false; | ||
} | ||
}, | ||
resetTrigger: 'reset', | ||
}, | ||
mounted () { | ||
this.tapDetector = new TapDetector(); | ||
this.tapDetector.attach(this.$el); | ||
if (this.doubleClickToZoom) { | ||
this.tapDetector.onDoubleTap(this.onDoubleTap); | ||
} | ||
// console.log('container size: ', this.containerWidth, this.containerHeight) | ||
window.addEventListener('resize', this.onWindowResize); | ||
this.onWindowResize(); | ||
this.refreshContainerPos(); | ||
this.loop(); | ||
}, | ||
destroyed () { | ||
this.tapDetector.detach(this.$el); | ||
window.removeEventListener('resize', this.onWindowResize); | ||
window.cancelAnimationFrame(this.raf); | ||
// console.log('destroy') | ||
}, | ||
methods: { | ||
// API --------------------------------------------------------------------- | ||
reset () { | ||
this.scale = 1; | ||
this.panLocked = true; | ||
this.translateX = 0; | ||
this.translateY = 0; | ||
}, | ||
zoomIn(scale = 2) { | ||
this.tryToScale(scale); | ||
this.onInteractionEnd(); | ||
}, | ||
zoomOut(scale = 0.5) { | ||
this.tryToScale(scale); | ||
this.onInteractionEnd(); | ||
}, | ||
// Main Logic -------------------------------------------------------------- | ||
// scale | ||
// Zoom the image with the point at the pointer(mouse or pinch center) pinned. | ||
// Simplify: This can be regard as vector pointer to old-image-center scaling. | ||
tryToScale (scaleDelta) { | ||
let newScale = this.scale * scaleDelta; | ||
if (this.zoomingElastic) { | ||
// damping | ||
if (newScale < this.minScale || newScale > this.maxScale) { | ||
let log = Math.log2(scaleDelta); | ||
log *= 0.2; | ||
scaleDelta = Math.pow(2, log); | ||
newScale = this.scale * scaleDelta; | ||
} | ||
} else { | ||
if (newScale < this.minScale) newScale = this.minScale; | ||
else if (newScale > this.maxScale) newScale = this.maxScale; | ||
} | ||
scaleDelta = newScale / this.scale; | ||
this.scale = newScale; | ||
if (this.pivot !== 'image-center') { | ||
let normMousePosX = (this.pointerPosX - this.containerLeft) / this.containerWidth; | ||
let normMousePosY = (this.pointerPosY - this.containerTop) / this.containerHeight; | ||
this.translateX = (0.5 + this.translateX - normMousePosX) * scaleDelta + normMousePosX - 0.5; | ||
this.translateY = (0.5 + this.translateY - normMousePosY) * scaleDelta + normMousePosY - 0.5; | ||
} | ||
}, | ||
setPointerPosCenter () { | ||
this.pointerPosX = this.containerLeft + this.containerWidth / 2; | ||
this.pointerPosY = this.containerTop + this.containerHeight / 2; | ||
}, | ||
// pan | ||
onPointerMove (newMousePosX, newMousePosY) { | ||
if (this.isPointerDown) { | ||
let pixelDeltaX = newMousePosX - this.pointerPosX; | ||
let pixelDeltaY = newMousePosY - this.pointerPosY; | ||
// console.log('pixelDeltaX, pixelDeltaY', pixelDeltaX, pixelDeltaY) | ||
if (!this.panLocked) { | ||
this.translateX += pixelDeltaX / this.containerWidth; | ||
this.translateY += pixelDeltaY / this.containerHeight; | ||
} | ||
} | ||
this.pointerPosX = newMousePosX; | ||
this.pointerPosY = newMousePosY; | ||
}, | ||
onInteractionEnd: Ze(function () { | ||
this.limit(); | ||
this.panLocked = this.scale === 1; | ||
this.$emit('update:zoomed', !this.panLocked); | ||
}, 100), | ||
// limit the scale between max and min and the translate within the viewport | ||
limit () { | ||
// scale | ||
if (this.scale < this.minScale) { | ||
this.scale = this.minScale; | ||
// FIXME this sometimes will not reset when pinching in | ||
// this.tryToScale(this.minScale / this.scale) | ||
} else if (this.scale > this.maxScale) { | ||
this.tryToScale(this.maxScale / this.scale); | ||
} | ||
// translate | ||
if (this.limitTranslation) { | ||
let translateLimit = this.calcTranslateLimit(); | ||
if (Math.abs(this.translateX) > translateLimit.x) { | ||
this.translateX *= translateLimit.x / Math.abs(this.translateX); | ||
} | ||
if (Math.abs(this.translateY) > translateLimit.y) { | ||
this.translateY *= translateLimit.y / Math.abs(this.translateY); | ||
} | ||
} | ||
}, | ||
calcTranslateLimit () { | ||
if (this.getMarginDirection() === 'y') { | ||
let imageToContainerRatio = this.containerWidth / this.aspectRatio / this.containerHeight; | ||
let translateLimitY = (this.scale * imageToContainerRatio - 1) / 2; | ||
if (translateLimitY < 0) translateLimitY = 0; | ||
return { | ||
x: (this.scale - 1) / 2, | ||
y: translateLimitY, | ||
} | ||
} else { | ||
let imageToContainerRatio = this.containerHeight * this.aspectRatio / this.containerWidth; | ||
let translateLimitX = (this.scale * imageToContainerRatio - 1) / 2; | ||
if (translateLimitX < 0) translateLimitX = 0; | ||
return { | ||
x: translateLimitX, | ||
y: (this.scale - 1) / 2, | ||
} | ||
} | ||
}, | ||
getMarginDirection () { | ||
let containerRatio = this.containerWidth / this.containerHeight; | ||
return containerRatio > this.aspectRatio ? 'x' : 'y' | ||
}, | ||
onDoubleTap (ev) { | ||
if (this.scale === 1) { | ||
if (ev.clientX > 0) { | ||
this.pointerPosX = ev.clientX; | ||
this.pointerPosY = ev.clientY; | ||
} | ||
this.tryToScale(Math.min(3, this.maxScale)); | ||
} else { | ||
this.reset(); | ||
} | ||
this.onInteractionEnd(); | ||
}, | ||
// reactive | ||
onWindowResize () { | ||
let styles = window.getComputedStyle(this.$el); | ||
this.containerWidth = parseFloat(styles.width); | ||
this.containerHeight = parseFloat(styles.height); | ||
this.setPointerPosCenter(); | ||
this.limit(); | ||
}, | ||
refreshContainerPos () { | ||
let rect = this.$el.getBoundingClientRect(); | ||
this.containerLeft = rect.left; | ||
this.containerTop = rect.top; | ||
}, | ||
loop () { | ||
this.animScale = this.gainOn(this.animScale, this.scale); | ||
this.animTranslateX = this.gainOn(this.animTranslateX, this.translateX); | ||
this.animTranslateY = this.gainOn(this.animTranslateY, this.translateY); | ||
this.raf = window.requestAnimationFrame(this.loop); | ||
// console.log('loop', this.raf) | ||
}, | ||
gainOn (from, to) { | ||
let delta = (to - from) * 0.3; | ||
// console.log('gainOn', from, to, from + delta) | ||
if (Math.abs(delta) > 1e-5) { | ||
return from + delta | ||
} else { | ||
return to | ||
} | ||
}, | ||
// Mouse Events ------------------------------------------------------------ | ||
// Mouse wheel scroll, TrackPad pinch or TrackPad scroll | ||
onMouseWheel (ev) { | ||
if (!this.mouseWheelToZoom) return | ||
// prevent is used to stop the page scroll elastic effects | ||
ev.preventDefault(); | ||
if (ev.detail) ev.wheelDelta = ev.detail * -10; | ||
let currTime = Date.now(); | ||
if (Math.abs(ev.wheelDelta) === 120) { | ||
// Throttle the TouchPad pinch on Mac, or it will be too sensitive | ||
if (currTime - this.lastFullWheelTime > 50) { | ||
this.onMouseWheelDo(ev.wheelDelta); | ||
this.lastFullWheelTime = currTime; | ||
} | ||
} else { | ||
if (currTime - this.lastWheelTime > 50 && typeof ev.deltaX === 'number') { | ||
this.lastWheelDirection = (ev.detail == 0 && Math.abs(ev.deltaX) > Math.abs(ev.deltaY)) ? 'x' : 'y'; | ||
if (this.lastWheelDirection === 'x') { | ||
this.$emit('swipe', ev.deltaX > 0 ? 'left' : 'right'); | ||
} | ||
} | ||
if (this.lastWheelDirection === 'y') { | ||
this.onMouseWheelDo(ev.wheelDelta); | ||
} | ||
} | ||
this.lastWheelTime = currTime; | ||
}, | ||
onMouseWheelDo (wheelDelta) { | ||
// Value basis: One mouse wheel (wheelDelta=+-120) means 1.25/0.8 scale. | ||
let scaleDelta = Math.pow(1.25, wheelDelta / 120); | ||
this.tryToScale(scaleDelta); | ||
this.onInteractionEnd(); | ||
}, | ||
onMouseDown (ev) { | ||
this.refreshContainerPos(); | ||
this.isPointerDown = true; | ||
// Open the context menu then click other place will skip the mousemove events. | ||
// This will cause the pointerPosX/Y NOT sync, then we will need to fix it on mousedown event. | ||
this.pointerPosX = ev.clientX; | ||
this.pointerPosY = ev.clientY; | ||
// console.log('onMouseDown', ev) | ||
}, | ||
onMouseUp (ev) { | ||
this.isPointerDown = false; | ||
this.onInteractionEnd(); | ||
}, | ||
onMouseMove (ev) { | ||
this.onPointerMove(ev.clientX, ev.clientY); | ||
// console.log('onMouseMove client, offset', ev.clientX, ev.clientY) | ||
}, | ||
// Touch Events ------------------------------------------------------------ | ||
onTouchStart (ev) { | ||
if (ev.touches.length === 1) { | ||
this.refreshContainerPos(); | ||
this.pointerPosX = ev.touches[0].clientX; | ||
this.pointerPosY = ev.touches[0].clientY; | ||
this.isPointerDown = true; | ||
} else if (ev.touches.length === 2) { | ||
this.isPointerDown = true; | ||
// pos | ||
this.pointerPosX = (ev.touches[0].clientX + ev.touches[1].clientX) / 2; | ||
this.pointerPosY = (ev.touches[0].clientY + ev.touches[1].clientY) / 2; | ||
// dist | ||
let distX = ev.touches[0].clientX - ev.touches[1].clientX; | ||
let distY = ev.touches[0].clientY - ev.touches[1].clientY; | ||
this.twoFingerInitDist = Math.sqrt(distX * distX + distY * distY); | ||
} | ||
// console.log('onTouchStart', ev.touches) | ||
}, | ||
onTouchEnd (ev) { | ||
if (ev.touches.length === 0) { | ||
this.isPointerDown = false; | ||
// Near 1 to set 1 | ||
if (Math.abs(this.scale - 1) < 0.1) this.scale = 1; | ||
this.onInteractionEnd(); | ||
} else if (ev.touches.length === 1) { | ||
this.pointerPosX = ev.touches[0].clientX; | ||
this.pointerPosY = ev.touches[0].clientY; | ||
} | ||
// console.log('onTouchEnd', ev.touches.length) | ||
}, | ||
onTouchMove (ev) { | ||
if (ev.touches.length === 1) { | ||
this.onPointerMove(ev.touches[0].clientX, ev.touches[0].clientY); | ||
} else if (ev.touches.length === 2) { | ||
// pos | ||
let newMousePosX = (ev.touches[0].clientX + ev.touches[1].clientX) / 2; | ||
let newMousePosY = (ev.touches[0].clientY + ev.touches[1].clientY) / 2; | ||
this.onPointerMove(newMousePosX, newMousePosY); | ||
this.pointerPosX = newMousePosX; | ||
this.pointerPosY = newMousePosY; | ||
// dist | ||
let distX = ev.touches[0].clientX - ev.touches[1].clientX; | ||
let distY = ev.touches[0].clientY - ev.touches[1].clientY; | ||
let newTwoFingerDist = Math.sqrt(distX * distX + distY * distY); | ||
this.tryToScale(newTwoFingerDist / this.twoFingerInitDist); | ||
this.twoFingerInitDist = newTwoFingerDist; | ||
} | ||
// console.log('onTouchMove', this.pointerPosX, this.pointerPosY) | ||
}, | ||
}, | ||
}; | ||
function invokeFunc(time) { | ||
var args = lastArgs, | ||
thisArg = lastThis; | ||
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { | ||
if (typeof shadowMode !== 'boolean') { | ||
createInjectorSSR = createInjector; | ||
createInjector = shadowMode; | ||
shadowMode = false; | ||
} | ||
// Vue.extend constructor export interop. | ||
const options = typeof script === 'function' ? script.options : script; | ||
// render functions | ||
if (template && template.render) { | ||
options.render = template.render; | ||
options.staticRenderFns = template.staticRenderFns; | ||
options._compiled = true; | ||
// functional template | ||
if (isFunctionalTemplate) { | ||
options.functional = true; | ||
} | ||
} | ||
// scopedId | ||
if (scopeId) { | ||
options._scopeId = scopeId; | ||
} | ||
let hook; | ||
if (moduleIdentifier) { | ||
// server build | ||
hook = function (context) { | ||
// 2.3 injection | ||
context = | ||
context || // cached call | ||
(this.$vnode && this.$vnode.ssrContext) || // stateful | ||
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional | ||
// 2.2 with runInNewContext: true | ||
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { | ||
context = __VUE_SSR_CONTEXT__; | ||
} | ||
// inject component styles | ||
if (style) { | ||
style.call(this, createInjectorSSR(context)); | ||
} | ||
// register component module identifier for async chunk inference | ||
if (context && context._registeredComponents) { | ||
context._registeredComponents.add(moduleIdentifier); | ||
} | ||
}; | ||
// used by ssr in case component is cached and beforeCreate | ||
// never gets called | ||
options._ssrRegister = hook; | ||
} | ||
else if (style) { | ||
hook = shadowMode | ||
? function (context) { | ||
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); | ||
} | ||
: function (context) { | ||
style.call(this, createInjector(context)); | ||
}; | ||
} | ||
if (hook) { | ||
if (options.functional) { | ||
// register for functional component in vue file | ||
const originalRender = options.render; | ||
options.render = function renderWithStyleInjection(h, context) { | ||
hook.call(context); | ||
return originalRender(h, context); | ||
}; | ||
} | ||
else { | ||
// inject component registration as beforeCreate hook | ||
const existing = options.beforeCreate; | ||
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; | ||
} | ||
} | ||
return script; | ||
} | ||
lastArgs = lastThis = undefined; | ||
lastInvokeTime = time; | ||
result = func.apply(thisArg, args); | ||
return result; | ||
} | ||
const isOldIE = typeof navigator !== 'undefined' && | ||
/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); | ||
function createInjector(context) { | ||
return (id, style) => addStyle(id, style); | ||
} | ||
let HEAD; | ||
const styles = {}; | ||
function addStyle(id, css) { | ||
const group = isOldIE ? css.media || 'default' : id; | ||
const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] }); | ||
if (!style.ids.has(id)) { | ||
style.ids.add(id); | ||
let code = css.source; | ||
if (css.map) { | ||
// https://developer.chrome.com/devtools/docs/javascript-debugging | ||
// this makes source maps inside style tags work properly in Chrome | ||
code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; | ||
// http://stackoverflow.com/a/26603875 | ||
code += | ||
'\n/*# sourceMappingURL=data:application/json;base64,' + | ||
btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + | ||
' */'; | ||
} | ||
if (!style.element) { | ||
style.element = document.createElement('style'); | ||
style.element.type = 'text/css'; | ||
if (css.media) | ||
style.element.setAttribute('media', css.media); | ||
if (HEAD === undefined) { | ||
HEAD = document.head || document.getElementsByTagName('head')[0]; | ||
} | ||
HEAD.appendChild(style.element); | ||
} | ||
if ('styleSheet' in style.element) { | ||
style.styles.push(code); | ||
style.element.styleSheet.cssText = style.styles | ||
.filter(Boolean) | ||
.join('\n'); | ||
} | ||
else { | ||
const index = style.ids.size - 1; | ||
const textNode = document.createTextNode(code); | ||
const nodes = style.element.childNodes; | ||
if (nodes[index]) | ||
style.element.removeChild(nodes[index]); | ||
if (nodes.length) | ||
style.element.insertBefore(textNode, nodes[index]); | ||
else | ||
style.element.appendChild(textNode); | ||
} | ||
} | ||
} | ||
function leadingEdge(time) { | ||
// Reset any `maxWait` timer. | ||
lastInvokeTime = time; | ||
// Start the timer for the trailing edge. | ||
timerId = setTimeout(timerExpired, wait); | ||
// Invoke the leading edge. | ||
return leading ? invokeFunc(time) : result; | ||
} | ||
/* script */ | ||
const __vue_script__ = script; | ||
function remainingWait(time) { | ||
var timeSinceLastCall = time - lastCallTime, | ||
timeSinceLastInvoke = time - lastInvokeTime, | ||
result = wait - timeSinceLastCall; | ||
/* template */ | ||
var __vue_render__ = function () { | ||
var _vm = this; | ||
var _h = _vm.$createElement; | ||
var _c = _vm._self._c || _h; | ||
return _c( | ||
"div", | ||
{ | ||
staticClass: "vue-zoomer", | ||
style: { backgroundColor: _vm.backgroundColor }, | ||
on: { | ||
mousewheel: _vm.onMouseWheel, | ||
DOMMouseScroll: _vm.onMouseWheel, | ||
mousedown: _vm.onMouseDown, | ||
mouseup: _vm.onMouseUp, | ||
mousemove: _vm.onMouseMove, | ||
mouseout: _vm.setPointerPosCenter, | ||
touchstart: _vm.onTouchStart, | ||
touchend: _vm.onTouchEnd, | ||
touchmove: _vm.onTouchMove, | ||
}, | ||
}, | ||
[ | ||
_c( | ||
"div", | ||
{ staticClass: "zoomer", style: _vm.wrapperStyle }, | ||
[_vm._t("default")], | ||
2 | ||
), | ||
] | ||
) | ||
}; | ||
var __vue_staticRenderFns__ = []; | ||
__vue_render__._withStripped = true; | ||
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; | ||
} | ||
/* style */ | ||
const __vue_inject_styles__ = function (inject) { | ||
if (!inject) return | ||
inject("data-v-e532c06e_0", { source: "\n.vue-zoomer[data-v-e532c06e] {\n overflow: hidden;\n}\n.zoomer[data-v-e532c06e] {\n transform-origin: 50% 50%;\n width: 100%;\n height: 100%;\n}\n.zoomer > img[data-v-e532c06e] {\n /* remove the 4px gap below the image */\n vertical-align: top;\n user-drag: none;\n -webkit-user-drag: none;\n -moz-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
function shouldInvoke(time) { | ||
var timeSinceLastCall = time - lastCallTime, | ||
timeSinceLastInvoke = time - lastInvokeTime; | ||
}; | ||
/* scoped */ | ||
const __vue_scope_id__ = "data-v-e532c06e"; | ||
/* module identifier */ | ||
const __vue_module_identifier__ = undefined; | ||
/* functional template */ | ||
const __vue_is_functional_template__ = false; | ||
/* style inject SSR */ | ||
/* style inject shadow dom */ | ||
// Either this is the first call, activity has stopped and we're at the | ||
// trailing edge, the system time has gone backwards and we're treating | ||
// it as the trailing edge, or we've hit the `maxWait` limit. | ||
return (lastCallTime === undefined || (timeSinceLastCall >= wait) || | ||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); | ||
} | ||
const __vue_component__ = /*#__PURE__*/normalizeComponent( | ||
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, | ||
__vue_inject_styles__, | ||
__vue_script__, | ||
__vue_scope_id__, | ||
__vue_is_functional_template__, | ||
__vue_module_identifier__, | ||
false, | ||
createInjector, | ||
undefined, | ||
undefined | ||
); | ||
function timerExpired() { | ||
var time = now(); | ||
if (shouldInvoke(time)) { | ||
return trailingEdge(time); | ||
} | ||
// Restart the timer. | ||
timerId = setTimeout(timerExpired, remainingWait(time)); | ||
} | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
function trailingEdge(time) { | ||
timerId = undefined; | ||
// Only invoke if we have `lastArgs` which means `func` has been | ||
// debounced at least once. | ||
if (trailing && lastArgs) { | ||
return invokeFunc(time); | ||
} | ||
lastArgs = lastThis = undefined; | ||
return result; | ||
} | ||
const SLIDE_WIDTH_THRESH = 50; // in px | ||
function cancel() { | ||
if (timerId !== undefined) { | ||
clearTimeout(timerId); | ||
} | ||
lastInvokeTime = 0; | ||
lastArgs = lastCallTime = lastThis = timerId = undefined; | ||
} | ||
var script$1 = { | ||
props: { | ||
value: { type: Number, required: true }, | ||
list: { type: Array, required: true }, | ||
backgroundColor: { type: String, default: '#333' }, | ||
pivot: { type: String, default: 'cursor' }, | ||
zoomingElastic: { type: Boolean, default: true }, | ||
limitTranslation: { type: Boolean, default: true }, | ||
doubleClickToZoom: { type: Boolean, default: true }, | ||
mouseWheelToZoom: { type: Boolean, default: true }, | ||
}, | ||
data () { | ||
return { | ||
// env states | ||
containerWidth: 1, | ||
containerHeight: 1, | ||
// main states | ||
selIndex: this.value, | ||
animSelIndex: this.value, | ||
currentZoomed: false, | ||
autoSliding: false, | ||
imageAspectRatios: [], // aspect ratio (width / height) of images | ||
// interaction states | ||
isPointerDown: false, | ||
lastPointerX: 0, | ||
slideOffsetX: 0, | ||
} | ||
}, | ||
computed: { | ||
middleStyle () { | ||
return { | ||
left: `${ 0 + this.slideOffsetX }px`, | ||
} | ||
}, | ||
leftStyle () { | ||
return { | ||
left: `${ -this.containerWidth + this.slideOffsetX }px`, | ||
} | ||
}, | ||
rightStyle () { | ||
return { | ||
left: `${ this.containerWidth + this.slideOffsetX }px`, | ||
} | ||
}, | ||
slideThresh () { | ||
return Math.max(SLIDE_WIDTH_THRESH, this.containerWidth * 0.1) | ||
}, | ||
}, | ||
watch: { | ||
value (val) { | ||
if (val !== this.animSelIndex) { | ||
this.selIndex = val; | ||
this.animSelIndex = val; | ||
} | ||
}, | ||
selIndex() { | ||
this.$nextTick(() => { | ||
this.$refs.zoomers.forEach(zoomer => { | ||
zoomer.refreshContainerPos(); | ||
}); | ||
}); | ||
}, | ||
}, | ||
mounted () { | ||
window.addEventListener('resize', this.onWindowResize); | ||
this.onWindowResize(); | ||
}, | ||
destroyed () { | ||
window.removeEventListener('resize', this.onWindowResize); | ||
}, | ||
methods: { | ||
// api --------------------------------------------------------------------- | ||
reset () { | ||
this.$refs.zoomers.forEach(zoomer => { | ||
zoomer.reset(); | ||
}); | ||
}, | ||
zoomIn (scale) { | ||
if (this.$refs.zoomers[1]) this.$refs.zoomers[1].zoomIn(scale); | ||
}, | ||
zoomOut (scale) { | ||
if (this.$refs.zoomers[1]) this.$refs.zoomers[1].zoomOut(scale); | ||
}, | ||
// events ------------------------------------------------------------------ | ||
onWindowResize () { | ||
let styles = window.getComputedStyle(this.$el); | ||
this.containerWidth = parseFloat(styles.width); | ||
this.containerHeight = parseFloat(styles.height); | ||
}, | ||
onPointerMove (deltaX) { | ||
if (this.isPointerDown && !this.currentZoomed) { | ||
let factor = ( | ||
(this.selIndex === 0 && deltaX > 0 && this.slideOffsetX + deltaX > 0) || | ||
(this.selIndex === this.list.length - 1 && deltaX < 0 && this.slideOffsetX + deltaX < 0) | ||
) ? 0.3 : 1; | ||
this.slideOffsetX += deltaX * factor; | ||
} | ||
}, | ||
onPointerUp () { | ||
if (this.slideOffsetX < -this.slideThresh) { | ||
// next page | ||
this.paginate(1); | ||
} else if (this.slideOffsetX > this.slideThresh) { | ||
// prev page | ||
this.paginate(-1); | ||
} else { | ||
// only apply the animation | ||
this.paginate(0); | ||
} | ||
}, | ||
// Stop Firefox dragging the image | ||
onImageDragStart(ev) { | ||
ev.preventDefault(); | ||
return false | ||
}, | ||
paginate (deltaIndex) { | ||
let targetIndex = this.selIndex + deltaIndex; | ||
if (targetIndex < 0 || targetIndex >= this.list.length) { | ||
this.slideOffsetX = 0; | ||
return | ||
} | ||
function flush() { | ||
return timerId === undefined ? result : trailingEdge(now()); | ||
} | ||
this.slideOffsetX = this.containerWidth * -deltaIndex; | ||
this.autoSliding = true; | ||
// update the selIndex before the animation to remove the delay feeling | ||
this.$emit('input', targetIndex); | ||
this.animSelIndex = targetIndex; | ||
setTimeout(() => { | ||
this.selIndex = targetIndex; | ||
this.slideOffsetX = 0; | ||
this.autoSliding = false; | ||
}, 400); | ||
}, | ||
onMouseDown (ev) { | ||
this.isPointerDown = true; | ||
this.lastPointerX = ev.clientX; | ||
}, | ||
onMouseUp (ev) { | ||
this.isPointerDown = false; | ||
this.onPointerUp(); | ||
}, | ||
onMouseMove (ev) { | ||
if (this.isPointerDown) { | ||
this.onPointerMove(ev.clientX - this.lastPointerX); | ||
this.lastPointerX = ev.clientX; | ||
} | ||
}, | ||
onTouchStart (ev) { | ||
if (ev.touches.length === 1) { | ||
this.isPointerDown = true; | ||
this.lastPointerX = ev.touches[0].clientX; | ||
} | ||
}, | ||
onTouchEnd (ev) { | ||
if (ev.touches.length === 0) { | ||
this.isPointerDown = false; | ||
this.onPointerUp(); | ||
} | ||
}, | ||
onTouchMove (ev) { | ||
if (ev.touches.length === 1) { | ||
this.onPointerMove(ev.touches[0].clientX - this.lastPointerX); | ||
this.lastPointerX = ev.touches[0].clientX; | ||
} | ||
}, | ||
onImageLoad (index, ev) { | ||
let aspectRatio = ev.target.naturalWidth / ev.target.naturalHeight; | ||
this.$set(this.imageAspectRatios, index, aspectRatio); | ||
}, | ||
onImageSwipe (direction) { | ||
this.paginate(direction == 'right' ? -1 : 1); | ||
}, | ||
}, | ||
}; | ||
function debounced() { | ||
var time = now(), | ||
isInvoking = shouldInvoke(time); | ||
/* script */ | ||
const __vue_script__$1 = script$1; | ||
lastArgs = arguments; | ||
lastThis = this; | ||
lastCallTime = time; | ||
/* template */ | ||
var __vue_render__$1 = function () { | ||
var _vm = this; | ||
var _h = _vm.$createElement; | ||
var _c = _vm._self._c || _h; | ||
return _c( | ||
"div", | ||
{ | ||
staticClass: "vue-zoomer-gallery", | ||
class: { | ||
anim: _vm.autoSliding && !_vm.isPointerDown, | ||
}, | ||
style: { | ||
"background-color": _vm.backgroundColor, | ||
}, | ||
on: { | ||
mousemove: _vm.onMouseMove, | ||
mousedown: _vm.onMouseDown, | ||
mouseout: _vm.onMouseUp, | ||
mouseup: _vm.onMouseUp, | ||
touchstart: _vm.onTouchStart, | ||
touchend: _vm.onTouchEnd, | ||
touchmove: function ($event) { | ||
$event.preventDefault(); | ||
return _vm.onTouchMove.apply(null, arguments) | ||
}, | ||
}, | ||
}, | ||
_vm._l(3, function (n, i) { | ||
return _c( | ||
"v-zoomer", | ||
{ | ||
key: i + "-" + _vm.selIndex, | ||
ref: "zoomers", | ||
refInFor: true, | ||
staticClass: "slide", | ||
class: ["left", "middle", "right"][i], | ||
style: [_vm.leftStyle, _vm.middleStyle, _vm.rightStyle][i], | ||
attrs: { | ||
"max-scale": 10, | ||
zoomed: _vm.currentZoomed, | ||
"reset-trigger": i, | ||
"aspect-ratio": _vm.imageAspectRatios[_vm.selIndex + i - 1] || 1, | ||
pivot: _vm.pivot, | ||
"zooming-elastic": _vm.zoomingElastic, | ||
"limit-translation": _vm.limitTranslation, | ||
"double-click-to-zoom": _vm.doubleClickToZoom, | ||
"mouse-wheel-to-zoom": _vm.mouseWheelToZoom, | ||
}, | ||
on: { | ||
"update:zoomed": function ($event) { | ||
_vm.currentZoomed = $event; | ||
}, | ||
swipe: _vm.onImageSwipe, | ||
}, | ||
}, | ||
[ | ||
_vm.selIndex + i - 1 > -1 && _vm.selIndex + i - 1 < _vm.list.length | ||
? _c("img", { | ||
staticStyle: { | ||
"object-fit": "contain", | ||
width: "100%", | ||
height: "100%", | ||
}, | ||
attrs: { | ||
src: _vm.list[_vm.selIndex + i - 1], | ||
draggable: "false", | ||
}, | ||
on: { | ||
load: function ($event) { | ||
return _vm.onImageLoad(_vm.selIndex + i - 1, $event) | ||
}, | ||
dragstart: _vm.onImageDragStart, | ||
}, | ||
}) | ||
: _vm._e(), | ||
] | ||
) | ||
}), | ||
1 | ||
) | ||
}; | ||
var __vue_staticRenderFns__$1 = []; | ||
__vue_render__$1._withStripped = true; | ||
if (isInvoking) { | ||
if (timerId === undefined) { | ||
return leadingEdge(lastCallTime); | ||
} | ||
if (maxing) { | ||
// Handle invocations in a tight loop. | ||
timerId = setTimeout(timerExpired, wait); | ||
return invokeFunc(lastCallTime); | ||
} | ||
} | ||
if (timerId === undefined) { | ||
timerId = setTimeout(timerExpired, wait); | ||
} | ||
return result; | ||
} | ||
debounced.cancel = cancel; | ||
debounced.flush = flush; | ||
return debounced; | ||
} | ||
/* style */ | ||
const __vue_inject_styles__$1 = function (inject) { | ||
if (!inject) return | ||
inject("data-v-fc52b35c_0", { source: "\n.vue-zoomer-gallery[data-v-fc52b35c] {\n position: relative;\n overflow: hidden;\n user-select: none;\n min-width: 100px;\n min-height: 100px;\n}\n.vue-zoomer-gallery > *[data-v-fc52b35c] {\n display: inline-block;\n}\n.vue-zoomer-gallery.anim .slide[data-v-fc52b35c] {\n transition: left 0.4s;\n}\n.slide[data-v-fc52b35c] {\n position: absolute;\n top: 0;\n object-fit: contain;\n width: 100%;\n height: 100%;\n -webkit-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
/** | ||
* Checks if `value` is the | ||
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) | ||
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 0.1.0 | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is an object, else `false`. | ||
* @example | ||
* | ||
* _.isObject({}); | ||
* // => true | ||
* | ||
* _.isObject([1, 2, 3]); | ||
* // => true | ||
* | ||
* _.isObject(_.noop); | ||
* // => true | ||
* | ||
* _.isObject(null); | ||
* // => false | ||
*/ | ||
function isObject(value) { | ||
var type = typeof value; | ||
return !!value && (type == 'object' || type == 'function'); | ||
} | ||
}; | ||
/* scoped */ | ||
const __vue_scope_id__$1 = "data-v-fc52b35c"; | ||
/* module identifier */ | ||
const __vue_module_identifier__$1 = undefined; | ||
/* functional template */ | ||
const __vue_is_functional_template__$1 = false; | ||
/* style inject SSR */ | ||
/* style inject shadow dom */ | ||
/** | ||
* Checks if `value` is object-like. A value is object-like if it's not `null` | ||
* and has a `typeof` result of "object". | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 4.0.0 | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`. | ||
* @example | ||
* | ||
* _.isObjectLike({}); | ||
* // => true | ||
* | ||
* _.isObjectLike([1, 2, 3]); | ||
* // => true | ||
* | ||
* _.isObjectLike(_.noop); | ||
* // => false | ||
* | ||
* _.isObjectLike(null); | ||
* // => false | ||
*/ | ||
function isObjectLike(value) { | ||
return !!value && typeof value == 'object'; | ||
} | ||
const __vue_component__$1 = /*#__PURE__*/normalizeComponent( | ||
{ render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }, | ||
__vue_inject_styles__$1, | ||
__vue_script__$1, | ||
__vue_scope_id__$1, | ||
__vue_is_functional_template__$1, | ||
__vue_module_identifier__$1, | ||
false, | ||
createInjector, | ||
undefined, | ||
undefined | ||
); | ||
/** | ||
* Checks if `value` is classified as a `Symbol` primitive or object. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 4.0.0 | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`. | ||
* @example | ||
* | ||
* _.isSymbol(Symbol.iterator); | ||
* // => true | ||
* | ||
* _.isSymbol('abc'); | ||
* // => false | ||
*/ | ||
function isSymbol(value) { | ||
return typeof value == 'symbol' || | ||
(isObjectLike(value) && objectToString.call(value) == symbolTag); | ||
} | ||
var index = { | ||
install (Vue) { | ||
Vue.component('VZoomer', __vue_component__); | ||
Vue.component('VZoomerGallery', __vue_component__$1); | ||
}, | ||
// for locally register | ||
Zoomer: __vue_component__, | ||
Gallery: __vue_component__$1, | ||
}; | ||
/** | ||
* Converts `value` to a number. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @since 4.0.0 | ||
* @category Lang | ||
* @param {*} value The value to process. | ||
* @returns {number} Returns the number. | ||
* @example | ||
* | ||
* _.toNumber(3.2); | ||
* // => 3.2 | ||
* | ||
* _.toNumber(Number.MIN_VALUE); | ||
* // => 5e-324 | ||
* | ||
* _.toNumber(Infinity); | ||
* // => Infinity | ||
* | ||
* _.toNumber('3.2'); | ||
* // => 3.2 | ||
*/ | ||
function toNumber(value) { | ||
if (typeof value == 'number') { | ||
return value; | ||
} | ||
if (isSymbol(value)) { | ||
return NAN; | ||
} | ||
if (isObject(value)) { | ||
var other = typeof value.valueOf == 'function' ? value.valueOf() : value; | ||
value = isObject(other) ? (other + '') : other; | ||
} | ||
if (typeof value != 'string') { | ||
return value === 0 ? value : +value; | ||
} | ||
value = value.replace(reTrim, ''); | ||
var isBinary = reIsBinary.test(value); | ||
return (isBinary || reIsOctal.test(value)) | ||
? freeParseInt(value.slice(2), isBinary ? 2 : 8) | ||
: (reIsBadHex.test(value) ? NAN : +value); | ||
} | ||
return index; | ||
var lodash_debounce = debounce; | ||
/** | ||
* Detect double tap events | ||
* # Deals with: | ||
* - Time intervals between taps | ||
* - Swipe will stop the taps | ||
* # Usage: | ||
* let tapDetector = new TapDetector() | ||
* tapDetector.attach(this.$el) // in mounted | ||
* tapDetector.detach(this.$el) // in destroy | ||
* tapDetector.onSingle(callback) | ||
* tapDetector.onDouble(callback) | ||
*/ | ||
function TapDetector () { | ||
// Callbacks ----------------------------------------------------------------- | ||
let singleTapCallbacks = []; | ||
let doubleTapCallbacks = []; | ||
function triggerCallbacks (cbList, arg) { | ||
cbList.forEach(cbItem => { | ||
cbItem.call(null, arg); | ||
}); | ||
} | ||
this.onSingleTap = function (cb) { | ||
if (typeof cb === 'function' && !singleTapCallbacks.includes(cb)) { | ||
singleTapCallbacks.push(cb); | ||
} | ||
}; | ||
this.onDoubleTap = function (cb) { | ||
if (typeof cb === 'function' && !doubleTapCallbacks.includes(cb)) { | ||
doubleTapCallbacks.push(cb); | ||
} | ||
}; | ||
this.attach = function (dom) { | ||
if (!(dom instanceof Element)) { | ||
console.error('TapDetector.attach: arg must be an Element'); | ||
return | ||
} | ||
dom.addEventListener('touchstart', onTouchStart); | ||
dom.addEventListener('touchmove', onTouchMove); | ||
dom.addEventListener('touchend', onTouchEnd); | ||
dom.addEventListener('mousedown', onMouseDown); | ||
dom.addEventListener('mouseup', onMouseUp); | ||
dom.addEventListener('mousemove', onMouseMove); | ||
}; | ||
this.detach = function (dom) { | ||
dom.removeEventListener('touchstart', onTouchStart); | ||
dom.removeEventListener('touchmove', onTouchMove); | ||
dom.removeEventListener('touchend', onTouchEnd); | ||
dom.removeEventListener('mousedown', onMouseDown); | ||
dom.removeEventListener('mouseup', onMouseUp); | ||
dom.removeEventListener('mousemove', onMouseMove); | ||
}; | ||
// Main logic ---------------------------------------------------------------- | ||
// in touch mode mouse events will be disabled. Otherwise touches will | ||
// trigger both touchend end mouseup, i.e. one touch triggers two onPointerUp. | ||
let isTouchMode = false; | ||
let lastTapTimestamp = 0; | ||
let tappedCount = 0; | ||
let touchMovedLength = 0; | ||
let lastPointerX = 0; | ||
let lastPointerY = 0; | ||
function onTouchStart (ev) { | ||
isTouchMode = true; | ||
// console.log('onTouchStart') | ||
if (ev.touches.length === 1) { | ||
onPointerDown(ev.touches[0].clientX, ev.touches[0].clientY); | ||
} | ||
} | ||
function onTouchEnd (ev) { | ||
// console.log('onTouchEnd') | ||
if (ev.touches.length === 0) { | ||
onPointerUp(); | ||
} | ||
} | ||
function onTouchMove (ev) { | ||
// console.log('onTouchMove', ev) | ||
if (ev.touches.length === 1) { | ||
onPointerMove(ev.touches[0].clientX, ev.touches[0].clientY); | ||
} | ||
} | ||
function onMouseDown (ev) { | ||
if (isTouchMode) return | ||
// console.log('onMouseDown') | ||
onPointerDown(ev.clientX, ev.clientY); | ||
} | ||
function onMouseUp (ev) { | ||
if (isTouchMode) return | ||
// console.log('onMouseUp') | ||
onPointerUp(); | ||
} | ||
function onMouseMove (ev) { | ||
if (isTouchMode) return | ||
// console.log('onMouseMove', ev) | ||
if (ev.button === 0) { | ||
onPointerMove(ev.clientX, ev.clientY); | ||
} | ||
} | ||
function onPointerDown (x, y) { | ||
lastPointerX = x; | ||
lastPointerY = y; | ||
touchMovedLength = 0; | ||
} | ||
function onPointerUp () { | ||
let currTimeStamp = Date.now(); | ||
// console.log('touchMovedLength', touchMovedLength) | ||
if (touchMovedLength < 10) { | ||
// Only when no sliding two far is considered as a valid tap | ||
if (currTimeStamp - lastTapTimestamp < 300) { | ||
tappedCount += 1; | ||
} else { | ||
tappedCount = 1; | ||
} | ||
lastTapTimestamp = Date.now(); | ||
// console.log('tappedCount', tappedCount) | ||
triggerCallbacks(singleTapCallbacks, { | ||
clientX: lastPointerX, | ||
clientY: lastPointerY, | ||
}); | ||
if (tappedCount === 2) { | ||
triggerCallbacks(doubleTapCallbacks, { | ||
clientX: lastPointerX, | ||
clientY: lastPointerY, | ||
}); | ||
tappedCount = 0; // clear count on maximum tap count | ||
} | ||
} | ||
touchMovedLength = 0; | ||
} | ||
function onPointerMove (x, y) { | ||
let deltaX = lastPointerX - x; | ||
let deltaY = lastPointerY - y; | ||
let length = Math.sqrt(deltaX * deltaX + deltaY * deltaY); | ||
// console.log('onTouchMove length', length) | ||
touchMovedLength += length; | ||
lastPointerX = x; | ||
lastPointerY = y; | ||
} | ||
} | ||
// | ||
var script = { | ||
props: { | ||
minScale: { type: Number, default: 1 }, | ||
maxScale: { type: Number, default: 5 }, | ||
zoomed: { type: Boolean, default: false }, | ||
resetTrigger: { type: Number, default: 1e5 }, | ||
aspectRatio: { type: Number, default: 1 }, | ||
backgroundColor: { type: String, default: 'transparent' }, | ||
pivot: { type: String, default: 'cursor' }, // other options: image-center | ||
zoomingElastic: { type: Boolean, default: true }, | ||
limitTranslation: { type: Boolean, default: true }, | ||
doubleClickToZoom: { type: Boolean, default: true }, | ||
mouseWheelToZoom: { type: Boolean, default: true }, | ||
}, | ||
data () { | ||
return { | ||
// Container sizes, used to determin the initial zoomer size. | ||
// Need to reactive to window resizing. | ||
containerWidth: 1, | ||
containerHeight: 1, | ||
containerLeft: 0, | ||
containerTop: 0, | ||
// Store values: Interactions will at last change these values. | ||
// After rotation or resize, these values will keep still. | ||
// These three values are all relative to the container size. | ||
translateX: 0, | ||
animTranslateX: 0, | ||
translateY: 0, | ||
animTranslateY: 0, | ||
scale: 1, | ||
animScale: 1, | ||
// Mouse states | ||
lastFullWheelTime: 0, | ||
lastWheelTime: 0, | ||
lastWheelDirection: 'y', | ||
isPointerDown: false, | ||
pointerPosX: -1, | ||
pointerPosY: -1, | ||
twoFingerInitDist: 0, | ||
panLocked: true, | ||
// Others | ||
raf: null, | ||
tapDetector: null, | ||
} | ||
}, | ||
computed: { | ||
wrapperStyle () { | ||
let translateX = this.containerWidth * this.animTranslateX; | ||
let translateY = this.containerHeight * this.animTranslateY; | ||
return { | ||
transform: [ | ||
`translate(${ translateX }px, ${ translateY }px)`, | ||
`scale(${ this.animScale })`, | ||
].join(' ') | ||
} | ||
}, | ||
}, | ||
watch: { | ||
scale (val) { | ||
if (val !== 1) { | ||
this.$emit('update:zoomed', true); | ||
this.panLocked = false; | ||
} | ||
}, | ||
resetTrigger: 'reset', | ||
}, | ||
mounted () { | ||
this.tapDetector = new TapDetector(); | ||
this.tapDetector.attach(this.$el); | ||
if (this.doubleClickToZoom) { | ||
this.tapDetector.onDoubleTap(this.onDoubleTap); | ||
} | ||
// console.log('container size: ', this.containerWidth, this.containerHeight) | ||
window.addEventListener('resize', this.onWindowResize); | ||
this.onWindowResize(); | ||
this.refreshContainerPos(); | ||
this.loop(); | ||
}, | ||
destroyed () { | ||
this.tapDetector.detach(this.$el); | ||
window.removeEventListener('resize', this.onWindowResize); | ||
window.cancelAnimationFrame(this.raf); | ||
// console.log('destroy') | ||
}, | ||
methods: { | ||
// API --------------------------------------------------------------------- | ||
reset () { | ||
this.scale = 1; | ||
this.panLocked = true; | ||
this.translateX = 0; | ||
this.translateY = 0; | ||
}, | ||
zoomIn(scale = 2) { | ||
this.tryToScale(scale); | ||
this.onInteractionEnd(); | ||
}, | ||
zoomOut(scale = 0.5) { | ||
this.tryToScale(scale); | ||
this.onInteractionEnd(); | ||
}, | ||
// Main Logic -------------------------------------------------------------- | ||
// scale | ||
// Zoom the image with the point at the pointer(mouse or pinch center) pinned. | ||
// Simplify: This can be regard as vector pointer to old-image-center scaling. | ||
tryToScale (scaleDelta) { | ||
let newScale = this.scale * scaleDelta; | ||
if (this.zoomingElastic) { | ||
// damping | ||
if (newScale < this.minScale || newScale > this.maxScale) { | ||
let log = Math.log2(scaleDelta); | ||
log *= 0.2; | ||
scaleDelta = Math.pow(2, log); | ||
newScale = this.scale * scaleDelta; | ||
} | ||
} else { | ||
if (newScale < this.minScale) newScale = this.minScale; | ||
else if (newScale > this.maxScale) newScale = this.maxScale; | ||
} | ||
scaleDelta = newScale / this.scale; | ||
this.scale = newScale; | ||
if (this.pivot !== 'image-center') { | ||
let normMousePosX = (this.pointerPosX - this.containerLeft) / this.containerWidth; | ||
let normMousePosY = (this.pointerPosY - this.containerTop) / this.containerHeight; | ||
this.translateX = (0.5 + this.translateX - normMousePosX) * scaleDelta + normMousePosX - 0.5; | ||
this.translateY = (0.5 + this.translateY - normMousePosY) * scaleDelta + normMousePosY - 0.5; | ||
} | ||
}, | ||
setPointerPosCenter () { | ||
this.pointerPosX = this.containerLeft + this.containerWidth / 2; | ||
this.pointerPosY = this.containerTop + this.containerHeight / 2; | ||
}, | ||
// pan | ||
onPointerMove (newMousePosX, newMousePosY) { | ||
if (this.isPointerDown) { | ||
let pixelDeltaX = newMousePosX - this.pointerPosX; | ||
let pixelDeltaY = newMousePosY - this.pointerPosY; | ||
// console.log('pixelDeltaX, pixelDeltaY', pixelDeltaX, pixelDeltaY) | ||
if (!this.panLocked) { | ||
this.translateX += pixelDeltaX / this.containerWidth; | ||
this.translateY += pixelDeltaY / this.containerHeight; | ||
} | ||
} | ||
this.pointerPosX = newMousePosX; | ||
this.pointerPosY = newMousePosY; | ||
}, | ||
onInteractionEnd: lodash_debounce(function () { | ||
this.limit(); | ||
this.panLocked = this.scale === 1; | ||
this.$emit('update:zoomed', !this.panLocked); | ||
}, 100), | ||
// limit the scale between max and min and the translate within the viewport | ||
limit () { | ||
// scale | ||
if (this.scale < this.minScale) { | ||
this.scale = this.minScale; | ||
// FIXME this sometimes will not reset when pinching in | ||
// this.tryToScale(this.minScale / this.scale) | ||
} else if (this.scale > this.maxScale) { | ||
this.tryToScale(this.maxScale / this.scale); | ||
} | ||
// translate | ||
if (this.limitTranslation) { | ||
let translateLimit = this.calcTranslateLimit(); | ||
if (Math.abs(this.translateX) > translateLimit.x) { | ||
this.translateX *= translateLimit.x / Math.abs(this.translateX); | ||
} | ||
if (Math.abs(this.translateY) > translateLimit.y) { | ||
this.translateY *= translateLimit.y / Math.abs(this.translateY); | ||
} | ||
} | ||
}, | ||
calcTranslateLimit () { | ||
if (this.getMarginDirection() === 'y') { | ||
let imageToContainerRatio = this.containerWidth / this.aspectRatio / this.containerHeight; | ||
let translateLimitY = (this.scale * imageToContainerRatio - 1) / 2; | ||
if (translateLimitY < 0) translateLimitY = 0; | ||
return { | ||
x: (this.scale - 1) / 2, | ||
y: translateLimitY, | ||
} | ||
} else { | ||
let imageToContainerRatio = this.containerHeight * this.aspectRatio / this.containerWidth; | ||
let translateLimitX = (this.scale * imageToContainerRatio - 1) / 2; | ||
if (translateLimitX < 0) translateLimitX = 0; | ||
return { | ||
x: translateLimitX, | ||
y: (this.scale - 1) / 2, | ||
} | ||
} | ||
}, | ||
getMarginDirection () { | ||
let containerRatio = this.containerWidth / this.containerHeight; | ||
return containerRatio > this.aspectRatio ? 'x' : 'y' | ||
}, | ||
onDoubleTap (ev) { | ||
if (this.scale === 1) { | ||
if (ev.clientX > 0) { | ||
this.pointerPosX = ev.clientX; | ||
this.pointerPosY = ev.clientY; | ||
} | ||
this.tryToScale(Math.min(3, this.maxScale)); | ||
} else { | ||
this.reset(); | ||
} | ||
this.onInteractionEnd(); | ||
}, | ||
// reactive | ||
onWindowResize () { | ||
let styles = window.getComputedStyle(this.$el); | ||
this.containerWidth = parseFloat(styles.width); | ||
this.containerHeight = parseFloat(styles.height); | ||
this.setPointerPosCenter(); | ||
this.limit(); | ||
}, | ||
refreshContainerPos () { | ||
let rect = this.$el.getBoundingClientRect(); | ||
this.containerLeft = rect.left; | ||
this.containerTop = rect.top; | ||
}, | ||
loop () { | ||
this.animScale = this.gainOn(this.animScale, this.scale); | ||
this.animTranslateX = this.gainOn(this.animTranslateX, this.translateX); | ||
this.animTranslateY = this.gainOn(this.animTranslateY, this.translateY); | ||
this.raf = window.requestAnimationFrame(this.loop); | ||
// console.log('loop', this.raf) | ||
}, | ||
gainOn (from, to) { | ||
let delta = (to - from) * 0.3; | ||
// console.log('gainOn', from, to, from + delta) | ||
if (Math.abs(delta) > 1e-5) { | ||
return from + delta | ||
} else { | ||
return to | ||
} | ||
}, | ||
// Mouse Events ------------------------------------------------------------ | ||
// Mouse wheel scroll, TrackPad pinch or TrackPad scroll | ||
onMouseWheel (ev) { | ||
if (!this.mouseWheelToZoom) return | ||
// prevent is used to stop the page scroll elastic effects | ||
ev.preventDefault(); | ||
if (ev.detail) ev.wheelDelta = ev.detail * -10; | ||
let currTime = Date.now(); | ||
if (Math.abs(ev.wheelDelta) === 120) { | ||
// Throttle the TouchPad pinch on Mac, or it will be too sensitive | ||
if (currTime - this.lastFullWheelTime > 50) { | ||
this.onMouseWheelDo(ev.wheelDelta); | ||
this.lastFullWheelTime = currTime; | ||
} | ||
} else { | ||
if (currTime - this.lastWheelTime > 50 && typeof ev.deltaX === 'number') { | ||
this.lastWheelDirection = (ev.detail == 0 && Math.abs(ev.deltaX) > Math.abs(ev.deltaY)) ? 'x' : 'y'; | ||
if (this.lastWheelDirection === 'x') { | ||
this.$emit('swipe', ev.deltaX > 0 ? 'left' : 'right'); | ||
} | ||
} | ||
if (this.lastWheelDirection === 'y') { | ||
this.onMouseWheelDo(ev.wheelDelta); | ||
} | ||
} | ||
this.lastWheelTime = currTime; | ||
}, | ||
onMouseWheelDo (wheelDelta) { | ||
// Value basis: One mouse wheel (wheelDelta=+-120) means 1.25/0.8 scale. | ||
let scaleDelta = Math.pow(1.25, wheelDelta / 120); | ||
this.tryToScale(scaleDelta); | ||
this.onInteractionEnd(); | ||
}, | ||
onMouseDown (ev) { | ||
this.refreshContainerPos(); | ||
this.isPointerDown = true; | ||
// Open the context menu then click other place will skip the mousemove events. | ||
// This will cause the pointerPosX/Y NOT sync, then we will need to fix it on mousedown event. | ||
this.pointerPosX = ev.clientX; | ||
this.pointerPosY = ev.clientY; | ||
// console.log('onMouseDown', ev) | ||
}, | ||
onMouseUp (ev) { | ||
this.isPointerDown = false; | ||
this.onInteractionEnd(); | ||
}, | ||
onMouseMove (ev) { | ||
this.onPointerMove(ev.clientX, ev.clientY); | ||
// console.log('onMouseMove client, offset', ev.clientX, ev.clientY) | ||
}, | ||
// Touch Events ------------------------------------------------------------ | ||
onTouchStart (ev) { | ||
if (ev.touches.length === 1) { | ||
this.refreshContainerPos(); | ||
this.pointerPosX = ev.touches[0].clientX; | ||
this.pointerPosY = ev.touches[0].clientY; | ||
this.isPointerDown = true; | ||
} else if (ev.touches.length === 2) { | ||
this.isPointerDown = true; | ||
// pos | ||
this.pointerPosX = (ev.touches[0].clientX + ev.touches[1].clientX) / 2; | ||
this.pointerPosY = (ev.touches[0].clientY + ev.touches[1].clientY) / 2; | ||
// dist | ||
let distX = ev.touches[0].clientX - ev.touches[1].clientX; | ||
let distY = ev.touches[0].clientY - ev.touches[1].clientY; | ||
this.twoFingerInitDist = Math.sqrt(distX * distX + distY * distY); | ||
} | ||
// console.log('onTouchStart', ev.touches) | ||
}, | ||
onTouchEnd (ev) { | ||
if (ev.touches.length === 0) { | ||
this.isPointerDown = false; | ||
// Near 1 to set 1 | ||
if (Math.abs(this.scale - 1) < 0.1) this.scale = 1; | ||
this.onInteractionEnd(); | ||
} else if (ev.touches.length === 1) { | ||
this.pointerPosX = ev.touches[0].clientX; | ||
this.pointerPosY = ev.touches[0].clientY; | ||
} | ||
// console.log('onTouchEnd', ev.touches.length) | ||
}, | ||
onTouchMove (ev) { | ||
if (ev.touches.length === 1) { | ||
this.onPointerMove(ev.touches[0].clientX, ev.touches[0].clientY); | ||
} else if (ev.touches.length === 2) { | ||
// pos | ||
let newMousePosX = (ev.touches[0].clientX + ev.touches[1].clientX) / 2; | ||
let newMousePosY = (ev.touches[0].clientY + ev.touches[1].clientY) / 2; | ||
this.onPointerMove(newMousePosX, newMousePosY); | ||
this.pointerPosX = newMousePosX; | ||
this.pointerPosY = newMousePosY; | ||
// dist | ||
let distX = ev.touches[0].clientX - ev.touches[1].clientX; | ||
let distY = ev.touches[0].clientY - ev.touches[1].clientY; | ||
let newTwoFingerDist = Math.sqrt(distX * distX + distY * distY); | ||
this.tryToScale(newTwoFingerDist / this.twoFingerInitDist); | ||
this.twoFingerInitDist = newTwoFingerDist; | ||
} | ||
// console.log('onTouchMove', this.pointerPosX, this.pointerPosY) | ||
}, | ||
}, | ||
}; | ||
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier | ||
/* server only */ | ||
, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { | ||
if (typeof shadowMode !== 'boolean') { | ||
createInjectorSSR = createInjector; | ||
createInjector = shadowMode; | ||
shadowMode = false; | ||
} // Vue.extend constructor export interop. | ||
var options = typeof script === 'function' ? script.options : script; // render functions | ||
if (template && template.render) { | ||
options.render = template.render; | ||
options.staticRenderFns = template.staticRenderFns; | ||
options._compiled = true; // functional template | ||
if (isFunctionalTemplate) { | ||
options.functional = true; | ||
} | ||
} // scopedId | ||
if (scopeId) { | ||
options._scopeId = scopeId; | ||
} | ||
var hook; | ||
if (moduleIdentifier) { | ||
// server build | ||
hook = function hook(context) { | ||
// 2.3 injection | ||
context = context || // cached call | ||
this.$vnode && this.$vnode.ssrContext || // stateful | ||
this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional | ||
// 2.2 with runInNewContext: true | ||
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { | ||
context = __VUE_SSR_CONTEXT__; | ||
} // inject component styles | ||
if (style) { | ||
style.call(this, createInjectorSSR(context)); | ||
} // register component module identifier for async chunk inference | ||
if (context && context._registeredComponents) { | ||
context._registeredComponents.add(moduleIdentifier); | ||
} | ||
}; // used by ssr in case component is cached and beforeCreate | ||
// never gets called | ||
options._ssrRegister = hook; | ||
} else if (style) { | ||
hook = shadowMode ? function () { | ||
style.call(this, createInjectorShadow(this.$root.$options.shadowRoot)); | ||
} : function (context) { | ||
style.call(this, createInjector(context)); | ||
}; | ||
} | ||
if (hook) { | ||
if (options.functional) { | ||
// register for functional component in vue file | ||
var originalRender = options.render; | ||
options.render = function renderWithStyleInjection(h, context) { | ||
hook.call(context); | ||
return originalRender(h, context); | ||
}; | ||
} else { | ||
// inject component registration as beforeCreate hook | ||
var existing = options.beforeCreate; | ||
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; | ||
} | ||
} | ||
return script; | ||
} | ||
var normalizeComponent_1 = normalizeComponent; | ||
var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); | ||
function createInjector(context) { | ||
return function (id, style) { | ||
return addStyle(id, style); | ||
}; | ||
} | ||
var HEAD; | ||
var styles = {}; | ||
function addStyle(id, css) { | ||
var group = isOldIE ? css.media || 'default' : id; | ||
var style = styles[group] || (styles[group] = { | ||
ids: new Set(), | ||
styles: [] | ||
}); | ||
if (!style.ids.has(id)) { | ||
style.ids.add(id); | ||
var code = css.source; | ||
if (css.map) { | ||
// https://developer.chrome.com/devtools/docs/javascript-debugging | ||
// this makes source maps inside style tags work properly in Chrome | ||
code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 | ||
code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; | ||
} | ||
if (!style.element) { | ||
style.element = document.createElement('style'); | ||
style.element.type = 'text/css'; | ||
if (css.media) style.element.setAttribute('media', css.media); | ||
if (HEAD === undefined) { | ||
HEAD = document.head || document.getElementsByTagName('head')[0]; | ||
} | ||
HEAD.appendChild(style.element); | ||
} | ||
if ('styleSheet' in style.element) { | ||
style.styles.push(code); | ||
style.element.styleSheet.cssText = style.styles.filter(Boolean).join('\n'); | ||
} else { | ||
var index = style.ids.size - 1; | ||
var textNode = document.createTextNode(code); | ||
var nodes = style.element.childNodes; | ||
if (nodes[index]) style.element.removeChild(nodes[index]); | ||
if (nodes.length) style.element.insertBefore(textNode, nodes[index]);else style.element.appendChild(textNode); | ||
} | ||
} | ||
} | ||
var browser = createInjector; | ||
/* script */ | ||
const __vue_script__ = script; | ||
/* template */ | ||
var __vue_render__ = function() { | ||
var _vm = this; | ||
var _h = _vm.$createElement; | ||
var _c = _vm._self._c || _h; | ||
return _c( | ||
"div", | ||
{ | ||
staticClass: "vue-zoomer", | ||
style: { backgroundColor: _vm.backgroundColor }, | ||
on: { | ||
mousewheel: _vm.onMouseWheel, | ||
DOMMouseScroll: _vm.onMouseWheel, | ||
mousedown: _vm.onMouseDown, | ||
mouseup: _vm.onMouseUp, | ||
mousemove: _vm.onMouseMove, | ||
mouseout: _vm.setPointerPosCenter, | ||
touchstart: _vm.onTouchStart, | ||
touchend: _vm.onTouchEnd, | ||
touchmove: _vm.onTouchMove | ||
} | ||
}, | ||
[ | ||
_c( | ||
"div", | ||
{ staticClass: "zoomer", style: _vm.wrapperStyle }, | ||
[_vm._t("default")], | ||
2 | ||
) | ||
] | ||
) | ||
}; | ||
var __vue_staticRenderFns__ = []; | ||
__vue_render__._withStripped = true; | ||
/* style */ | ||
const __vue_inject_styles__ = function (inject) { | ||
if (!inject) return | ||
inject("data-v-33e6a267_0", { source: ".vue-zoomer[data-v-33e6a267] {\n overflow: hidden;\n}\n.zoomer[data-v-33e6a267] {\n transform-origin: 50% 50%;\n width: 100%;\n height: 100%;\n}\n.zoomer > img[data-v-33e6a267] {\n vertical-align: top;\n user-drag: none;\n -webkit-user-drag: none;\n -moz-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
}; | ||
/* scoped */ | ||
const __vue_scope_id__ = "data-v-33e6a267"; | ||
/* module identifier */ | ||
const __vue_module_identifier__ = undefined; | ||
/* functional template */ | ||
const __vue_is_functional_template__ = false; | ||
/* style inject SSR */ | ||
/* style inject shadow dom */ | ||
const __vue_component__ = /*#__PURE__*/normalizeComponent_1( | ||
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, | ||
__vue_inject_styles__, | ||
__vue_script__, | ||
__vue_scope_id__, | ||
__vue_is_functional_template__, | ||
__vue_module_identifier__, | ||
false, | ||
browser, | ||
undefined, | ||
undefined | ||
); | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// | ||
const SLIDE_WIDTH_THRESH = 50; // in px | ||
var script$1 = { | ||
props: { | ||
value: { type: Number, required: true }, | ||
list: { type: Array, required: true }, | ||
backgroundColor: { type: String, default: '#333' }, | ||
pivot: { type: String, default: 'cursor' }, | ||
zoomingElastic: { type: Boolean, default: true }, | ||
limitTranslation: { type: Boolean, default: true }, | ||
doubleClickToZoom: { type: Boolean, default: true }, | ||
mouseWheelToZoom: { type: Boolean, default: true }, | ||
}, | ||
data () { | ||
return { | ||
// env states | ||
containerWidth: 1, | ||
containerHeight: 1, | ||
// main states | ||
selIndex: this.value, | ||
animSelIndex: this.value, | ||
currentZoomed: false, | ||
autoSliding: false, | ||
imageAspectRatios: [], // aspect ratio (width / height) of images | ||
// interaction states | ||
isPointerDown: false, | ||
lastPointerX: 0, | ||
slideOffsetX: 0, | ||
} | ||
}, | ||
computed: { | ||
middleStyle () { | ||
return { | ||
left: `${ 0 + this.slideOffsetX }px`, | ||
} | ||
}, | ||
leftStyle () { | ||
return { | ||
left: `${ -this.containerWidth + this.slideOffsetX }px`, | ||
} | ||
}, | ||
rightStyle () { | ||
return { | ||
left: `${ this.containerWidth + this.slideOffsetX }px`, | ||
} | ||
}, | ||
slideThresh () { | ||
return Math.max(SLIDE_WIDTH_THRESH, this.containerWidth * 0.1) | ||
}, | ||
}, | ||
watch: { | ||
value (val) { | ||
if (val !== this.animSelIndex) { | ||
this.selIndex = val; | ||
this.animSelIndex = val; | ||
} | ||
}, | ||
selIndex() { | ||
this.$nextTick(() => { | ||
this.$refs.zoomers.forEach(zoomer => { | ||
zoomer.refreshContainerPos(); | ||
}); | ||
}); | ||
}, | ||
}, | ||
mounted () { | ||
window.addEventListener('resize', this.onWindowResize); | ||
this.onWindowResize(); | ||
}, | ||
destroyed () { | ||
window.removeEventListener('resize', this.onWindowResize); | ||
}, | ||
methods: { | ||
// api --------------------------------------------------------------------- | ||
reset () { | ||
this.$refs.zoomers.forEach(zoomer => { | ||
zoomer.reset(); | ||
}); | ||
}, | ||
zoomIn (scale) { | ||
if (this.$refs.zoomers[1]) this.$refs.zoomers[1].zoomIn(scale); | ||
}, | ||
zoomOut (scale) { | ||
if (this.$refs.zoomers[1]) this.$refs.zoomers[1].zoomOut(scale); | ||
}, | ||
// events ------------------------------------------------------------------ | ||
onWindowResize () { | ||
let styles = window.getComputedStyle(this.$el); | ||
this.containerWidth = parseFloat(styles.width); | ||
this.containerHeight = parseFloat(styles.height); | ||
}, | ||
onPointerMove (deltaX) { | ||
if (this.isPointerDown && !this.currentZoomed) { | ||
let factor = ( | ||
(this.selIndex === 0 && deltaX > 0 && this.slideOffsetX + deltaX > 0) || | ||
(this.selIndex === this.list.length - 1 && deltaX < 0 && this.slideOffsetX + deltaX < 0) | ||
) ? 0.3 : 1; | ||
this.slideOffsetX += deltaX * factor; | ||
} | ||
}, | ||
onPointerUp () { | ||
if (this.slideOffsetX < -this.slideThresh) { | ||
// next page | ||
this.paginate(1); | ||
} else if (this.slideOffsetX > this.slideThresh) { | ||
// prev page | ||
this.paginate(-1); | ||
} else { | ||
// only apply the animation | ||
this.paginate(0); | ||
} | ||
}, | ||
// Stop Firefox dragging the image | ||
onImageDragStart(ev) { | ||
ev.preventDefault(); | ||
return false | ||
}, | ||
paginate (deltaIndex) { | ||
let targetIndex = this.selIndex + deltaIndex; | ||
if (targetIndex < 0 || targetIndex >= this.list.length) { | ||
this.slideOffsetX = 0; | ||
return | ||
} | ||
this.slideOffsetX = this.containerWidth * -deltaIndex; | ||
this.autoSliding = true; | ||
// update the selIndex before the animation to remove the delay feeling | ||
this.$emit('input', targetIndex); | ||
this.animSelIndex = targetIndex; | ||
setTimeout(() => { | ||
this.selIndex = targetIndex; | ||
this.slideOffsetX = 0; | ||
this.autoSliding = false; | ||
}, 400); | ||
}, | ||
onMouseDown (ev) { | ||
this.isPointerDown = true; | ||
this.lastPointerX = ev.clientX; | ||
}, | ||
onMouseUp (ev) { | ||
this.isPointerDown = false; | ||
this.onPointerUp(); | ||
}, | ||
onMouseMove (ev) { | ||
if (this.isPointerDown) { | ||
this.onPointerMove(ev.clientX - this.lastPointerX); | ||
this.lastPointerX = ev.clientX; | ||
} | ||
}, | ||
onTouchStart (ev) { | ||
if (ev.touches.length === 1) { | ||
this.isPointerDown = true; | ||
this.lastPointerX = ev.touches[0].clientX; | ||
} | ||
}, | ||
onTouchEnd (ev) { | ||
if (ev.touches.length === 0) { | ||
this.isPointerDown = false; | ||
this.onPointerUp(); | ||
} | ||
}, | ||
onTouchMove (ev) { | ||
if (ev.touches.length === 1) { | ||
this.onPointerMove(ev.touches[0].clientX - this.lastPointerX); | ||
this.lastPointerX = ev.touches[0].clientX; | ||
} | ||
}, | ||
onImageLoad (index, ev) { | ||
let aspectRatio = ev.target.naturalWidth / ev.target.naturalHeight; | ||
this.$set(this.imageAspectRatios, index, aspectRatio); | ||
}, | ||
onImageSwipe (direction) { | ||
this.paginate(direction == 'right' ? -1 : 1); | ||
}, | ||
}, | ||
}; | ||
/* script */ | ||
const __vue_script__$1 = script$1; | ||
/* template */ | ||
var __vue_render__$1 = function() { | ||
var _vm = this; | ||
var _h = _vm.$createElement; | ||
var _c = _vm._self._c || _h; | ||
return _c( | ||
"div", | ||
{ | ||
staticClass: "vue-zoomer-gallery", | ||
class: { | ||
anim: _vm.autoSliding && !_vm.isPointerDown | ||
}, | ||
style: { | ||
"background-color": _vm.backgroundColor | ||
}, | ||
on: { | ||
mousemove: _vm.onMouseMove, | ||
mousedown: _vm.onMouseDown, | ||
mouseout: _vm.onMouseUp, | ||
mouseup: _vm.onMouseUp, | ||
touchstart: _vm.onTouchStart, | ||
touchend: _vm.onTouchEnd, | ||
touchmove: function($event) { | ||
$event.preventDefault(); | ||
return _vm.onTouchMove($event) | ||
} | ||
} | ||
}, | ||
_vm._l(3, function(n, i) { | ||
return _c( | ||
"v-zoomer", | ||
{ | ||
key: i + "-" + _vm.selIndex, | ||
ref: "zoomers", | ||
refInFor: true, | ||
staticClass: "slide", | ||
class: ["left", "middle", "right"][i], | ||
style: [_vm.leftStyle, _vm.middleStyle, _vm.rightStyle][i], | ||
attrs: { | ||
"max-scale": 10, | ||
zoomed: _vm.currentZoomed, | ||
"reset-trigger": i, | ||
"aspect-ratio": _vm.imageAspectRatios[_vm.selIndex + i - 1] || 1, | ||
pivot: _vm.pivot, | ||
"zooming-elastic": _vm.zoomingElastic, | ||
"limit-translation": _vm.limitTranslation, | ||
"double-click-to-zoom": _vm.doubleClickToZoom, | ||
"mouse-wheel-to-zoom": _vm.mouseWheelToZoom | ||
}, | ||
on: { | ||
"update:zoomed": function($event) { | ||
_vm.currentZoomed = $event; | ||
}, | ||
swipe: _vm.onImageSwipe | ||
} | ||
}, | ||
[ | ||
_vm.selIndex + i - 1 > -1 && _vm.selIndex + i - 1 < _vm.list.length | ||
? _c("img", { | ||
staticStyle: { | ||
"object-fit": "contain", | ||
width: "100%", | ||
height: "100%" | ||
}, | ||
attrs: { | ||
src: _vm.list[_vm.selIndex + i - 1], | ||
draggable: "false" | ||
}, | ||
on: { | ||
load: function($event) { | ||
return _vm.onImageLoad(_vm.selIndex + i - 1, $event) | ||
}, | ||
dragstart: _vm.onImageDragStart | ||
} | ||
}) | ||
: _vm._e() | ||
] | ||
) | ||
}), | ||
1 | ||
) | ||
}; | ||
var __vue_staticRenderFns__$1 = []; | ||
__vue_render__$1._withStripped = true; | ||
/* style */ | ||
const __vue_inject_styles__$1 = function (inject) { | ||
if (!inject) return | ||
inject("data-v-ea62d372_0", { source: ".vue-zoomer-gallery[data-v-ea62d372] {\n position: relative;\n overflow: hidden;\n user-select: none;\n min-width: 100px;\n min-height: 100px;\n}\n.vue-zoomer-gallery > *[data-v-ea62d372] {\n display: inline-block;\n}\n.vue-zoomer-gallery.anim .slide[data-v-ea62d372] {\n transition: left 0.4s;\n}\n.slide[data-v-ea62d372] {\n position: absolute;\n top: 0;\n object-fit: contain;\n width: 100%;\n height: 100%;\n -webkit-user-drag: none;\n}\n", map: undefined, media: undefined }); | ||
}; | ||
/* scoped */ | ||
const __vue_scope_id__$1 = "data-v-ea62d372"; | ||
/* module identifier */ | ||
const __vue_module_identifier__$1 = undefined; | ||
/* functional template */ | ||
const __vue_is_functional_template__$1 = false; | ||
/* style inject SSR */ | ||
/* style inject shadow dom */ | ||
const __vue_component__$1 = /*#__PURE__*/normalizeComponent_1( | ||
{ render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }, | ||
__vue_inject_styles__$1, | ||
__vue_script__$1, | ||
__vue_scope_id__$1, | ||
__vue_is_functional_template__$1, | ||
__vue_module_identifier__$1, | ||
false, | ||
browser, | ||
undefined, | ||
undefined | ||
); | ||
var index = { | ||
install (Vue) { | ||
Vue.component('VZoomer', __vue_component__); | ||
Vue.component('VZoomerGallery', __vue_component__$1); | ||
}, | ||
}; | ||
return index; | ||
}))); |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).VueZoomer=t()}(this,(function(){"use strict";var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},t=/^\s+|\s+$/g,i=/^[-+]0x[0-9a-f]+$/i,n=/^0b[01]+$/i,o=/^0o[0-7]+$/i,s=parseInt,a="object"==typeof e&&e&&e.Object===Object&&e,r="object"==typeof self&&self&&self.Object===Object&&self,l=a||r||Function("return this")(),h=Object.prototype.toString,c=Math.max,u=Math.min,d=function(){return l.Date.now()};function m(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function f(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Symbol]"==h.call(e)}(e))return NaN;if(m(e)){var a="function"==typeof e.valueOf?e.valueOf():e;e=m(a)?a+"":a}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(t,"");var r=n.test(e);return r||o.test(e)?s(e.slice(2),r?2:8):i.test(e)?NaN:+e}function p(){let e=[],t=[];function i(e,t){e.forEach(e=>{e.call(null,t)})}this.onSingleTap=function(t){"function"!=typeof t||e.includes(t)||e.push(t)},this.onDoubleTap=function(e){"function"!=typeof e||t.includes(e)||t.push(e)},this.attach=function(e){e instanceof Element?(e.addEventListener("touchstart",h),e.addEventListener("touchmove",u),e.addEventListener("touchend",c),e.addEventListener("mousedown",d),e.addEventListener("mouseup",m),e.addEventListener("mousemove",f)):console.error("TapDetector.attach: arg must be an Element")},this.detach=function(e){e.removeEventListener("touchstart",h),e.removeEventListener("touchmove",u),e.removeEventListener("touchend",c),e.removeEventListener("mousedown",d),e.removeEventListener("mouseup",m),e.removeEventListener("mousemove",f)};let n=!1,o=0,s=0,a=0,r=0,l=0;function h(e){n=!0,1===e.touches.length&&p(e.touches[0].clientX,e.touches[0].clientY)}function c(e){0===e.touches.length&&g()}function u(e){1===e.touches.length&&v(e.touches[0].clientX,e.touches[0].clientY)}function d(e){n||p(e.clientX,e.clientY)}function m(e){n||g()}function f(e){n||0===e.button&&v(e.clientX,e.clientY)}function p(e,t){r=e,l=t,a=0}function g(){let n=Date.now();a<10&&(n-o<300?s+=1:s=1,o=Date.now(),i(e,{clientX:r,clientY:l}),2===s&&(i(t,{clientX:r,clientY:l}),s=0)),a=0}function v(e,t){let i=r-e,n=l-t,o=Math.sqrt(i*i+n*n);a+=o,r=e,l=t}}var g={props:{minScale:{type:Number,default:1},maxScale:{type:Number,default:5},zoomed:{type:Boolean,default:!1},resetTrigger:{type:Number,default:1e5},aspectRatio:{type:Number,default:1},backgroundColor:{type:String,default:"transparent"},pivot:{type:String,default:"cursor"},zoomingElastic:{type:Boolean,default:!0},limitTranslation:{type:Boolean,default:!0},doubleClickToZoom:{type:Boolean,default:!0},mouseWheelToZoom:{type:Boolean,default:!0}},data:()=>({containerWidth:1,containerHeight:1,containerLeft:0,containerTop:0,translateX:0,animTranslateX:0,translateY:0,animTranslateY:0,scale:1,animScale:1,lastFullWheelTime:0,lastWheelTime:0,lastWheelDirection:"y",isPointerDown:!1,pointerPosX:-1,pointerPosY:-1,twoFingerInitDist:0,panLocked:!0,raf:null,tapDetector:null}),computed:{wrapperStyle(){return{transform:[`translate(${this.containerWidth*this.animTranslateX}px, ${this.containerHeight*this.animTranslateY}px)`,`scale(${this.animScale})`].join(" ")}}},watch:{scale(e){1!==e&&(this.$emit("update:zoomed",!0),this.panLocked=!1)},resetTrigger:"reset"},mounted(){this.tapDetector=new p,this.tapDetector.attach(this.$el),this.doubleClickToZoom&&this.tapDetector.onDoubleTap(this.onDoubleTap),window.addEventListener("resize",this.onWindowResize),this.onWindowResize(),this.refreshContainerPos(),this.loop()},destroyed(){this.tapDetector.detach(this.$el),window.removeEventListener("resize",this.onWindowResize),window.cancelAnimationFrame(this.raf)},methods:{reset(){this.scale=1,this.panLocked=!0,this.translateX=0,this.translateY=0},zoomIn(e=2){this.tryToScale(e),this.onInteractionEnd()},zoomOut(e=.5){this.tryToScale(e),this.onInteractionEnd()},tryToScale(e){let t=this.scale*e;if(this.zoomingElastic){if(t<this.minScale||t>this.maxScale){let i=Math.log2(e);i*=.2,e=Math.pow(2,i),t=this.scale*e}}else t<this.minScale?t=this.minScale:t>this.maxScale&&(t=this.maxScale);if(e=t/this.scale,this.scale=t,"image-center"!==this.pivot){let t=(this.pointerPosX-this.containerLeft)/this.containerWidth,i=(this.pointerPosY-this.containerTop)/this.containerHeight;this.translateX=(.5+this.translateX-t)*e+t-.5,this.translateY=(.5+this.translateY-i)*e+i-.5}},setPointerPosCenter(){this.pointerPosX=this.containerLeft+this.containerWidth/2,this.pointerPosY=this.containerTop+this.containerHeight/2},onPointerMove(e,t){if(this.isPointerDown){let i=e-this.pointerPosX,n=t-this.pointerPosY;this.panLocked||(this.translateX+=i/this.containerWidth,this.translateY+=n/this.containerHeight)}this.pointerPosX=e,this.pointerPosY=t},onInteractionEnd:function(e,t,i){var n,o,s,a,r,l,h=0,p=!1,g=!1,v=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function y(t){var i=n,s=o;return n=o=void 0,h=t,a=e.apply(s,i)}function w(e){return h=e,r=setTimeout(X,t),p?y(e):a}function T(e){var i=e-l;return void 0===l||i>=t||i<0||g&&e-h>=s}function X(){var e=d();if(T(e))return S(e);r=setTimeout(X,function(e){var i=t-(e-l);return g?u(i,s-(e-h)):i}(e))}function S(e){return r=void 0,v&&n?y(e):(n=o=void 0,a)}function b(){var e=d(),i=T(e);if(n=arguments,o=this,l=e,i){if(void 0===r)return w(l);if(g)return r=setTimeout(X,t),y(l)}return void 0===r&&(r=setTimeout(X,t)),a}return t=f(t)||0,m(i)&&(p=!!i.leading,s=(g="maxWait"in i)?c(f(i.maxWait)||0,t):s,v="trailing"in i?!!i.trailing:v),b.cancel=function(){void 0!==r&&clearTimeout(r),h=0,n=l=o=r=void 0},b.flush=function(){return void 0===r?a:S(d())},b}((function(){this.limit(),this.panLocked=1===this.scale,this.$emit("update:zoomed",!this.panLocked)}),100),limit(){if(this.scale<this.minScale?this.scale=this.minScale:this.scale>this.maxScale&&this.tryToScale(this.maxScale/this.scale),this.limitTranslation){let e=this.calcTranslateLimit();Math.abs(this.translateX)>e.x&&(this.translateX*=e.x/Math.abs(this.translateX)),Math.abs(this.translateY)>e.y&&(this.translateY*=e.y/Math.abs(this.translateY))}},calcTranslateLimit(){if("y"===this.getMarginDirection()){let e=this.containerWidth/this.aspectRatio/this.containerHeight,t=(this.scale*e-1)/2;return t<0&&(t=0),{x:(this.scale-1)/2,y:t}}{let e=this.containerHeight*this.aspectRatio/this.containerWidth,t=(this.scale*e-1)/2;return t<0&&(t=0),{x:t,y:(this.scale-1)/2}}},getMarginDirection(){return this.containerWidth/this.containerHeight>this.aspectRatio?"x":"y"},onDoubleTap(e){1===this.scale?(e.clientX>0&&(this.pointerPosX=e.clientX,this.pointerPosY=e.clientY),this.tryToScale(Math.min(3,this.maxScale))):this.reset(),this.onInteractionEnd()},onWindowResize(){let e=window.getComputedStyle(this.$el);this.containerWidth=parseFloat(e.width),this.containerHeight=parseFloat(e.height),this.setPointerPosCenter(),this.limit()},refreshContainerPos(){let e=this.$el.getBoundingClientRect();this.containerLeft=e.left,this.containerTop=e.top},loop(){this.animScale=this.gainOn(this.animScale,this.scale),this.animTranslateX=this.gainOn(this.animTranslateX,this.translateX),this.animTranslateY=this.gainOn(this.animTranslateY,this.translateY),this.raf=window.requestAnimationFrame(this.loop)},gainOn(e,t){let i=.3*(t-e);return Math.abs(i)>1e-5?e+i:t},onMouseWheel(e){if(!this.mouseWheelToZoom)return;e.preventDefault(),e.detail&&(e.wheelDelta=-10*e.detail);let t=Date.now();120===Math.abs(e.wheelDelta)?t-this.lastFullWheelTime>50&&(this.onMouseWheelDo(e.wheelDelta),this.lastFullWheelTime=t):(t-this.lastWheelTime>50&&"number"==typeof e.deltaX&&(this.lastWheelDirection=0==e.detail&&Math.abs(e.deltaX)>Math.abs(e.deltaY)?"x":"y","x"===this.lastWheelDirection&&this.$emit("swipe",e.deltaX>0?"left":"right")),"y"===this.lastWheelDirection&&this.onMouseWheelDo(e.wheelDelta)),this.lastWheelTime=t},onMouseWheelDo(e){let t=Math.pow(1.25,e/120);this.tryToScale(t),this.onInteractionEnd()},onMouseDown(e){this.refreshContainerPos(),this.isPointerDown=!0,this.pointerPosX=e.clientX,this.pointerPosY=e.clientY},onMouseUp(e){this.isPointerDown=!1,this.onInteractionEnd()},onMouseMove(e){this.onPointerMove(e.clientX,e.clientY)},onTouchStart(e){if(1===e.touches.length)this.refreshContainerPos(),this.pointerPosX=e.touches[0].clientX,this.pointerPosY=e.touches[0].clientY,this.isPointerDown=!0;else if(2===e.touches.length){this.isPointerDown=!0,this.pointerPosX=(e.touches[0].clientX+e.touches[1].clientX)/2,this.pointerPosY=(e.touches[0].clientY+e.touches[1].clientY)/2;let t=e.touches[0].clientX-e.touches[1].clientX,i=e.touches[0].clientY-e.touches[1].clientY;this.twoFingerInitDist=Math.sqrt(t*t+i*i)}},onTouchEnd(e){0===e.touches.length?(this.isPointerDown=!1,Math.abs(this.scale-1)<.1&&(this.scale=1),this.onInteractionEnd()):1===e.touches.length&&(this.pointerPosX=e.touches[0].clientX,this.pointerPosY=e.touches[0].clientY)},onTouchMove(e){if(1===e.touches.length)this.onPointerMove(e.touches[0].clientX,e.touches[0].clientY);else if(2===e.touches.length){let t=(e.touches[0].clientX+e.touches[1].clientX)/2,i=(e.touches[0].clientY+e.touches[1].clientY)/2;this.onPointerMove(t,i),this.pointerPosX=t,this.pointerPosY=i;let n=e.touches[0].clientX-e.touches[1].clientX,o=e.touches[0].clientY-e.touches[1].clientY,s=Math.sqrt(n*n+o*o);this.tryToScale(s/this.twoFingerInitDist),this.twoFingerInitDist=s}}}};var v,y=function(e,t,i,n,o,s,a,r,l,h){"boolean"!=typeof a&&(l=r,r=a,a=!1);var c,u="function"==typeof i?i.options:i;if(e&&e.render&&(u.render=e.render,u.staticRenderFns=e.staticRenderFns,u._compiled=!0,o&&(u.functional=!0)),n&&(u._scopeId=n),s?(c=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),t&&t.call(this,l(e)),e&&e._registeredComponents&&e._registeredComponents.add(s)},u._ssrRegister=c):t&&(c=a?function(){t.call(this,h(this.$root.$options.shadowRoot))}:function(e){t.call(this,r(e))}),c)if(u.functional){var d=u.render;u.render=function(e,t){return c.call(t),d(e,t)}}else{var m=u.beforeCreate;u.beforeCreate=m?[].concat(m,c):[c]}return i},w="undefined"!=typeof navigator&&/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());var T={};var X=function(e){return function(e,t){return function(e,t){var i=w?t.media||"default":e,n=T[i]||(T[i]={ids:new Set,styles:[]});if(!n.ids.has(e)){n.ids.add(e);var o=t.source;if(t.map&&(o+="\n/*# sourceURL="+t.map.sources[0]+" */",o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t.map))))+" */"),n.element||(n.element=document.createElement("style"),n.element.type="text/css",t.media&&n.element.setAttribute("media",t.media),void 0===v&&(v=document.head||document.getElementsByTagName("head")[0]),v.appendChild(n.element)),"styleSheet"in n.element)n.styles.push(o),n.element.styleSheet.cssText=n.styles.filter(Boolean).join("\n");else{var s=n.ids.size-1,a=document.createTextNode(o),r=n.element.childNodes;r[s]&&n.element.removeChild(r[s]),r.length?n.element.insertBefore(a,r[s]):n.element.appendChild(a)}}}(e,t)}};const S=g;var b=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"vue-zoomer",style:{backgroundColor:e.backgroundColor},on:{mousewheel:e.onMouseWheel,DOMMouseScroll:e.onMouseWheel,mousedown:e.onMouseDown,mouseup:e.onMouseUp,mousemove:e.onMouseMove,mouseout:e.setPointerPosCenter,touchstart:e.onTouchStart,touchend:e.onTouchEnd,touchmove:e.onTouchMove}},[i("div",{staticClass:"zoomer",style:e.wrapperStyle},[e._t("default")],2)])};b._withStripped=!0;const P=y({render:b,staticRenderFns:[]},(function(e){e&&e("data-v-33e6a267_0",{source:".vue-zoomer[data-v-33e6a267] {\n overflow: hidden;\n}\n.zoomer[data-v-33e6a267] {\n transform-origin: 50% 50%;\n width: 100%;\n height: 100%;\n}\n.zoomer > img[data-v-33e6a267] {\n vertical-align: top;\n user-drag: none;\n -webkit-user-drag: none;\n -moz-user-drag: none;\n}\n",map:void 0,media:void 0})}),S,"data-v-33e6a267",!1,void 0,!1,X,void 0,void 0);const M={props:{value:{type:Number,required:!0},list:{type:Array,required:!0},backgroundColor:{type:String,default:"#333"},pivot:{type:String,default:"cursor"},zoomingElastic:{type:Boolean,default:!0},limitTranslation:{type:Boolean,default:!0},doubleClickToZoom:{type:Boolean,default:!0},mouseWheelToZoom:{type:Boolean,default:!0}},data(){return{containerWidth:1,containerHeight:1,selIndex:this.value,animSelIndex:this.value,currentZoomed:!1,autoSliding:!1,imageAspectRatios:[],isPointerDown:!1,lastPointerX:0,slideOffsetX:0}},computed:{middleStyle(){return{left:0+this.slideOffsetX+"px"}},leftStyle(){return{left:-this.containerWidth+this.slideOffsetX+"px"}},rightStyle(){return{left:this.containerWidth+this.slideOffsetX+"px"}},slideThresh(){return Math.max(50,.1*this.containerWidth)}},watch:{value(e){e!==this.animSelIndex&&(this.selIndex=e,this.animSelIndex=e)},selIndex(){this.$nextTick(()=>{this.$refs.zoomers.forEach(e=>{e.refreshContainerPos()})})}},mounted(){window.addEventListener("resize",this.onWindowResize),this.onWindowResize()},destroyed(){window.removeEventListener("resize",this.onWindowResize)},methods:{reset(){this.$refs.zoomers.forEach(e=>{e.reset()})},zoomIn(e){this.$refs.zoomers[1]&&this.$refs.zoomers[1].zoomIn(e)},zoomOut(e){this.$refs.zoomers[1]&&this.$refs.zoomers[1].zoomOut(e)},onWindowResize(){let e=window.getComputedStyle(this.$el);this.containerWidth=parseFloat(e.width),this.containerHeight=parseFloat(e.height)},onPointerMove(e){if(this.isPointerDown&&!this.currentZoomed){let t=0===this.selIndex&&e>0&&this.slideOffsetX+e>0||this.selIndex===this.list.length-1&&e<0&&this.slideOffsetX+e<0?.3:1;this.slideOffsetX+=e*t}},onPointerUp(){this.slideOffsetX<-this.slideThresh?this.paginate(1):this.slideOffsetX>this.slideThresh?this.paginate(-1):this.paginate(0)},onImageDragStart:e=>(e.preventDefault(),!1),paginate(e){let t=this.selIndex+e;t<0||t>=this.list.length?this.slideOffsetX=0:(this.slideOffsetX=this.containerWidth*-e,this.autoSliding=!0,this.$emit("input",t),this.animSelIndex=t,setTimeout(()=>{this.selIndex=t,this.slideOffsetX=0,this.autoSliding=!1},400))},onMouseDown(e){this.isPointerDown=!0,this.lastPointerX=e.clientX},onMouseUp(e){this.isPointerDown=!1,this.onPointerUp()},onMouseMove(e){this.isPointerDown&&(this.onPointerMove(e.clientX-this.lastPointerX),this.lastPointerX=e.clientX)},onTouchStart(e){1===e.touches.length&&(this.isPointerDown=!0,this.lastPointerX=e.touches[0].clientX)},onTouchEnd(e){0===e.touches.length&&(this.isPointerDown=!1,this.onPointerUp())},onTouchMove(e){1===e.touches.length&&(this.onPointerMove(e.touches[0].clientX-this.lastPointerX),this.lastPointerX=e.touches[0].clientX)},onImageLoad(e,t){let i=t.target.naturalWidth/t.target.naturalHeight;this.$set(this.imageAspectRatios,e,i)},onImageSwipe(e){this.paginate("right"==e?-1:1)}}};var D=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"vue-zoomer-gallery",class:{anim:e.autoSliding&&!e.isPointerDown},style:{"background-color":e.backgroundColor},on:{mousemove:e.onMouseMove,mousedown:e.onMouseDown,mouseout:e.onMouseUp,mouseup:e.onMouseUp,touchstart:e.onTouchStart,touchend:e.onTouchEnd,touchmove:function(t){return t.preventDefault(),e.onTouchMove(t)}}},e._l(3,(function(t,n){return i("v-zoomer",{key:n+"-"+e.selIndex,ref:"zoomers",refInFor:!0,staticClass:"slide",class:["left","middle","right"][n],style:[e.leftStyle,e.middleStyle,e.rightStyle][n],attrs:{"max-scale":10,zoomed:e.currentZoomed,"reset-trigger":n,"aspect-ratio":e.imageAspectRatios[e.selIndex+n-1]||1,pivot:e.pivot,"zooming-elastic":e.zoomingElastic,"limit-translation":e.limitTranslation,"double-click-to-zoom":e.doubleClickToZoom,"mouse-wheel-to-zoom":e.mouseWheelToZoom},on:{"update:zoomed":function(t){e.currentZoomed=t},swipe:e.onImageSwipe}},[e.selIndex+n-1>-1&&e.selIndex+n-1<e.list.length?i("img",{staticStyle:{"object-fit":"contain",width:"100%",height:"100%"},attrs:{src:e.list[e.selIndex+n-1],draggable:"false"},on:{load:function(t){return e.onImageLoad(e.selIndex+n-1,t)},dragstart:e.onImageDragStart}}):e._e()])})),1)};D._withStripped=!0;const x=y({render:D,staticRenderFns:[]},(function(e){e&&e("data-v-ea62d372_0",{source:".vue-zoomer-gallery[data-v-ea62d372] {\n position: relative;\n overflow: hidden;\n user-select: none;\n min-width: 100px;\n min-height: 100px;\n}\n.vue-zoomer-gallery > *[data-v-ea62d372] {\n display: inline-block;\n}\n.vue-zoomer-gallery.anim .slide[data-v-ea62d372] {\n transition: left 0.4s;\n}\n.slide[data-v-ea62d372] {\n position: absolute;\n top: 0;\n object-fit: contain;\n width: 100%;\n height: 100%;\n -webkit-user-drag: none;\n}\n",map:void 0,media:void 0})}),M,"data-v-ea62d372",!1,void 0,!1,X,void 0,void 0);return{install(e){e.component("VZoomer",P),e.component("VZoomerGallery",x)}}})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).VueZoomer=t()}(this,(function(){"use strict";if(void 0===e)var e=window;var t,i=Object.create,n=Object.defineProperty,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,a=Object.getOwnPropertyNames,r=Object.getOwnPropertyDescriptor,l=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),h=(e,t,i)=>{if((e=>{n(e,"__esModule",{value:!0})})(e),t&&"object"==typeof t||"function"==typeof t)for(let o of a(t))!s.call(e,o)&&"default"!==o&&n(e,o,{get:()=>t[o],enumerable:!(i=r(t,o))||i.enumerable});return e},c=l((e,t)=>{t.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}}),u=l((t,i)=>{var n="object"==typeof e&&e&&e.Object===Object&&e;i.exports=n}),d=l((e,t)=>{var i=u(),n="object"==typeof self&&self&&self.Object===Object&&self,o=i||n||Function("return this")();t.exports=o}),m=l((e,t)=>{var i=d();t.exports=function(){return i.Date.now()}}),p=l((e,t)=>{var i=d().Symbol;t.exports=i}),f=l((e,t)=>{var i=p(),n=Object.prototype,o=n.hasOwnProperty,s=n.toString,a=i?i.toStringTag:void 0;t.exports=function(e){var t=o.call(e,a),i=e[a];try{e[a]=void 0;var n=!0}catch(e){}var r=s.call(e);return n&&(t?e[a]=i:delete e[a]),r}}),v=l((e,t)=>{var i=Object.prototype.toString;t.exports=function(e){return i.call(e)}}),g=l((e,t)=>{var i=p(),n=f(),o=v(),s=i?i.toStringTag:void 0;t.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":s&&s in Object(e)?n(e):o(e)}}),y=l((e,t)=>{t.exports=function(e){return null!=e&&"object"==typeof e}}),w=l((e,t)=>{var i=g(),n=y();t.exports=function(e){return"symbol"==typeof e||n(e)&&"[object Symbol]"==i(e)}}),b=l((e,t)=>{var i=c(),n=w(),o=/^\s+|\s+$/g,s=/^[-+]0x[0-9a-f]+$/i,a=/^0b[01]+$/i,r=/^0o[0-7]+$/i,l=parseInt;t.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(i(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=i(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(o,"");var h=a.test(e);return h||r.test(e)?l(e.slice(2),h?2:8):s.test(e)?NaN:+e}}),T=l((e,t)=>{var i=c(),n=m(),o=b(),s=Math.max,a=Math.min;t.exports=function(e,t,r){var l,h,c,u,d,m,p=0,f=!1,v=!1,g=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function y(t){var i=l,n=h;return l=h=void 0,p=t,u=e.apply(n,i)}function w(e){return p=e,d=setTimeout(T,t),f?y(e):u}function b(e){var i=e-m;return void 0===m||i>=t||i<0||v&&e-p>=c}function T(){var e=n();if(b(e))return X(e);d=setTimeout(T,function(e){var i=t-(e-m);return v?a(i,c-(e-p)):i}(e))}function X(e){return d=void 0,g&&l?y(e):(l=h=void 0,u)}function S(){var e=n(),i=b(e);if(l=arguments,h=this,m=e,i){if(void 0===d)return w(m);if(v)return clearTimeout(d),d=setTimeout(T,t),y(m)}return void 0===d&&(d=setTimeout(T,t)),u}return t=o(t)||0,i(r)&&(f=!!r.leading,c=(v="maxWait"in r)?s(o(r.maxWait)||0,t):c,g="trailing"in r?!!r.trailing:g),S.cancel=function(){void 0!==d&&clearTimeout(d),p=0,l=m=h=d=void 0},S.flush=function(){return void 0===d?u:X(n())},S}}),X=((t=T())&&t.__esModule?t:h(n(null!=t?i(o(t)):{},"default",{value:t,enumerable:!0}),t)).default;function S(){let e=[],t=[];function i(e,t){e.forEach(e=>{e.call(null,t)})}this.onSingleTap=function(t){"function"!=typeof t||e.includes(t)||e.push(t)},this.onDoubleTap=function(e){"function"!=typeof e||t.includes(e)||t.push(e)},this.attach=function(e){e instanceof Element?(e.addEventListener("touchstart",h),e.addEventListener("touchmove",u),e.addEventListener("touchend",c),e.addEventListener("mousedown",d),e.addEventListener("mouseup",m),e.addEventListener("mousemove",p)):console.error("TapDetector.attach: arg must be an Element")},this.detach=function(e){e.removeEventListener("touchstart",h),e.removeEventListener("touchmove",u),e.removeEventListener("touchend",c),e.removeEventListener("mousedown",d),e.removeEventListener("mouseup",m),e.removeEventListener("mousemove",p)};let n=!1,o=0,s=0,a=0,r=0,l=0;function h(e){n=!0,1===e.touches.length&&f(e.touches[0].clientX,e.touches[0].clientY)}function c(e){0===e.touches.length&&v()}function u(e){1===e.touches.length&&g(e.touches[0].clientX,e.touches[0].clientY)}function d(e){n||f(e.clientX,e.clientY)}function m(e){n||v()}function p(e){n||0===e.button&&g(e.clientX,e.clientY)}function f(e,t){r=e,l=t,a=0}function v(){let n=Date.now();a<10&&(n-o<300?s+=1:s=1,o=Date.now(),i(e,{clientX:r,clientY:l}),2===s&&(i(t,{clientX:r,clientY:l}),s=0)),a=0}function g(e,t){let i=r-e,n=l-t,o=Math.sqrt(i*i+n*n);a+=o,r=e,l=t}}var P={props:{minScale:{type:Number,default:1},maxScale:{type:Number,default:5},zoomed:{type:Boolean,default:!1},resetTrigger:{type:Number,default:1e5},aspectRatio:{type:Number,default:1},backgroundColor:{type:String,default:"transparent"},pivot:{type:String,default:"cursor"},zoomingElastic:{type:Boolean,default:!0},limitTranslation:{type:Boolean,default:!0},doubleClickToZoom:{type:Boolean,default:!0},mouseWheelToZoom:{type:Boolean,default:!0}},data:()=>({containerWidth:1,containerHeight:1,containerLeft:0,containerTop:0,translateX:0,animTranslateX:0,translateY:0,animTranslateY:0,scale:1,animScale:1,lastFullWheelTime:0,lastWheelTime:0,lastWheelDirection:"y",isPointerDown:!1,pointerPosX:-1,pointerPosY:-1,twoFingerInitDist:0,panLocked:!0,raf:null,tapDetector:null}),computed:{wrapperStyle(){return{transform:[`translate(${this.containerWidth*this.animTranslateX}px, ${this.containerHeight*this.animTranslateY}px)`,`scale(${this.animScale})`].join(" ")}}},watch:{scale(e){1!==e&&(this.$emit("update:zoomed",!0),this.panLocked=!1)},resetTrigger:"reset"},mounted(){this.tapDetector=new S,this.tapDetector.attach(this.$el),this.doubleClickToZoom&&this.tapDetector.onDoubleTap(this.onDoubleTap),window.addEventListener("resize",this.onWindowResize),this.onWindowResize(),this.refreshContainerPos(),this.loop()},destroyed(){this.tapDetector.detach(this.$el),window.removeEventListener("resize",this.onWindowResize),window.cancelAnimationFrame(this.raf)},methods:{reset(){this.scale=1,this.panLocked=!0,this.translateX=0,this.translateY=0},zoomIn(e=2){this.tryToScale(e),this.onInteractionEnd()},zoomOut(e=.5){this.tryToScale(e),this.onInteractionEnd()},tryToScale(e){let t=this.scale*e;if(this.zoomingElastic){if(t<this.minScale||t>this.maxScale){let i=Math.log2(e);i*=.2,e=Math.pow(2,i),t=this.scale*e}}else t<this.minScale?t=this.minScale:t>this.maxScale&&(t=this.maxScale);if(e=t/this.scale,this.scale=t,"image-center"!==this.pivot){let t=(this.pointerPosX-this.containerLeft)/this.containerWidth,i=(this.pointerPosY-this.containerTop)/this.containerHeight;this.translateX=(.5+this.translateX-t)*e+t-.5,this.translateY=(.5+this.translateY-i)*e+i-.5}},setPointerPosCenter(){this.pointerPosX=this.containerLeft+this.containerWidth/2,this.pointerPosY=this.containerTop+this.containerHeight/2},onPointerMove(e,t){if(this.isPointerDown){let i=e-this.pointerPosX,n=t-this.pointerPosY;this.panLocked||(this.translateX+=i/this.containerWidth,this.translateY+=n/this.containerHeight)}this.pointerPosX=e,this.pointerPosY=t},onInteractionEnd:X((function(){this.limit(),this.panLocked=1===this.scale,this.$emit("update:zoomed",!this.panLocked)}),100),limit(){if(this.scale<this.minScale?this.scale=this.minScale:this.scale>this.maxScale&&this.tryToScale(this.maxScale/this.scale),this.limitTranslation){let e=this.calcTranslateLimit();Math.abs(this.translateX)>e.x&&(this.translateX*=e.x/Math.abs(this.translateX)),Math.abs(this.translateY)>e.y&&(this.translateY*=e.y/Math.abs(this.translateY))}},calcTranslateLimit(){if("y"===this.getMarginDirection()){let e=this.containerWidth/this.aspectRatio/this.containerHeight,t=(this.scale*e-1)/2;return t<0&&(t=0),{x:(this.scale-1)/2,y:t}}{let e=this.containerHeight*this.aspectRatio/this.containerWidth,t=(this.scale*e-1)/2;return t<0&&(t=0),{x:t,y:(this.scale-1)/2}}},getMarginDirection(){return this.containerWidth/this.containerHeight>this.aspectRatio?"x":"y"},onDoubleTap(e){1===this.scale?(e.clientX>0&&(this.pointerPosX=e.clientX,this.pointerPosY=e.clientY),this.tryToScale(Math.min(3,this.maxScale))):this.reset(),this.onInteractionEnd()},onWindowResize(){let e=window.getComputedStyle(this.$el);this.containerWidth=parseFloat(e.width),this.containerHeight=parseFloat(e.height),this.setPointerPosCenter(),this.limit()},refreshContainerPos(){let e=this.$el.getBoundingClientRect();this.containerLeft=e.left,this.containerTop=e.top},loop(){this.animScale=this.gainOn(this.animScale,this.scale),this.animTranslateX=this.gainOn(this.animTranslateX,this.translateX),this.animTranslateY=this.gainOn(this.animTranslateY,this.translateY),this.raf=window.requestAnimationFrame(this.loop)},gainOn(e,t){let i=.3*(t-e);return Math.abs(i)>1e-5?e+i:t},onMouseWheel(e){if(!this.mouseWheelToZoom)return;e.preventDefault(),e.detail&&(e.wheelDelta=-10*e.detail);let t=Date.now();120===Math.abs(e.wheelDelta)?t-this.lastFullWheelTime>50&&(this.onMouseWheelDo(e.wheelDelta),this.lastFullWheelTime=t):(t-this.lastWheelTime>50&&"number"==typeof e.deltaX&&(this.lastWheelDirection=0==e.detail&&Math.abs(e.deltaX)>Math.abs(e.deltaY)?"x":"y","x"===this.lastWheelDirection&&this.$emit("swipe",e.deltaX>0?"left":"right")),"y"===this.lastWheelDirection&&this.onMouseWheelDo(e.wheelDelta)),this.lastWheelTime=t},onMouseWheelDo(e){let t=Math.pow(1.25,e/120);this.tryToScale(t),this.onInteractionEnd()},onMouseDown(e){this.refreshContainerPos(),this.isPointerDown=!0,this.pointerPosX=e.clientX,this.pointerPosY=e.clientY},onMouseUp(e){this.isPointerDown=!1,this.onInteractionEnd()},onMouseMove(e){this.onPointerMove(e.clientX,e.clientY)},onTouchStart(e){if(1===e.touches.length)this.refreshContainerPos(),this.pointerPosX=e.touches[0].clientX,this.pointerPosY=e.touches[0].clientY,this.isPointerDown=!0;else if(2===e.touches.length){this.isPointerDown=!0,this.pointerPosX=(e.touches[0].clientX+e.touches[1].clientX)/2,this.pointerPosY=(e.touches[0].clientY+e.touches[1].clientY)/2;let t=e.touches[0].clientX-e.touches[1].clientX,i=e.touches[0].clientY-e.touches[1].clientY;this.twoFingerInitDist=Math.sqrt(t*t+i*i)}},onTouchEnd(e){0===e.touches.length?(this.isPointerDown=!1,Math.abs(this.scale-1)<.1&&(this.scale=1),this.onInteractionEnd()):1===e.touches.length&&(this.pointerPosX=e.touches[0].clientX,this.pointerPosY=e.touches[0].clientY)},onTouchMove(e){if(1===e.touches.length)this.onPointerMove(e.touches[0].clientX,e.touches[0].clientY);else if(2===e.touches.length){let t=(e.touches[0].clientX+e.touches[1].clientX)/2,i=(e.touches[0].clientY+e.touches[1].clientY)/2;this.onPointerMove(t,i),this.pointerPosX=t,this.pointerPosY=i;let n=e.touches[0].clientX-e.touches[1].clientX,o=e.touches[0].clientY-e.touches[1].clientY,s=Math.sqrt(n*n+o*o);this.tryToScale(s/this.twoFingerInitDist),this.twoFingerInitDist=s}}}};function x(e,t,i,n,o,s,a,r,l,h){"boolean"!=typeof a&&(l=r,r=a,a=!1);const c="function"==typeof i?i.options:i;let u;if(e&&e.render&&(c.render=e.render,c.staticRenderFns=e.staticRenderFns,c._compiled=!0,o&&(c.functional=!0)),n&&(c._scopeId=n),s?(u=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),t&&t.call(this,l(e)),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=u):t&&(u=a?function(e){t.call(this,h(e,this.$root.$options.shadowRoot))}:function(e){t.call(this,r(e))}),u)if(c.functional){const e=c.render;c.render=function(t,i){return u.call(i),e(t,i)}}else{const e=c.beforeCreate;c.beforeCreate=e?[].concat(e,u):[u]}return i}const M="undefined"!=typeof navigator&&/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());function D(e){return(e,t)=>function(e,t){const i=M?t.media||"default":e,n=E[i]||(E[i]={ids:new Set,styles:[]});if(!n.ids.has(e)){n.ids.add(e);let i=t.source;if(t.map&&(i+="\n/*# sourceURL="+t.map.sources[0]+" */",i+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t.map))))+" */"),n.element||(n.element=document.createElement("style"),n.element.type="text/css",t.media&&n.element.setAttribute("media",t.media),void 0===z&&(z=document.head||document.getElementsByTagName("head")[0]),z.appendChild(n.element)),"styleSheet"in n.element)n.styles.push(i),n.element.styleSheet.cssText=n.styles.filter(Boolean).join("\n");else{const e=n.ids.size-1,t=document.createTextNode(i),o=n.element.childNodes;o[e]&&n.element.removeChild(o[e]),o.length?n.element.insertBefore(t,o[e]):n.element.appendChild(t)}}}(e,t)}let z;const E={};const W=P;var Y=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"vue-zoomer",style:{backgroundColor:e.backgroundColor},on:{mousewheel:e.onMouseWheel,DOMMouseScroll:e.onMouseWheel,mousedown:e.onMouseDown,mouseup:e.onMouseUp,mousemove:e.onMouseMove,mouseout:e.setPointerPosCenter,touchstart:e.onTouchStart,touchend:e.onTouchEnd,touchmove:e.onTouchMove}},[i("div",{staticClass:"zoomer",style:e.wrapperStyle},[e._t("default")],2)])};Y._withStripped=!0;const O=x({render:Y,staticRenderFns:[]},(function(e){e&&e("data-v-e532c06e_0",{source:"\n.vue-zoomer[data-v-e532c06e] {\n overflow: hidden;\n}\n.zoomer[data-v-e532c06e] {\n transform-origin: 50% 50%;\n width: 100%;\n height: 100%;\n}\n.zoomer > img[data-v-e532c06e] {\n /* remove the 4px gap below the image */\n vertical-align: top;\n user-drag: none;\n -webkit-user-drag: none;\n -moz-user-drag: none;\n}\n",map:void 0,media:void 0})}),W,"data-v-e532c06e",!1,void 0,!1,D,void 0,void 0);const I={props:{value:{type:Number,required:!0},list:{type:Array,required:!0},backgroundColor:{type:String,default:"#333"},pivot:{type:String,default:"cursor"},zoomingElastic:{type:Boolean,default:!0},limitTranslation:{type:Boolean,default:!0},doubleClickToZoom:{type:Boolean,default:!0},mouseWheelToZoom:{type:Boolean,default:!0}},data(){return{containerWidth:1,containerHeight:1,selIndex:this.value,animSelIndex:this.value,currentZoomed:!1,autoSliding:!1,imageAspectRatios:[],isPointerDown:!1,lastPointerX:0,slideOffsetX:0}},computed:{middleStyle(){return{left:0+this.slideOffsetX+"px"}},leftStyle(){return{left:-this.containerWidth+this.slideOffsetX+"px"}},rightStyle(){return{left:this.containerWidth+this.slideOffsetX+"px"}},slideThresh(){return Math.max(50,.1*this.containerWidth)}},watch:{value(e){e!==this.animSelIndex&&(this.selIndex=e,this.animSelIndex=e)},selIndex(){this.$nextTick(()=>{this.$refs.zoomers.forEach(e=>{e.refreshContainerPos()})})}},mounted(){window.addEventListener("resize",this.onWindowResize),this.onWindowResize()},destroyed(){window.removeEventListener("resize",this.onWindowResize)},methods:{reset(){this.$refs.zoomers.forEach(e=>{e.reset()})},zoomIn(e){this.$refs.zoomers[1]&&this.$refs.zoomers[1].zoomIn(e)},zoomOut(e){this.$refs.zoomers[1]&&this.$refs.zoomers[1].zoomOut(e)},onWindowResize(){let e=window.getComputedStyle(this.$el);this.containerWidth=parseFloat(e.width),this.containerHeight=parseFloat(e.height)},onPointerMove(e){if(this.isPointerDown&&!this.currentZoomed){let t=0===this.selIndex&&e>0&&this.slideOffsetX+e>0||this.selIndex===this.list.length-1&&e<0&&this.slideOffsetX+e<0?.3:1;this.slideOffsetX+=e*t}},onPointerUp(){this.slideOffsetX<-this.slideThresh?this.paginate(1):this.slideOffsetX>this.slideThresh?this.paginate(-1):this.paginate(0)},onImageDragStart:e=>(e.preventDefault(),!1),paginate(e){let t=this.selIndex+e;t<0||t>=this.list.length?this.slideOffsetX=0:(this.slideOffsetX=this.containerWidth*-e,this.autoSliding=!0,this.$emit("input",t),this.animSelIndex=t,setTimeout(()=>{this.selIndex=t,this.slideOffsetX=0,this.autoSliding=!1},400))},onMouseDown(e){this.isPointerDown=!0,this.lastPointerX=e.clientX},onMouseUp(e){this.isPointerDown=!1,this.onPointerUp()},onMouseMove(e){this.isPointerDown&&(this.onPointerMove(e.clientX-this.lastPointerX),this.lastPointerX=e.clientX)},onTouchStart(e){1===e.touches.length&&(this.isPointerDown=!0,this.lastPointerX=e.touches[0].clientX)},onTouchEnd(e){0===e.touches.length&&(this.isPointerDown=!1,this.onPointerUp())},onTouchMove(e){1===e.touches.length&&(this.onPointerMove(e.touches[0].clientX-this.lastPointerX),this.lastPointerX=e.touches[0].clientX)},onImageLoad(e,t){let i=t.target.naturalWidth/t.target.naturalHeight;this.$set(this.imageAspectRatios,e,i)},onImageSwipe(e){this.paginate("right"==e?-1:1)}}};var C=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"vue-zoomer-gallery",class:{anim:e.autoSliding&&!e.isPointerDown},style:{"background-color":e.backgroundColor},on:{mousemove:e.onMouseMove,mousedown:e.onMouseDown,mouseout:e.onMouseUp,mouseup:e.onMouseUp,touchstart:e.onTouchStart,touchend:e.onTouchEnd,touchmove:function(t){return t.preventDefault(),e.onTouchMove.apply(null,arguments)}}},e._l(3,(function(t,n){return i("v-zoomer",{key:n+"-"+e.selIndex,ref:"zoomers",refInFor:!0,staticClass:"slide",class:["left","middle","right"][n],style:[e.leftStyle,e.middleStyle,e.rightStyle][n],attrs:{"max-scale":10,zoomed:e.currentZoomed,"reset-trigger":n,"aspect-ratio":e.imageAspectRatios[e.selIndex+n-1]||1,pivot:e.pivot,"zooming-elastic":e.zoomingElastic,"limit-translation":e.limitTranslation,"double-click-to-zoom":e.doubleClickToZoom,"mouse-wheel-to-zoom":e.mouseWheelToZoom},on:{"update:zoomed":function(t){e.currentZoomed=t},swipe:e.onImageSwipe}},[e.selIndex+n-1>-1&&e.selIndex+n-1<e.list.length?i("img",{staticStyle:{"object-fit":"contain",width:"100%",height:"100%"},attrs:{src:e.list[e.selIndex+n-1],draggable:"false"},on:{load:function(t){return e.onImageLoad(e.selIndex+n-1,t)},dragstart:e.onImageDragStart}}):e._e()])})),1)};C._withStripped=!0;const L=x({render:C,staticRenderFns:[]},(function(e){e&&e("data-v-fc52b35c_0",{source:"\n.vue-zoomer-gallery[data-v-fc52b35c] {\n position: relative;\n overflow: hidden;\n user-select: none;\n min-width: 100px;\n min-height: 100px;\n}\n.vue-zoomer-gallery > *[data-v-fc52b35c] {\n display: inline-block;\n}\n.vue-zoomer-gallery.anim .slide[data-v-fc52b35c] {\n transition: left 0.4s;\n}\n.slide[data-v-fc52b35c] {\n position: absolute;\n top: 0;\n object-fit: contain;\n width: 100%;\n height: 100%;\n -webkit-user-drag: none;\n}\n",map:void 0,media:void 0})}),I,"data-v-fc52b35c",!1,void 0,!1,D,void 0,void 0);return{install(e){e.component("VZoomer",O),e.component("VZoomerGallery",L)},Zoomer:O,Gallery:L}})); |
{ | ||
"name": "vue-zoomer", | ||
"version": "0.3.9", | ||
"version": "0.3.10", | ||
"description": "Zoom the image or other thing with mouse or touch", | ||
@@ -27,4 +27,2 @@ "main": "dist/vue-zoomer.min.js", | ||
"@vue/component-compiler-utils": "^2.6.0", | ||
"lodash.debounce": "^4.0.8", | ||
"lodash.throttle": "^4.1.1", | ||
"parcel-bundler": "^1.12.4", | ||
@@ -34,6 +32,4 @@ "rollup": "^1.20.2", | ||
"rollup-plugin-node-resolve": "^5.2.0", | ||
"rollup-plugin-stylus-compiler": "^1.0.1", | ||
"rollup-plugin-terser": "^5.1.1", | ||
"rollup-plugin-vue": "^5.0.1", | ||
"stylus": "^0.54.5", | ||
"vue": "^2.6.7", | ||
@@ -44,4 +40,5 @@ "vue-hot-reload-api": "^2.3.3", | ||
"files": [ | ||
"src/**/*", | ||
"dist/**/*" | ||
] | ||
} |
@@ -5,6 +5,12 @@ # vue-zoomer | ||
## For Vue 3 | ||
This library has released a Vue 3 beta version [here](https://github.com/jarvisniu/vue-zoomer/tree/next). | ||
## Demo | ||
- [Single Image](https://unpkg.com/vue-zoomer/dist/demo/basic.html) | ||
- [Gallery](https://unpkg.com/vue-zoomer/dist/demo/gallery.html) | ||
- [Single Image](https://unpkg.com/vue-zoomer/dist/demo/basic.html) - | ||
[(src)](https://github.com/jarvisniu/vue-zoomer/blob/master/demo/basic/app.vue) | ||
- [Gallery](https://unpkg.com/vue-zoomer/dist/demo/gallery.html) - | ||
[(src)](https://github.com/jarvisniu/vue-zoomer/blob/master/demo/gallery/app.vue) | ||
@@ -19,3 +25,3 @@ ## Usage | ||
Import: | ||
Import and register globally: | ||
@@ -29,2 +35,24 @@ ```js | ||
Import and register locally (after `v0.3.10`): | ||
```html | ||
<!-- page1.vue --> | ||
<script> | ||
import VueZoomer from 'vue-zoomer' | ||
export default { | ||
components: { | ||
VZoomer: VueZoomer.Zoomer, | ||
VZoomerGallery: VueZoomer.Gallery, | ||
}, | ||
} | ||
</script> | ||
``` | ||
You can also import the source files (after `v0.3.10`), rather than | ||
the minified umd bundle, for better debugging experience: | ||
```js | ||
import VueZoomer from 'vue-zoomer/src' | ||
``` | ||
Single usage: | ||
@@ -31,0 +59,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
AI-detected possible typosquat
Supply chain riskAI has identified this package as a potential typosquat of a more popular package. This suggests that the package may be intentionally mimicking another package's name, description, or other metadata.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
2472794
10
23
114
3011
3