1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', { value: true });
- function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
- var React = _interopDefault(require('react'));
- var classNames = _interopDefault(require('classnames'));
- var reactDom = require('react-dom');
- /*! *****************************************************************************
- Copyright (c) Microsoft Corporation.
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
- ***************************************************************************** */
- /* global Reflect, Promise */
- var extendStatics = function(d, b) {
- extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
- return extendStatics(d, b);
- };
- function __extends(d, b) {
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- }
- var __assign = function() {
- __assign = Object.assign || function __assign(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
- }
- return t;
- };
- return __assign.apply(this, arguments);
- };
- function __rest(s, e) {
- var t = {};
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
- t[p] = s[p];
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
- t[p[i]] = s[p[i]];
- }
- return t;
- }
- var PhotoContext = React.createContext({
- onShow: function () { },
- addItem: function () { },
- removeItem: function () { },
- });
- function Spinner() {
- return (React.createElement("div", { className: "PhotoView__Spinner" },
- React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 32", width: "36", height: "36", fill: "white" },
- React.createElement("path", { opacity: ".25", d: "M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4" }),
- React.createElement("path", { d: "M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z" }))));
- }
- /**
- * 获取图片合适的大小
- */
- function getSuitableImageSize(naturalWidth, naturalHeight, rotate) {
- var _a;
- var width;
- var height;
- var y = 0;
- var innerWidth = window.innerWidth, innerHeight = window.innerHeight;
- var isVertical = rotate % 180 !== 0;
- // 若图片不是水平则调换宽高
- if (isVertical) {
- _a = [innerWidth, innerHeight], innerHeight = _a[0], innerWidth = _a[1];
- }
- var autoWidth = (naturalWidth / naturalHeight) * innerHeight;
- var autoHeight = (naturalHeight / naturalWidth) * innerWidth;
- if (naturalWidth < innerWidth && naturalHeight < innerHeight) {
- width = naturalWidth;
- height = naturalHeight;
- }
- else if (naturalWidth < innerWidth && naturalHeight >= innerHeight) {
- width = autoWidth;
- height = innerHeight;
- }
- else if (naturalWidth >= innerWidth && naturalHeight < innerHeight) {
- width = innerWidth;
- height = autoHeight;
- }
- else if (naturalWidth / naturalHeight > innerWidth / innerHeight) {
- width = innerWidth;
- height = autoHeight;
- }
- // 长图模式
- else if (naturalHeight / naturalWidth >= 3 && !isVertical) {
- width = innerWidth;
- height = autoHeight;
- // 默认定位到顶部区域
- y = (height - innerHeight) / 2;
- }
- else {
- width = autoWidth;
- height = innerHeight;
- }
- return {
- width: Math.floor(width),
- height: Math.floor(height),
- x: 0,
- y: y,
- scale: 1,
- };
- }
- function useMountedState() {
- var mountedRef = React.useRef(false);
- React.useEffect(function () {
- mountedRef.current = true;
- return function () {
- mountedRef.current = false;
- };
- });
- return React.useCallback(function () { return mountedRef.current; }, []);
- }
- var Photo = function (props) {
- var src = props.src, intro = props.intro, loaded = props.loaded, broken = props.broken, width = props.width, height = props.height, rotate = props.rotate, className = props.className, onImageLoad = props.onImageLoad, loadingElement = props.loadingElement, brokenElement = props.brokenElement, restProps = __rest(props, ["src", "intro", "loaded", "broken", "width", "height", "rotate", "className", "onImageLoad", "loadingElement", "brokenElement"]);
- var isMounted = useMountedState();
- function handleImageLoaded(e) {
- var _a = e.target, naturalWidth = _a.naturalWidth, naturalHeight = _a.naturalHeight;
- if (isMounted()) {
- onImageLoad(__assign({ loaded: true, naturalWidth: naturalWidth,
- naturalHeight: naturalHeight }, getSuitableImageSize(naturalWidth, naturalHeight, rotate)));
- }
- }
- function handleImageBroken() {
- if (isMounted()) {
- onImageLoad({
- broken: true,
- });
- }
- }
- React.useEffect(function () {
- var currPhoto = new Image();
- currPhoto.onload = handleImageLoaded;
- currPhoto.onerror = handleImageBroken;
- currPhoto.src = src;
- }, []);
- if (src && !broken) {
- if (loaded) {
- return (React.createElement("img", __assign({ className: classNames('PhotoView__Photo', className), src: src, width: width, height: height, alt: "" }, restProps)));
- }
- return loadingElement || React.createElement(Spinner, null);
- }
- if (brokenElement) {
- if (typeof brokenElement === 'function') {
- return brokenElement({
- src: src,
- intro: intro,
- });
- }
- return brokenElement;
- }
- return null;
- };
- Photo.displayName = 'Photo';
- var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
- /**
- * 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;
- /**
- * throttle
- * @param func
- * @param wait
- */
- function throttle(func, wait) {
- return lodash_debounce(func, wait, {
- leading: true,
- maxWait: wait,
- trailing: true,
- });
- }
- /**
- * 是否支持触摸设备
- */
- var isTouchDevice = typeof document !== 'undefined' && 'ontouchstart' in document.documentElement;
- /**
- * 从 Touch 事件中获取两个触控中心位置
- */
- function getMultipleTouchPosition(evt) {
- var _a = evt.touches[0], clientX = _a.clientX, clientY = _a.clientY;
- if (evt.touches.length >= 2) {
- var _b = evt.touches[1], nextClientX = _b.clientX, nextClientY = _b.clientY;
- return {
- clientX: (clientX + nextClientX) / 2,
- clientY: (clientY + nextClientY) / 2,
- touchLength: Math.sqrt(Math.pow(nextClientX - clientX, 2) + Math.pow(nextClientY - clientY, 2)),
- };
- }
- return { clientX: clientX, clientY: clientY, touchLength: 0 };
- }
- /**
- * 获取移动或缩放之后的中心点
- */
- function getPositionOnMoveOrScale(_a) {
- var x = _a.x, y = _a.y, clientX = _a.clientX, clientY = _a.clientY, _b = _a.offsetX, offsetX = _b === void 0 ? 0 : _b, _c = _a.offsetY, offsetY = _c === void 0 ? 0 : _c, fromScale = _a.fromScale, toScale = _a.toScale;
- var innerWidth = window.innerWidth, innerHeight = window.innerHeight;
- var centerClientX = innerWidth / 2;
- var centerClientY = innerHeight / 2;
- // 坐标偏移
- var lastPositionX = centerClientX + x;
- var lastPositionY = centerClientY + y;
- // 放大偏移量
- var offsetScale = toScale / fromScale;
- // 偏移位置
- var originX = clientX - (clientX - lastPositionX) * offsetScale - centerClientX;
- var originY = clientY - (clientY - lastPositionY) * offsetScale - centerClientY;
- return {
- x: originX + offsetX,
- y: originY + offsetY,
- scale: toScale,
- lastMoveClientX: clientX,
- lastMoveClientY: clientY,
- };
- }
- /**
- * 最大触摸时间
- */
- var maxTouchTime = 200;
- /**
- * 最大滑动切换图片距离
- */
- var maxMoveOffset = 40;
- /**
- * 图片的间隔
- */
- var horizontalOffset = 20;
- /**
- * 最小初始响应距离
- */
- var minStartTouchOffset = 10;
- /**
- * 默认背景透明度
- */
- var defaultOpacity = 1;
- /**
- * 最小缩放度
- */
- var minScale = 1;
- /**
- * 最大缩放度(若图片足够大,则会超出)
- */
- var maxScale = 6;
- /**
- * 滑动加速度
- */
- var slideAcceleration = 0.005;
- /**
- * 缩放弹性缓冲
- */
- var scaleBuffer = 0.2;
- /**
- * 边缘超出状态
- */
- var CloseEdgeEnum;
- (function (CloseEdgeEnum) {
- CloseEdgeEnum[CloseEdgeEnum["Normal"] = 0] = "Normal";
- CloseEdgeEnum[CloseEdgeEnum["Small"] = 1] = "Small";
- CloseEdgeEnum[CloseEdgeEnum["Before"] = 2] = "Before";
- CloseEdgeEnum[CloseEdgeEnum["After"] = 3] = "After";
- })(CloseEdgeEnum || (CloseEdgeEnum = {}));
- /**
- * 边缘触发状态
- */
- var ReachTypeEnum;
- (function (ReachTypeEnum) {
- ReachTypeEnum[ReachTypeEnum["Normal"] = 0] = "Normal";
- ReachTypeEnum[ReachTypeEnum["XReach"] = 1] = "XReach";
- ReachTypeEnum[ReachTypeEnum["YReach"] = 2] = "YReach";
- })(ReachTypeEnum || (ReachTypeEnum = {}));
- /**
- * 初始响应状态
- */
- var TouchStartEnum;
- (function (TouchStartEnum) {
- TouchStartEnum[TouchStartEnum["Normal"] = 0] = "Normal";
- TouchStartEnum[TouchStartEnum["X"] = 1] = "X";
- TouchStartEnum[TouchStartEnum["YPush"] = 2] = "YPush";
- TouchStartEnum[TouchStartEnum["YPull"] = 3] = "YPull";
- })(TouchStartEnum || (TouchStartEnum = {}));
- /**
- * 动画类型
- */
- var ShowAnimateEnum;
- (function (ShowAnimateEnum) {
- ShowAnimateEnum[ShowAnimateEnum["None"] = 0] = "None";
- ShowAnimateEnum[ShowAnimateEnum["In"] = 1] = "In";
- ShowAnimateEnum[ShowAnimateEnum["Out"] = 2] = "Out";
- })(ShowAnimateEnum || (ShowAnimateEnum = {}));
- /**
- * 接触左边/上边 或 右边/下边边缘
- * @param position - x/y
- * @param scale
- * @param size - width/height
- * @param innerSize - innerWidth/innerHeight
- * @return CloseEdgeEnum
- */
- function getClosedEdge(position, scale, size, innerSize) {
- var currentWidth = size * scale;
- // 图片超出的宽度
- var outOffsetX = (currentWidth - innerSize) / 2;
- if (currentWidth <= innerSize) {
- return CloseEdgeEnum.Small;
- }
- else if (position > 0 && outOffsetX - position <= 0) {
- return CloseEdgeEnum.Before;
- }
- else if (position < 0 && outOffsetX + position <= 0) {
- return CloseEdgeEnum.After;
- }
- return CloseEdgeEnum.Normal;
- }
- /**
- * 获取接触边缘类型
- * @param initialTouchState
- * @param horizontalCloseEdge
- * @param verticalCloseEdge
- * @param reachState
- */
- function getReachType(_a) {
- var initialTouchState = _a.initialTouchState, horizontalCloseEdge = _a.horizontalCloseEdge, verticalCloseEdge = _a.verticalCloseEdge, reachState = _a.reachState;
- if ((horizontalCloseEdge > 0 && initialTouchState === TouchStartEnum.X) || reachState === ReachTypeEnum.XReach) {
- return ReachTypeEnum.XReach;
- }
- else if ((verticalCloseEdge > 0 &&
- (initialTouchState === TouchStartEnum.YPull || initialTouchState === TouchStartEnum.YPush)) ||
- reachState === ReachTypeEnum.YReach) {
- return ReachTypeEnum.YReach;
- }
- return ReachTypeEnum.Normal;
- }
- /**
- * 适应到合适的图片偏移量
- */
- function slideToPosition(_a) {
- var _b;
- var x = _a.x, y = _a.y, lastX = _a.lastX, lastY = _a.lastY, width = _a.width, height = _a.height, scale = _a.scale, rotate = _a.rotate, touchedTime = _a.touchedTime;
- var moveTime = Date.now() - touchedTime;
- // 初始速度
- var speedX = (x - lastX) / moveTime;
- var speedY = (y - lastY) / moveTime;
- // 停下所消耗时间
- var slideTimeX = Math.abs(speedX / slideAcceleration);
- var slideTimeY = Math.abs(speedY / slideAcceleration);
- // 计划滑动位置
- var planX = Math.floor(x + speedX * slideTimeX);
- var planY = Math.floor(y + speedY * slideTimeY);
- // 若图片不是水平则调换属性
- if (rotate % 180 !== 0) {
- _b = [height, width], width = _b[0], height = _b[1];
- }
- var currentX = planX;
- var currentY = planY;
- var innerWidth = window.innerWidth, innerHeight = window.innerHeight;
- // 图片超出的长度
- var outOffsetX = (width * scale - innerWidth) / 2;
- var outOffsetY = (height * scale - innerHeight) / 2;
- var horizontalCloseEdge = getClosedEdge(planX, scale, width, innerWidth);
- var verticalCloseEdge = getClosedEdge(planY, scale, height, innerHeight);
- // x
- if (horizontalCloseEdge === CloseEdgeEnum.Small) {
- currentX = 0;
- }
- else if (horizontalCloseEdge === CloseEdgeEnum.Before) {
- currentX = outOffsetX;
- }
- else if (horizontalCloseEdge === CloseEdgeEnum.After) {
- currentX = -outOffsetX;
- }
- // y
- if (verticalCloseEdge === CloseEdgeEnum.Small) {
- currentY = 0;
- }
- else if (verticalCloseEdge === CloseEdgeEnum.Before) {
- currentY = outOffsetY;
- }
- else if (verticalCloseEdge === CloseEdgeEnum.After) {
- currentY = -outOffsetY;
- }
- // 时间过长
- if (moveTime >= maxTouchTime &&
- horizontalCloseEdge === CloseEdgeEnum.Normal &&
- verticalCloseEdge === CloseEdgeEnum.Normal) {
- return {
- x: x,
- y: y,
- };
- }
- return {
- x: currentX,
- y: currentY,
- };
- }
- /**
- * 单击和双击事件处理
- * @param singleTap - 单击事件
- * @param doubleTap - 双击事件
- * @return invokeTap
- */
- function withContinuousTap(singleTap, doubleTap) {
- // 当前连续点击次数
- var continuousClick = 0;
- var withDebounceTap = lodash_debounce(function () {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- continuousClick = 0;
- singleTap.apply(void 0, args);
- }, 300);
- return function invokeTap() {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- continuousClick += 1;
- withDebounceTap.apply(void 0, args);
- // 双击
- if (continuousClick >= 2) {
- withDebounceTap.cancel();
- continuousClick = 0;
- doubleTap.apply(void 0, args);
- }
- };
- }
- function getAnimateOrigin(originRect, width, height) {
- if (originRect) {
- var innerWidth_1 = window.innerWidth, innerHeight_1 = window.innerHeight;
- var xOrigin = (width - innerWidth_1) / 2 + originRect.clientX;
- var yOrigin = (height - innerHeight_1) / 2 + originRect.clientY;
- return xOrigin + "px " + yOrigin + "px";
- }
- return undefined;
- }
- /**
- * 纠正缩放后偏离中心区域位置
- */
- function correctSuitablePosition(_a) {
- var x = _a.x, y = _a.y, scale = _a.scale;
- if (scale <= 1) {
- return {
- x: 0,
- y: 0,
- };
- }
- return {
- x: x,
- y: y,
- };
- }
- var initialState = {
- // 真实宽度
- naturalWidth: 1,
- // 真实高度
- naturalHeight: 1,
- // 宽度
- width: 1,
- // 高度
- height: 1,
- // 加载成功状态
- loaded: false,
- // 破碎状态
- broken: false,
- // 图片 X 偏移量
- x: 0,
- // 图片 y 偏移量
- y: 0,
- // 图片缩放程度
- scale: 1,
- // 图片处于触摸的状态
- touched: false,
- // 背景处于触摸状态
- maskTouched: false,
- // 触摸开始时 x 原始坐标
- clientX: 0,
- // 触摸开始时 y 原始坐标
- clientY: 0,
- // 触摸开始时图片 x 偏移量
- lastX: 0,
- // 触摸开始时图片 y 偏移量
- lastY: 0,
- // 上一个触摸状态 x 原始坐标
- lastMoveClientX: 0,
- // 上一个触摸状态 y 原始坐标
- lastMoveClientY: 0,
- // 触摸开始时时间
- touchedTime: 0,
- // 多指触控间距
- lastTouchLength: 0,
- // 当前边缘触发状态
- reachState: ReachTypeEnum.Normal,
- };
- var PhotoView = /** @class */ (function (_super) {
- __extends(PhotoView, _super);
- function PhotoView(props) {
- var _this = _super.call(this, props) || this;
- _this.state = initialState;
- // 初始响应状态
- _this.initialTouchState = TouchStartEnum.Normal;
- _this.handleImageLoad = function (imageParams) {
- _this.setState(imageParams);
- };
- _this.handleResize = function () {
- var _a = _this.props, onPhotoResize = _a.onPhotoResize, rotate = _a.rotate;
- var _b = _this.state, loaded = _b.loaded, naturalWidth = _b.naturalWidth, naturalHeight = _b.naturalHeight;
- if (loaded) {
- _this.setState(getSuitableImageSize(naturalWidth, naturalHeight, rotate));
- if (onPhotoResize) {
- onPhotoResize();
- }
- }
- };
- _this.handleStart = function (clientX, clientY, touchLength) {
- if (touchLength === void 0) { touchLength = 0; }
- _this.setState(function (prevState) { return ({
- touched: true,
- clientX: clientX,
- clientY: clientY,
- lastMoveClientX: clientX,
- lastMoveClientY: clientY,
- lastX: prevState.x,
- lastY: prevState.y,
- lastTouchLength: touchLength,
- touchedTime: Date.now(),
- }); });
- };
- _this.onMove = function (newClientX, newClientY, touchLength) {
- var _a;
- if (touchLength === void 0) { touchLength = 0; }
- var _b = _this.props, onReachMove = _b.onReachMove, isActive = _b.isActive, rotate = _b.rotate;
- var _c = _this.state, naturalWidth = _c.naturalWidth, x = _c.x, y = _c.y, clientX = _c.clientX, clientY = _c.clientY, lastMoveClientX = _c.lastMoveClientX, lastMoveClientY = _c.lastMoveClientY, lastX = _c.lastX, lastY = _c.lastY, scale = _c.scale, lastTouchLength = _c.lastTouchLength, reachState = _c.reachState, touched = _c.touched, maskTouched = _c.maskTouched;
- if ((touched || maskTouched) && isActive) {
- var _d = _this.state, width = _d.width, height = _d.height;
- // 若图片不是水平则调换属性
- if (rotate % 180 !== 0) {
- _a = [height, width], width = _a[0], height = _a[1];
- }
- // 单指最小缩放下,以初始移动距离来判断意图
- if (touchLength === 0 && _this.initialTouchState === TouchStartEnum.Normal) {
- var isStillX = Math.abs(newClientX - clientX) <= minStartTouchOffset;
- var isStillY = Math.abs(newClientY - clientY) <= minStartTouchOffset;
- // 初始移动距离不足
- if (isStillX && isStillY) {
- // 方向记录上次移动距离,以便平滑过渡
- _this.setState({
- lastMoveClientX: newClientX,
- lastMoveClientY: newClientY,
- });
- return;
- }
- // 设置响应状态
- _this.initialTouchState = !isStillX
- ? TouchStartEnum.X
- : newClientY > clientY
- ? TouchStartEnum.YPull
- : TouchStartEnum.YPush;
- }
- var offsetX = newClientX - lastMoveClientX;
- var offsetY = newClientY - lastMoveClientY;
- // 边缘触发状态
- var currentReachState = ReachTypeEnum.Normal;
- if (touchLength === 0) {
- // 边缘超出状态
- var horizontalCloseEdge = getClosedEdge(offsetX + lastX, scale, width, window.innerWidth);
- var verticalCloseEdge = getClosedEdge(offsetY + lastY, scale, height, window.innerHeight);
- // 边缘触发检测
- currentReachState = getReachType({
- initialTouchState: _this.initialTouchState,
- horizontalCloseEdge: horizontalCloseEdge,
- verticalCloseEdge: verticalCloseEdge,
- reachState: reachState,
- });
- // 接触边缘
- if (currentReachState != ReachTypeEnum.Normal) {
- onReachMove(currentReachState, newClientX, newClientY, scale);
- }
- }
- // 横向边缘触发、背景触发禁用当前滑动
- if (currentReachState === ReachTypeEnum.XReach || maskTouched) {
- _this.setState({
- reachState: ReachTypeEnum.XReach,
- });
- }
- else {
- // 目标倍数
- var endScale = scale + ((touchLength - lastTouchLength) / 100 / 2) * scale;
- // 限制最大倍数和最小倍数
- var toScale = Math.max(Math.min(endScale, Math.max(maxScale, naturalWidth / width)), minScale - scaleBuffer);
- _this.setState(__assign({ lastTouchLength: touchLength, reachState: currentReachState }, getPositionOnMoveOrScale({
- x: x,
- y: y,
- clientX: newClientX,
- clientY: newClientY,
- offsetX: offsetX,
- offsetY: offsetY,
- fromScale: scale,
- toScale: toScale,
- })));
- }
- }
- };
- _this.onPhotoTap = function (clientX, clientY) {
- var onPhotoTap = _this.props.onPhotoTap;
- if (onPhotoTap) {
- onPhotoTap(clientX, clientY);
- }
- };
- _this.onDoubleTap = function (clientX, clientY) {
- var _a = _this.state, width = _a.width, naturalWidth = _a.naturalWidth, x = _a.x, y = _a.y, scale = _a.scale, reachState = _a.reachState;
- if (reachState !== ReachTypeEnum.Normal) {
- return;
- }
- var position = getPositionOnMoveOrScale({
- x: x,
- y: y,
- clientX: clientX,
- clientY: clientY,
- fromScale: scale,
- // 若图片足够大,则放大适应的倍数
- toScale: scale !== 1 ? 1 : Math.max(2, naturalWidth / width),
- });
- _this.setState(__assign(__assign({ clientX: clientX,
- clientY: clientY }, position), correctSuitablePosition(position)));
- };
- _this.handleWheel = function (e) {
- e.stopPropagation();
- var clientX = e.clientX, clientY = e.clientY, deltaY = e.deltaY;
- var _a = _this.state, width = _a.width, naturalWidth = _a.naturalWidth, reachState = _a.reachState;
- if (reachState !== ReachTypeEnum.Normal) {
- return;
- }
- _this.setState(function (_a) {
- var x = _a.x, y = _a.y, scale = _a.scale;
- var endScale = scale - deltaY / 100 / 2;
- // 限制最大倍数和最小倍数
- var toScale = Math.max(Math.min(endScale, Math.max(maxScale, naturalWidth / width)), minScale);
- var position = getPositionOnMoveOrScale({
- x: x,
- y: y,
- clientX: clientX,
- clientY: clientY,
- fromScale: scale,
- toScale: toScale,
- });
- return __assign(__assign({ clientX: clientX,
- clientY: clientY }, position), correctSuitablePosition(position));
- });
- };
- _this.handleMaskStart = function (clientX, clientY) {
- _this.setState(function (prevState) { return ({
- maskTouched: true,
- clientX: clientX,
- clientY: clientY,
- lastX: prevState.x,
- lastY: prevState.y,
- }); });
- };
- _this.handleMaskMouseDown = function (e) {
- e.stopPropagation();
- _this.handleMaskStart(e.clientX, e.clientY);
- };
- _this.handleMaskTouchStart = function (e) {
- e.stopPropagation();
- var _a = e.touches[0], clientX = _a.clientX, clientY = _a.clientY;
- _this.handleMaskStart(clientX, clientY);
- };
- _this.handleTouchStart = function (e) {
- e.stopPropagation();
- var _a = getMultipleTouchPosition(e), clientX = _a.clientX, clientY = _a.clientY, touchLength = _a.touchLength;
- _this.handleStart(clientX, clientY, touchLength);
- };
- _this.handleMouseDown = function (e) {
- e.preventDefault();
- e.stopPropagation();
- _this.handleStart(e.clientX, e.clientY, 0);
- };
- _this.handleTouchMove = function (e) {
- e.preventDefault();
- e.stopPropagation();
- var _a = getMultipleTouchPosition(e), clientX = _a.clientX, clientY = _a.clientY, touchLength = _a.touchLength;
- _this.onMove(clientX, clientY, touchLength);
- };
- _this.handleMouseMove = function (e) {
- e.preventDefault();
- e.stopPropagation();
- _this.onMove(e.clientX, e.clientY);
- };
- _this.handleUp = function (newClientX, newClientY) {
- // 重置响应状态
- _this.initialTouchState = TouchStartEnum.Normal;
- var _a = _this.props, onReachUp = _a.onReachUp, onPhotoTap = _a.onPhotoTap, onMaskTap = _a.onMaskTap, isActive = _a.isActive, rotate = _a.rotate;
- var _b = _this.state, width = _b.width, height = _b.height, naturalWidth = _b.naturalWidth, x = _b.x, y = _b.y, lastX = _b.lastX, lastY = _b.lastY, scale = _b.scale, touchedTime = _b.touchedTime, clientX = _b.clientX, clientY = _b.clientY, touched = _b.touched, maskTouched = _b.maskTouched;
- if ((touched || maskTouched) && isActive) {
- var hasMove_1 = clientX !== newClientX || clientY !== newClientY;
- _this.setState(__assign({ touched: false, maskTouched: false,
- // 限制缩放
- scale: Math.max(Math.min(scale, Math.max(maxScale, naturalWidth / width)), minScale), reachState: ReachTypeEnum.Normal }, (hasMove_1
- ? slideToPosition({
- x: x,
- y: y,
- lastX: lastX,
- lastY: lastY,
- width: width,
- height: height,
- scale: scale,
- rotate: rotate,
- touchedTime: touchedTime,
- })
- : {
- x: x,
- y: y,
- })), function () {
- if (onReachUp) {
- onReachUp(newClientX, newClientY);
- }
- // 触发 Tap 事件
- if (!hasMove_1) {
- if (touched && onPhotoTap) {
- _this.handlePhotoTap(newClientX, newClientY);
- }
- else if (maskTouched && onMaskTap) {
- onMaskTap(newClientX, newClientY);
- }
- }
- });
- }
- };
- _this.handleTouchEnd = function (e) {
- var _a = e.changedTouches[0], clientX = _a.clientX, clientY = _a.clientY;
- _this.handleUp(clientX, clientY);
- };
- _this.handleMouseUp = function (e) {
- var clientX = e.clientX, clientY = e.clientY;
- _this.handleUp(clientX, clientY);
- };
- _this.onMove = throttle(_this.onMove, 8);
- _this.handleResize = throttle(_this.handleResize, 8);
- // 单击与双击事件处理
- _this.handlePhotoTap = withContinuousTap(_this.onPhotoTap, _this.onDoubleTap);
- return _this;
- }
- PhotoView.prototype.componentDidMount = function () {
- if (isTouchDevice) {
- window.addEventListener('touchmove', this.handleTouchMove, { passive: false });
- window.addEventListener('touchend', this.handleTouchEnd, { passive: false });
- }
- else {
- window.addEventListener('mousemove', this.handleMouseMove);
- window.addEventListener('mouseup', this.handleMouseUp);
- }
- window.addEventListener('resize', this.handleResize);
- };
- PhotoView.prototype.componentDidUpdate = function (prevProps) {
- var rotate = this.props.rotate;
- if (rotate !== prevProps.rotate) {
- var _a = this.state, naturalWidth = _a.naturalWidth, naturalHeight = _a.naturalHeight;
- this.setState(getSuitableImageSize(naturalWidth, naturalHeight, rotate));
- }
- };
- PhotoView.prototype.componentWillUnmount = function () {
- window.removeEventListener('touchmove', this.handleTouchMove);
- window.removeEventListener('touchend', this.handleTouchEnd);
- window.removeEventListener('mousemove', this.handleMouseMove);
- window.removeEventListener('mouseup', this.handleMouseUp);
- window.removeEventListener('resize', this.handleResize);
- };
- PhotoView.prototype.render = function () {
- var _a = this.props, src = _a.src, intro = _a.intro, viewClassName = _a.viewClassName, className = _a.className, style = _a.style, rotate = _a.rotate, loadingElement = _a.loadingElement, brokenElement = _a.brokenElement, isActive = _a.isActive, showAnimateType = _a.showAnimateType, originRect = _a.originRect;
- var _b = this.state, width = _b.width, height = _b.height, loaded = _b.loaded, x = _b.x, y = _b.y, scale = _b.scale, touched = _b.touched, broken = _b.broken;
- var transform = "translate3d(" + x + "px, " + y + "px, 0) scale(" + scale + ") rotate(" + rotate + "deg)";
- return (React.createElement("div", { className: classNames('PhotoView__PhotoWrap', viewClassName), style: style },
- React.createElement("div", { className: "PhotoView__PhotoMask", onMouseDown: !isTouchDevice && isActive ? this.handleMaskMouseDown : undefined, onTouchStart: isTouchDevice && isActive ? this.handleMaskTouchStart : undefined }),
- React.createElement("div", { className: classNames('PhotoView__PhotoBox', {
- PhotoView__animateIn: loaded && showAnimateType === ShowAnimateEnum.In,
- PhotoView__animateOut: loaded && showAnimateType === ShowAnimateEnum.Out,
- }), style: {
- transformOrigin: loaded ? getAnimateOrigin(originRect, 0, 0) : undefined,
- } },
- React.createElement(Photo, { className: className, src: src, intro: intro, width: width, height: height, loaded: loaded, broken: broken, rotate: rotate, onMouseDown: isTouchDevice ? undefined : this.handleMouseDown, onTouchStart: isTouchDevice ? this.handleTouchStart : undefined, onWheel: this.handleWheel, style: {
- WebkitTransform: transform,
- transform: transform,
- transition: touched ? undefined : 'transform 0.5s cubic-bezier(0.25, 0.8, 0.25, 1)',
- }, onImageLoad: this.handleImageLoad, loadingElement: loadingElement, brokenElement: brokenElement }))));
- };
- PhotoView.displayName = 'PhotoView';
- return PhotoView;
- }(React.Component));
- var SlideWrap = function (_a) {
- var className = _a.className, children = _a.children, restProps = __rest(_a, ["className", "children"]);
- var dialogNode = React.useRef(document.createElement('section'));
- var originalOverflowCallback = React.useRef('');
- React.useEffect(function () {
- document.body.appendChild(dialogNode.current);
- var style = document.body.style;
- originalOverflowCallback.current = style.overflow;
- style.overflow = 'hidden';
- return function () {
- style.overflow = originalOverflowCallback.current;
- // 清除容器
- document.body.removeChild(dialogNode.current);
- };
- }, []);
- return reactDom.createPortal(React.createElement("div", __assign({ className: classNames('PhotoView-SlideWrap', className) }, restProps), children), dialogNode.current);
- };
- SlideWrap.displayName = 'SlideWrap';
- function VisibleAnimationHandle(_a) {
- var visible = _a.visible, currentImage = _a.currentImage, children = _a.children;
- var _b = React.useState(visible), photoVisible = _b[0], updatePhotoVisible = _b[1];
- var _c = React.useState(ShowAnimateEnum.None), showAnimateType = _c[0], updateAnimateStatus = _c[1];
- var _d = React.useState(), originRect = _d[0], updateOriginRect = _d[1];
- function onShowAnimateEnd() {
- updateAnimateStatus(ShowAnimateEnum.None);
- // Close
- if (showAnimateType === ShowAnimateEnum.Out) {
- updatePhotoVisible(false);
- }
- }
- React.useEffect(function () {
- var originRef = (currentImage || {}).originRef;
- if (originRef && originRef.nodeType === 1) {
- // 获取触发时节点位置
- var _a = originRef.getBoundingClientRect(), top_1 = _a.top, left = _a.left, width = _a.width, height = _a.height;
- updateOriginRect({
- clientX: left + width / 2,
- clientY: top_1 + height / 2,
- });
- }
- else if (originRect && !originRef) {
- updateOriginRect(undefined);
- }
- if (visible) {
- updateAnimateStatus(ShowAnimateEnum.In);
- updatePhotoVisible(true);
- }
- else {
- updateAnimateStatus(ShowAnimateEnum.Out);
- }
- }, [visible]);
- return children({
- photoVisible: photoVisible,
- showAnimateType: showAnimateType,
- originRect: originRect,
- onShowAnimateEnd: onShowAnimateEnd,
- });
- }
- function Close(props) {
- return (React.createElement("svg", __assign({ version: "1.1", xmlns: "http://www.w3.org/2000/svg", width: "44", height: "44", viewBox: "0 0 768 768" }, props),
- React.createElement("path", { fill: "#FFF", d: "M607.5 205.5l-178.5 178.5 178.5 178.5-45 45-178.5-178.5-178.5 178.5-45-45 178.5-178.5-178.5-178.5 45-45 178.5 178.5 178.5-178.5z" })));
- }
- function ArrowLeft(props) {
- return (React.createElement("svg", __assign({ version: "1.1", xmlns: "http://www.w3.org/2000/svg", width: "44", height: "44", viewBox: "0 0 768 768" }, props),
- React.createElement("path", { d: "M640.5 352.5v63h-390l178.5 180-45 45-256.5-256.5 256.5-256.5 45 45-178.5 180h390z" })));
- }
- function ArrowRight(props) {
- return (React.createElement("svg", __assign({ version: "1.1", xmlns: "http://www.w3.org/2000/svg", width: "44", height: "44", viewBox: "0 0 768 768" }, props),
- React.createElement("path", { d: "M384 127.5l256.5 256.5-256.5 256.5-45-45 178.5-180h-390v-63h390l-178.5-180z" })));
- }
- var PhotoSlider = /** @class */ (function (_super) {
- __extends(PhotoSlider, _super);
- function PhotoSlider(props) {
- var _this = _super.call(this, props) || this;
- _this.handleClose = function (evt) {
- var onClose = _this.props.onClose;
- var backdropOpacity = _this.state.backdropOpacity;
- onClose(evt);
- _this.setState({
- overlayVisible: true,
- // 记录当前关闭时的透明度
- lastBackdropOpacity: backdropOpacity,
- });
- };
- _this.handlePhotoTap = function () {
- var photoClosable = _this.props.photoClosable;
- if (photoClosable) {
- _this.handleClose();
- }
- else {
- _this.setState(function (prevState) { return ({
- overlayVisible: !prevState.overlayVisible,
- }); });
- }
- };
- _this.handlePhotoMaskTap = function () {
- var maskClosable = _this.props.maskClosable;
- if (maskClosable) {
- _this.handleClose();
- }
- };
- _this.handleResize = function () {
- var innerWidth = window.innerWidth;
- _this.setState(function (_a) {
- var photoIndex = _a.photoIndex;
- return {
- translateX: -(innerWidth + horizontalOffset) * photoIndex,
- lastClientX: undefined,
- lastClientY: undefined,
- shouldTransition: false,
- };
- });
- };
- _this.handleRotate = function (rotating) {
- var _a = _this.state, photoIndex = _a.photoIndex, rotatingMap = _a.rotatingMap;
- rotatingMap.set(photoIndex, rotating);
- _this.setState({
- rotatingMap: rotatingMap,
- });
- };
- _this.handleKeyDown = function (evt) {
- var visible = _this.props.visible;
- if (visible) {
- switch (evt.key) {
- case 'ArrowLeft':
- _this.handlePrevious(false);
- break;
- case 'ArrowRight':
- _this.handleNext(false);
- break;
- case 'Escape':
- _this.handleClose();
- break;
- }
- }
- };
- _this.handleBack = function (evt) {
- evt.stopPropagation();
- console.log("范湖一");
- };
- _this.handleReachVerticalMove = function (clientY, scale) {
- _this.setState(function (_a) {
- var lastClientY = _a.lastClientY, backdropOpacity = _a.backdropOpacity;
- if (lastClientY === undefined) {
- return {
- touched: true,
- lastClientY: clientY,
- backdropOpacity: backdropOpacity,
- canPullClose: true,
- };
- }
- var offsetClientY = Math.abs(clientY - lastClientY);
- var opacity = Math.max(Math.min(defaultOpacity, defaultOpacity - offsetClientY / 100 / 4), 0);
- return {
- touched: true,
- lastClientY: lastClientY,
- backdropOpacity: scale === 1 ? opacity : defaultOpacity,
- canPullClose: scale === 1,
- };
- });
- };
- _this.handleReachHorizontalMove = function (clientX) {
- var innerWidth = window.innerWidth;
- var images = _this.props.images;
- _this.setState(function (_a) {
- var lastClientX = _a.lastClientX, translateX = _a.translateX, photoIndex = _a.photoIndex;
- if (lastClientX === undefined) {
- return {
- touched: true,
- lastClientX: clientX,
- translateX: translateX,
- shouldTransition: true,
- };
- }
- var originOffsetClientX = clientX - lastClientX;
- var offsetClientX = originOffsetClientX;
- // 第一张和最后一张超出距离减半
- if ((photoIndex === 0 && originOffsetClientX > 0) ||
- (photoIndex === images.length - 1 && originOffsetClientX < 0)) {
- offsetClientX = originOffsetClientX / 2;
- }
- return {
- touched: true,
- lastClientX: lastClientX,
- translateX: -(innerWidth + horizontalOffset) * photoIndex + offsetClientX,
- shouldTransition: true,
- };
- });
- };
- _this.handleIndexChange = function (photoIndex, shouldTransition) {
- if (shouldTransition === void 0) { shouldTransition = true; }
- var singlePageWidth = window.innerWidth + horizontalOffset;
- var translateX = -singlePageWidth * photoIndex;
- _this.setState({
- touched: false,
- lastClientX: undefined,
- lastClientY: undefined,
- translateX: translateX,
- photoIndex: photoIndex,
- shouldTransition: shouldTransition,
- });
- var onIndexChange = _this.props.onIndexChange;
- if (onIndexChange) {
- onIndexChange(photoIndex);
- }
- };
- _this.handlePrevious = function (shouldTransition) {
- var photoIndex = _this.state.photoIndex;
- if (photoIndex > 0) {
- _this.handleIndexChange(photoIndex - 1, shouldTransition);
- }
- };
- _this.handleNext = function (shouldTransition) {
- var images = _this.props.images;
- var photoIndex = _this.state.photoIndex;
- if (photoIndex < images.length - 1) {
- _this.handleIndexChange(photoIndex + 1, shouldTransition);
- }
- };
- _this.handleReachMove = function (reachState, clientX, clientY, scale) {
- if (reachState === ReachTypeEnum.XReach) {
- _this.handleReachHorizontalMove(clientX);
- }
- else if (reachState === ReachTypeEnum.YReach) {
- _this.handleReachVerticalMove(clientY, scale);
- }
- };
- _this.handleReachUp = function (clientX, clientY) {
- var images = _this.props.images;
- var _a = _this.state, _b = _a.lastClientX, lastClientX = _b === void 0 ? clientX : _b, _c = _a.lastClientY, lastClientY = _c === void 0 ? clientY : _c, photoIndex = _a.photoIndex, overlayVisible = _a.overlayVisible, canPullClose = _a.canPullClose;
- var offsetClientX = clientX - lastClientX;
- var offsetClientY = clientY - lastClientY;
- var willClose = false;
- // 下一张
- if (offsetClientX < -maxMoveOffset && photoIndex < images.length - 1) {
- _this.handleIndexChange(photoIndex + 1);
- return;
- }
- // 上一张
- if (offsetClientX > maxMoveOffset && photoIndex > 0) {
- _this.handleIndexChange(photoIndex - 1);
- return;
- }
- var singlePageWidth = window.innerWidth + horizontalOffset;
- // 当前偏移
- var currentTranslateX = -singlePageWidth * photoIndex;
- var currentPhotoIndex = photoIndex;
- if (Math.abs(offsetClientY) > window.innerHeight * 0.14 && canPullClose) {
- willClose = true;
- _this.handleClose();
- }
- _this.setState({
- touched: false,
- translateX: currentTranslateX,
- photoIndex: currentPhotoIndex,
- lastClientX: undefined,
- lastClientY: undefined,
- backdropOpacity: defaultOpacity,
- overlayVisible: willClose ? true : overlayVisible,
- });
- };
- _this.state = {
- translateX: 0,
- photoIndex: 0,
- touched: false,
- shouldTransition: true,
- lastClientX: undefined,
- lastClientY: undefined,
- backdropOpacity: defaultOpacity,
- lastBackdropOpacity: defaultOpacity,
- overlayVisible: true,
- canPullClose: true,
- rotatingMap: new Map(),
- };
- return _this;
- }
- PhotoSlider.getDerivedStateFromProps = function (nextProps, prevState) {
- if (nextProps.index !== undefined && nextProps.index !== prevState.photoIndex) {
- return {
- photoIndex: nextProps.index,
- translateX: -(window.innerWidth + horizontalOffset) * nextProps.index,
- };
- }
- return null;
- };
- PhotoSlider.prototype.componentDidMount = function () {
- var _a = this.props.index, index = _a === void 0 ? 0 : _a;
- this.setState({
- translateX: index * -(window.innerWidth + horizontalOffset),
- photoIndex: index,
- });
- window.addEventListener('keydown', this.handleKeyDown);
- window.addEventListener('popstate', this.handleBack);
- };
- PhotoSlider.prototype.componentWillUnmount = function () {
- window.removeEventListener('keydown', this.handleKeyDown);
- };
- PhotoSlider.prototype.render = function () {
- var _this = this;
- var _a = this.props, images = _a.images, visible = _a.visible, className = _a.className, maskClassName = _a.maskClassName, viewClassName = _a.viewClassName, imageClassName = _a.imageClassName, bannerVisible = _a.bannerVisible, introVisible = _a.introVisible, overlayRender = _a.overlayRender, toolbarRender = _a.toolbarRender, loadingElement = _a.loadingElement, brokenElement = _a.brokenElement;
- var _b = this.state, translateX = _b.translateX, touched = _b.touched, photoIndex = _b.photoIndex, backdropOpacity = _b.backdropOpacity, lastBackdropOpacity = _b.lastBackdropOpacity, overlayVisible = _b.overlayVisible, rotatingMap = _b.rotatingMap, shouldTransition = _b.shouldTransition;
- var imageLength = images.length;
- var currentImage = images.length ? images[photoIndex] : undefined;
- var transform = "translate3d(" + translateX + "px, 0px, 0)";
- // Overlay
- var overlayIntro = currentImage && currentImage.intro;
- return (React.createElement(VisibleAnimationHandle, { visible: visible, currentImage: currentImage }, function (_a) {
- var photoVisible = _a.photoVisible, showAnimateType = _a.showAnimateType, originRect = _a.originRect, onShowAnimateEnd = _a.onShowAnimateEnd;
- if (photoVisible) {
- var innerWidth_1 = window.innerWidth;
- var currentOverlayVisible = overlayVisible && showAnimateType === ShowAnimateEnum.None;
- // 关闭过程中使用下拉保存的透明度
- var currentOpacity = visible ? backdropOpacity : lastBackdropOpacity;
- // 覆盖物参数
- var overlayParams = {
- images: images,
- index: photoIndex,
- visible: visible,
- onClose: _this.handleClose,
- onIndexChange: _this.handleIndexChange,
- overlayVisible: currentOverlayVisible,
- onRotate: _this.handleRotate,
- rotate: rotatingMap.get(photoIndex) || 0,
- };
- return (React.createElement(SlideWrap, { className: classNames({
- 'PhotoView-PhotoSlider__clean': !currentOverlayVisible,
- 'PhotoView-PhotoSlider__willClose': !visible,
- }, className), role: "dialog", id: "PhotoView_Slider", onClick: function (e) { return e.stopPropagation(); } },
- React.createElement("div", { className: classNames('PhotoView-PhotoSlider__Backdrop', maskClassName, {
- 'PhotoView-PhotoSlider__fadeIn': showAnimateType === ShowAnimateEnum.In,
- 'PhotoView-PhotoSlider__fadeOut': showAnimateType === ShowAnimateEnum.Out,
- }), style: {
- background: "rgba(0, 0, 0, " + currentOpacity + ")",
- }, onAnimationEnd: onShowAnimateEnd }),
- bannerVisible && (React.createElement("div", { className: "PhotoView-PhotoSlider__BannerWrap" },
- React.createElement("div", { className: "PhotoView-PhotoSlider__Counter" },
- photoIndex + 1,
- " / ",
- imageLength),
- React.createElement("div", { className: "PhotoView-PhotoSlider__BannerRight" },
- toolbarRender && toolbarRender(overlayParams),
- React.createElement(Close, { className: "PhotoView-PhotoSlider__toolbarIcon", onClick: _this.handleClose })))),
- images
- .slice(
- // 加载相邻三张
- Math.max(photoIndex - 1, 0), Math.min(photoIndex + 2, imageLength + 1))
- .map(function (item, index) {
- // 截取之前的索引位置
- var realIndex = photoIndex === 0 ? photoIndex + index : photoIndex - 1 + index;
- return (React.createElement(PhotoView, { key: item.key || realIndex, src: item.src, intro: item.intro, onReachMove: _this.handleReachMove, onReachUp: _this.handleReachUp, onPhotoTap: _this.handlePhotoTap, onMaskTap: _this.handlePhotoMaskTap, viewClassName: viewClassName, className: imageClassName, style: {
- left: (innerWidth_1 + horizontalOffset) * realIndex + "px",
- WebkitTransform: transform,
- transform: transform,
- transition: touched || !shouldTransition
- ? undefined
- : 'transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1)',
- }, loadingElement: loadingElement, brokenElement: brokenElement, onPhotoResize: _this.handleResize, isActive: photoIndex === realIndex, showAnimateType: showAnimateType, originRect: originRect, rotate: rotatingMap.get(realIndex) || 0 }));
- }),
- !isTouchDevice && bannerVisible && (React.createElement(React.Fragment, null,
- photoIndex !== 0 && (React.createElement("div", { className: "PhotoView-PhotoSlider__ArrowLeft", onClick: function () { return _this.handlePrevious(false); } },
- React.createElement(ArrowLeft, null))),
- photoIndex + 1 < imageLength && (React.createElement("div", { className: "PhotoView-PhotoSlider__ArrowRight", onClick: function () { return _this.handleNext(false); } },
- React.createElement(ArrowRight, null))))),
- Boolean(introVisible && overlayIntro) && (React.createElement("div", { className: "PhotoView-PhotoSlider__FooterWrap" }, overlayIntro)),
- overlayRender && overlayRender(overlayParams)));
- }
- return null;
- }));
- };
- PhotoSlider.displayName = 'PhotoSlider';
- PhotoSlider.defaultProps = {
- maskClosable: true,
- photoClosable: false,
- bannerVisible: true,
- introVisible: true,
- };
- return PhotoSlider;
- }(React.Component));
- var PhotoProvider = /** @class */ (function (_super) {
- __extends(PhotoProvider, _super);
- function PhotoProvider(props) {
- var _this = _super.call(this, props) || this;
- _this.handleAddItem = function (imageItem) {
- _this.setState(function (prev) { return ({
- images: prev.images.concat(imageItem),
- }); });
- };
- _this.handleRemoveItem = function (key) {
- _this.setState(function (_a) {
- var images = _a.images, index = _a.index;
- var nextImages = images.filter(function (item) { return item.key !== key; });
- var nextEndIndex = nextImages.length - 1;
- return {
- images: nextImages,
- index: Math.min(nextEndIndex, index),
- };
- });
- };
- _this.handleShow = function (key) {
- var images = _this.state.images;
- _this.setState({
- visible: true,
- index: images.findIndex(function (item) { return item.key === key; }),
- });
- };
- _this.handleClose = function () {
- _this.setState({
- visible: false,
- });
- };
- _this.handleIndexChange = function (index) {
- _this.setState({
- index: index,
- });
- };
- _this.state = {
- images: [],
- visible: false,
- index: 0,
- addItem: _this.handleAddItem,
- removeItem: _this.handleRemoveItem,
- onShow: _this.handleShow,
- };
- return _this;
- }
- PhotoProvider.prototype.render = function () {
- var _a = this.props, children = _a.children, restProps = __rest(_a, ["children"]);
- var _b = this.state, images = _b.images, visible = _b.visible, index = _b.index;
- return (React.createElement(PhotoContext.Provider, { value: this.state },
- children,
- React.createElement(PhotoSlider, __assign({ images: images, visible: visible, index: index, onIndexChange: this.handleIndexChange, onClose: this.handleClose }, restProps))));
- };
- return PhotoProvider;
- }(React.Component));
- /**
- * 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 references for various `Number` constants. */
- var INFINITY = 1 / 0;
- /** `Object#toString` result references. */
- var symbolTag$1 = '[object Symbol]';
- /** Detect free variable `global` from Node.js. */
- var freeGlobal$1 = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
- /** Detect free variable `self`. */
- var freeSelf$1 = typeof self == 'object' && self && self.Object === Object && self;
- /** Used as a reference to the global object. */
- var root$1 = freeGlobal$1 || freeSelf$1 || Function('return this')();
- /** Used for built-in method references. */
- var objectProto$1 = Object.prototype;
- /** Used to generate unique IDs. */
- var idCounter = 0;
- /**
- * Used to resolve the
- * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
- * of values.
- */
- var objectToString$1 = objectProto$1.toString;
- /** Built-in value references. */
- var Symbol = root$1.Symbol;
- /** Used to convert symbols to primitives and strings. */
- var symbolProto = Symbol ? Symbol.prototype : undefined,
- symbolToString = symbolProto ? symbolProto.toString : undefined;
- /**
- * The base implementation of `_.toString` which doesn't convert nullish
- * values to empty strings.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
- function baseToString(value) {
- // Exit early for strings to avoid a performance hit in some environments.
- if (typeof value == 'string') {
- return value;
- }
- if (isSymbol$1(value)) {
- return symbolToString ? symbolToString.call(value) : '';
- }
- var result = (value + '');
- return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
- }
- /**
- * 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$1(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$1(value) {
- return typeof value == 'symbol' ||
- (isObjectLike$1(value) && objectToString$1.call(value) == symbolTag$1);
- }
- /**
- * Converts `value` to a string. An empty string is returned for `null`
- * and `undefined` values. The sign of `-0` is preserved.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- * @example
- *
- * _.toString(null);
- * // => ''
- *
- * _.toString(-0);
- * // => '-0'
- *
- * _.toString([1, 2, 3]);
- * // => '1,2,3'
- */
- function toString(value) {
- return value == null ? '' : baseToString(value);
- }
- /**
- * Generates a unique ID. If `prefix` is given, the ID is appended to it.
- *
- * @static
- * @since 0.1.0
- * @memberOf _
- * @category Util
- * @param {string} [prefix=''] The value to prefix the ID with.
- * @returns {string} Returns the unique ID.
- * @example
- *
- * _.uniqueId('contact_');
- * // => 'contact_104'
- *
- * _.uniqueId();
- * // => '105'
- */
- function uniqueId(prefix) {
- var id = ++idCounter;
- return toString(prefix) + id;
- }
- var lodash_uniqueid = uniqueId;
- var PhotoConsumer = function (_a) {
- var src = _a.src, intro = _a.intro, children = _a.children;
- var photoContext = React.useContext(PhotoContext);
- var key = React.useMemo(function () { return lodash_uniqueid(); }, []);
- var _b = React.useState({
- clientX: undefined,
- clientY: undefined,
- }), position = _b[0], updatePosition = _b[1];
- var photoTriggerRef = React.useRef(null);
- React.useEffect(function () {
- photoContext.addItem({
- key: key,
- src: src,
- originRef: photoTriggerRef.current,
- intro: intro,
- });
- return function () {
- photoContext.removeItem(key);
- };
- }, []);
- function handleTouchStart(e) {
- var _a = e.touches[0], clientX = _a.clientX, clientY = _a.clientY;
- updatePosition({
- clientX: clientX,
- clientY: clientY,
- });
- if (children) {
- var onTouchStart = children.props.onTouchStart;
- if (onTouchStart) {
- onTouchStart(e);
- }
- }
- }
- function handleTouchEnd(e) {
- var _a = e.changedTouches[0], clientX = _a.clientX, clientY = _a.clientY;
- if (position.clientX === clientX && position.clientY === clientY) {
- photoContext.onShow(key);
- }
- if (children) {
- var onTouchEnd = children.props.onTouchEnd;
- if (onTouchEnd) {
- onTouchEnd(e);
- }
- }
- }
- function handleClick(e) {
- photoContext.onShow(key);
- if (children) {
- var onClick = children.props.onClick;
- if (onClick) {
- onClick(e);
- }
- }
- }
- if (children) {
- return React.Children.only(React.cloneElement(children, isTouchDevice
- ? {
- onTouchStart: handleTouchStart,
- onTouchEnd: handleTouchEnd,
- ref: photoTriggerRef,
- }
- : { onClick: handleClick, ref: photoTriggerRef }));
- }
- return null;
- };
- exports.PhotoConsumer = PhotoConsumer;
- exports.PhotoProvider = PhotoProvider;
- exports.PhotoSlider = PhotoSlider;
- //# sourceMappingURL=index.js.map
|