smartphoto 2.1.11 → 2.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/css/smartphoto.css +24 -0
- package/css/smartphoto.min.css +1 -1
- package/js/jquery-smartphoto.js +179 -31
- package/js/jquery-smartphoto.min.js +2 -2
- package/js/smartphoto.js +179 -31
- package/js/smartphoto.min.js +2 -2
- package/lib/smartphoto.js +178 -30
- package/lib/smartphoto.mjs +178 -30
- package/lib/types/core/index.d.ts +5 -0
- package/lib/types/core/types.d.ts +2 -1
- package/lib/types/core/view.d.ts +1 -0
- package/lib/types/lib/util.d.ts +1 -0
- package/package.json +1 -1
package/lib/smartphoto.mjs
CHANGED
|
@@ -3,6 +3,9 @@ var isSmartPhone = () => {
|
|
|
3
3
|
const agent = navigator.userAgent;
|
|
4
4
|
return agent.indexOf("iPhone") > 0 || agent.indexOf("iPad") > 0 || agent.indexOf("ipod") > 0 || agent.indexOf("Android") > 0;
|
|
5
5
|
};
|
|
6
|
+
var isWebKit = () => {
|
|
7
|
+
return typeof window.webkitConvertPointFromNodeToPage === "function";
|
|
8
|
+
};
|
|
6
9
|
function deepExtend(out, ...args) {
|
|
7
10
|
out = out || {};
|
|
8
11
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -140,6 +143,7 @@ var defaults = {
|
|
|
140
143
|
verticalGravity: false,
|
|
141
144
|
useOrientationApi: false,
|
|
142
145
|
useHistoryApi: true,
|
|
146
|
+
useViewTransitionApi: true,
|
|
143
147
|
swipeTopToClose: false,
|
|
144
148
|
swipeBottomToClose: true,
|
|
145
149
|
swipeOffset: 100,
|
|
@@ -424,6 +428,7 @@ function createGestures({ state, callbacks }, { signal }) {
|
|
|
424
428
|
let oldPos = null;
|
|
425
429
|
let moveDir = null;
|
|
426
430
|
let swipeStartTime = 0;
|
|
431
|
+
let tapTarget = null;
|
|
427
432
|
let photoSwipable = false;
|
|
428
433
|
let firstPhotoPos = null;
|
|
429
434
|
let oldPhotoPos = null;
|
|
@@ -554,6 +559,7 @@ function createGestures({ state, callbacks }, { signal }) {
|
|
|
554
559
|
firstPos = pos;
|
|
555
560
|
oldPos = pos;
|
|
556
561
|
swipeStartTime = Date.now();
|
|
562
|
+
tapTarget = e.target;
|
|
557
563
|
}
|
|
558
564
|
function startPhotoDrag(e) {
|
|
559
565
|
photoSwipable = true;
|
|
@@ -693,11 +699,11 @@ function createGestures({ state, callbacks }, { signal }) {
|
|
|
693
699
|
const swipeHeight = last.y - first.y;
|
|
694
700
|
const noMove = swipeWidth === 0 && swipeHeight === 0;
|
|
695
701
|
if (!isSmartPhone2() && noMove) {
|
|
696
|
-
callbacks.onTap();
|
|
702
|
+
callbacks.onTap(tapTarget);
|
|
697
703
|
return;
|
|
698
704
|
}
|
|
699
705
|
if (Math.abs(offset) <= 500 && noMove) {
|
|
700
|
-
callbacks.onTap();
|
|
706
|
+
callbacks.onTap(tapTarget);
|
|
701
707
|
return;
|
|
702
708
|
}
|
|
703
709
|
tapSecond = now;
|
|
@@ -1017,6 +1023,9 @@ function createView({ id, options }, handlers, { signal }) {
|
|
|
1017
1023
|
if (slideRefs.imgWrap && slideRefs.img) {
|
|
1018
1024
|
slideRefs.imgWrap.style.transform = `translate(${item.x}px,${item.y}px) scale(${item.scale})`;
|
|
1019
1025
|
slideRefs.img.style.width = `${item.width}px`;
|
|
1026
|
+
if (!isCurrent) {
|
|
1027
|
+
slideRefs.img.style.transform = "translate(0px,0px) scale(1)";
|
|
1028
|
+
}
|
|
1020
1029
|
slideRefs.img.classList.toggle("active", viewer.appear);
|
|
1021
1030
|
slideRefs.img.classList.toggle(
|
|
1022
1031
|
classNames.smartPhotoImgOnMove,
|
|
@@ -1100,6 +1109,23 @@ function createView({ id, options }, handlers, { signal }) {
|
|
|
1100
1109
|
refs.list.style.transform = `translate(${viewer.translateX}px,${viewer.translateY}px)`;
|
|
1101
1110
|
refs.list.classList.toggle(classNames.smartPhotoListOnMove, viewer.onMove);
|
|
1102
1111
|
}
|
|
1112
|
+
function applyViewTransitionLayout(state) {
|
|
1113
|
+
for (const [item, slideRefs] of refs.slides) {
|
|
1114
|
+
if (item.index !== state.viewer.currentIndex) {
|
|
1115
|
+
continue;
|
|
1116
|
+
}
|
|
1117
|
+
const { img, imgWrap } = slideRefs;
|
|
1118
|
+
if (!img || !imgWrap || !item.width || !item.scale || item.scale >= 1) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
const before = img.getBoundingClientRect();
|
|
1122
|
+
img.style.width = `${item.width * item.scale}px`;
|
|
1123
|
+
imgWrap.style.transform = `translate(${item.x}px,${item.y}px) scale(1)`;
|
|
1124
|
+
const after = img.getBoundingClientRect();
|
|
1125
|
+
imgWrap.style.transform = `translate(${item.x + before.left - after.left}px,${item.y + before.top - after.top}px) scale(1)`;
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1103
1129
|
function showAppearEffect(effect) {
|
|
1104
1130
|
const clone = document.createElement("img");
|
|
1105
1131
|
clone.className = classNames.smartPhotoImgClone;
|
|
@@ -1123,6 +1149,7 @@ function createView({ id, options }, handlers, { signal }) {
|
|
|
1123
1149
|
render,
|
|
1124
1150
|
syncSlides,
|
|
1125
1151
|
updatePhotoTransform,
|
|
1152
|
+
applyViewTransitionLayout,
|
|
1126
1153
|
updateListTransform,
|
|
1127
1154
|
showAppearEffect,
|
|
1128
1155
|
removeAppearEffect,
|
|
@@ -1159,6 +1186,13 @@ var SmartPhoto = class {
|
|
|
1159
1186
|
// doHideEffect() の後始末(画像に設定した translateY の除去と promise 解決)を
|
|
1160
1187
|
// transitionend を待たずに即時実行するための関数。後始末が済むと null に戻る
|
|
1161
1188
|
this.finishHideEffect = null;
|
|
1189
|
+
// 開く View Transition が進行中かどうか。進行中にリサイズ由来の再計算(commit)が
|
|
1190
|
+
// 走ると、モーフの目標位置は古いビューポート基準のままなのに実要素だけ新しい
|
|
1191
|
+
// 位置へ動いて「一旦ずれた位置に出てから正位置へ戻る」ように見え、さらに
|
|
1192
|
+
// モーフ用レイアウト(applyViewTransitionLayout)も巻き戻されてしまう。
|
|
1193
|
+
// そのため進行中はリサイズ再計算を保留し、finished 後にまとめて実行する
|
|
1194
|
+
this.isViewTransitionActive = false;
|
|
1195
|
+
this.pendingViewTransitionResync = false;
|
|
1162
1196
|
this.timeouts = [];
|
|
1163
1197
|
this.loadAllFired = /* @__PURE__ */ new Set();
|
|
1164
1198
|
this.syncedGroupId = null;
|
|
@@ -1217,16 +1251,24 @@ var SmartPhoto = class {
|
|
|
1217
1251
|
if (!this.isSmartPhoneFlag || !this.state.viewer.isOpen || !currentItems(this.state)) {
|
|
1218
1252
|
return;
|
|
1219
1253
|
}
|
|
1254
|
+
if (this.isViewTransitionActive) {
|
|
1255
|
+
this.pendingViewTransitionResync = true;
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1220
1258
|
this.resetTranslateCurrent();
|
|
1221
1259
|
this.setPosByCurrentIndex();
|
|
1222
1260
|
this.setSizeByScreen();
|
|
1223
1261
|
this.commit();
|
|
1224
1262
|
};
|
|
1225
1263
|
this.handleResize = () => {
|
|
1226
|
-
if (!currentItems(this.state)) {
|
|
1264
|
+
if (!this.state.viewer.isOpen || !currentItems(this.state)) {
|
|
1227
1265
|
return;
|
|
1228
1266
|
}
|
|
1229
1267
|
this.updateViewportHeight();
|
|
1268
|
+
if (this.isViewTransitionActive) {
|
|
1269
|
+
this.pendingViewTransitionResync = true;
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1230
1272
|
this.resetTranslateCurrent();
|
|
1231
1273
|
this.setPosByCurrentIndex();
|
|
1232
1274
|
this.setSizeByScreen();
|
|
@@ -1246,7 +1288,11 @@ var SmartPhoto = class {
|
|
|
1246
1288
|
}
|
|
1247
1289
|
};
|
|
1248
1290
|
this.handleOrientationChange = () => {
|
|
1249
|
-
if (!currentItems(this.state)) {
|
|
1291
|
+
if (!this.state.viewer.isOpen || !currentItems(this.state)) {
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
if (this.isViewTransitionActive) {
|
|
1295
|
+
this.pendingViewTransitionResync = true;
|
|
1250
1296
|
return;
|
|
1251
1297
|
}
|
|
1252
1298
|
this.updateViewportHeight();
|
|
@@ -1259,6 +1305,9 @@ var SmartPhoto = class {
|
|
|
1259
1305
|
const timeout = 500;
|
|
1260
1306
|
const poll = (time) => {
|
|
1261
1307
|
this.scheduleTimeout(() => {
|
|
1308
|
+
if (!this.state.viewer.isOpen) {
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1262
1311
|
if (prevWidth !== getWindowWidth2()) {
|
|
1263
1312
|
this.updateViewportHeight();
|
|
1264
1313
|
this.resetTranslateCurrent();
|
|
@@ -1410,10 +1459,26 @@ var SmartPhoto = class {
|
|
|
1410
1459
|
this.state.viewer.photoPosY = 0;
|
|
1411
1460
|
this.view.updatePhotoTransform(this.state);
|
|
1412
1461
|
this.scheduleTimeout(() => {
|
|
1462
|
+
if (!this.state.viewer.isOpen) {
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1413
1465
|
this.state.viewer.scale = true;
|
|
1414
1466
|
this.view.updatePhotoTransform(this.state);
|
|
1415
1467
|
this.fireEvent("zoomin");
|
|
1416
|
-
},
|
|
1468
|
+
}, this.state.options.animationSpeed);
|
|
1469
|
+
}
|
|
1470
|
+
// zoomPhoto() と同じ「ズームの余地があるか」の判定(scaleBorder <= 1 なら
|
|
1471
|
+
// ズームしても見た目が変わらない)。zoomPhoto() 自体は公開 API の契約
|
|
1472
|
+
// (ズームできなければ何もしない)を保つ必要があるため、タップの
|
|
1473
|
+
// zoom-or-close 分岐(§7)用に判定だけを切り出している
|
|
1474
|
+
canZoomCurrentPhoto() {
|
|
1475
|
+
const item = currentItem(this.state);
|
|
1476
|
+
return !!item && scaleBorder(
|
|
1477
|
+
item,
|
|
1478
|
+
getWindowWidth2(),
|
|
1479
|
+
getWindowHeight2(),
|
|
1480
|
+
this.isSmartPhoneFlag
|
|
1481
|
+
) > 1;
|
|
1417
1482
|
}
|
|
1418
1483
|
zoomOutPhoto() {
|
|
1419
1484
|
this.state.viewer.scaleSize = 1;
|
|
@@ -1619,6 +1684,7 @@ var SmartPhoto = class {
|
|
|
1619
1684
|
this.state.options.headerHeight,
|
|
1620
1685
|
this.state.options.footerHeight
|
|
1621
1686
|
);
|
|
1687
|
+
this.syncFillScale();
|
|
1622
1688
|
}
|
|
1623
1689
|
// resize/orientationchange ハンドラは呼び出し前に currentItems の存在を確認済み
|
|
1624
1690
|
resetTranslateCurrent() {
|
|
@@ -1632,9 +1698,18 @@ var SmartPhoto = class {
|
|
|
1632
1698
|
}
|
|
1633
1699
|
return null;
|
|
1634
1700
|
}
|
|
1701
|
+
currentLiElement() {
|
|
1702
|
+
for (const [item, slideRefs] of this.view.refs.slides) {
|
|
1703
|
+
if (item.index === this.state.viewer.currentIndex) {
|
|
1704
|
+
return slideRefs.li;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
return null;
|
|
1708
|
+
}
|
|
1635
1709
|
// ---- 内部: dialog 制御(§8) ----
|
|
1636
1710
|
syncDialog() {
|
|
1637
1711
|
const { dialog, caption } = this.view.refs;
|
|
1712
|
+
dialog.style.transition = this.state.options.showAnimation === false ? "none" : "";
|
|
1638
1713
|
if (this.state.viewer.isOpen && !dialog.open) {
|
|
1639
1714
|
dialog.style.removeProperty("display");
|
|
1640
1715
|
dialog.showModal();
|
|
@@ -1646,6 +1721,7 @@ var SmartPhoto = class {
|
|
|
1646
1721
|
}
|
|
1647
1722
|
commit() {
|
|
1648
1723
|
this.view.render(this.state);
|
|
1724
|
+
this.view.updatePhotoTransform(this.state);
|
|
1649
1725
|
this.syncDialog();
|
|
1650
1726
|
}
|
|
1651
1727
|
// ---- 内部: 開く演出 ----
|
|
@@ -1663,20 +1739,34 @@ var SmartPhoto = class {
|
|
|
1663
1739
|
this.setPosByCurrentIndex();
|
|
1664
1740
|
this.setSizeByScreen();
|
|
1665
1741
|
setArrow(this.state);
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1742
|
+
}
|
|
1743
|
+
// resizeStyle: 'fill' はスマートフォンでのみ、画面を隙間なく覆うよう
|
|
1744
|
+
// scaleBorder() の倍率を viewer.scaleSize に適用する。fit用の item.scale に
|
|
1745
|
+
// 依存するため、setSizeByScreen() の末尾から必ず呼ばれる(個別に呼ぶ必要はない)
|
|
1746
|
+
syncFillScale() {
|
|
1747
|
+
if (this.state.options.resizeStyle !== "fill" || !this.isSmartPhoneFlag) {
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
const item = currentItem(this.state);
|
|
1751
|
+
if (!item) {
|
|
1752
|
+
return;
|
|
1676
1753
|
}
|
|
1754
|
+
this.state.viewer.scale = true;
|
|
1755
|
+
this.state.viewer.hideUi = true;
|
|
1756
|
+
this.state.viewer.scaleSize = scaleBorder(
|
|
1757
|
+
item,
|
|
1758
|
+
getWindowWidth2(),
|
|
1759
|
+
getWindowHeight2(),
|
|
1760
|
+
this.isSmartPhoneFlag
|
|
1761
|
+
);
|
|
1677
1762
|
}
|
|
1678
1763
|
supportsViewTransition() {
|
|
1679
|
-
return typeof document.startViewTransition === "function"
|
|
1764
|
+
return this.state.options.useViewTransitionApi && typeof document.startViewTransition === "function" && // WebKit には「view-transition-name 付き要素が root スナップショットから
|
|
1765
|
+
// 除外されず、モーフ中に最終位置へ二重描画される」実装バグがあり、開く演出が
|
|
1766
|
+
// 「一旦ずれた位置に出てから正位置へ戻る」ように乱れる。API 対応の有無では
|
|
1767
|
+
// 検出できないため、WebKit ではクローン演出(addAppearEffect)へフォールバック
|
|
1768
|
+
// する(§util.isWebKit)
|
|
1769
|
+
!isWebKit();
|
|
1680
1770
|
}
|
|
1681
1771
|
openPhotoWithViewTransition(trigger) {
|
|
1682
1772
|
document.documentElement.style.setProperty(
|
|
@@ -1688,7 +1778,8 @@ var SmartPhoto = class {
|
|
|
1688
1778
|
if (thumbImg) {
|
|
1689
1779
|
thumbImg.style.viewTransitionName = transitionName;
|
|
1690
1780
|
}
|
|
1691
|
-
const
|
|
1781
|
+
const cleanup = () => {
|
|
1782
|
+
this.isViewTransitionActive = false;
|
|
1692
1783
|
if (thumbImg) {
|
|
1693
1784
|
thumbImg.style.viewTransitionName = "";
|
|
1694
1785
|
}
|
|
@@ -1696,6 +1787,21 @@ var SmartPhoto = class {
|
|
|
1696
1787
|
if (img) {
|
|
1697
1788
|
img.style.viewTransitionName = "";
|
|
1698
1789
|
}
|
|
1790
|
+
if (!this.state.viewer.isOpen) {
|
|
1791
|
+
this.pendingViewTransitionResync = false;
|
|
1792
|
+
return;
|
|
1793
|
+
}
|
|
1794
|
+
if (this.pendingViewTransitionResync && currentItems(this.state)) {
|
|
1795
|
+
this.pendingViewTransitionResync = false;
|
|
1796
|
+
this.updateViewportHeight();
|
|
1797
|
+
this.resetTranslateCurrent();
|
|
1798
|
+
this.setPosByCurrentIndex();
|
|
1799
|
+
this.setSizeByScreen();
|
|
1800
|
+
this.commit();
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1803
|
+
this.pendingViewTransitionResync = false;
|
|
1804
|
+
this.view.render(this.state);
|
|
1699
1805
|
};
|
|
1700
1806
|
const transition = document.startViewTransition?.(() => {
|
|
1701
1807
|
this.initPhoto();
|
|
@@ -1705,11 +1811,16 @@ var SmartPhoto = class {
|
|
|
1705
1811
|
thumbImg.style.viewTransitionName = "";
|
|
1706
1812
|
}
|
|
1707
1813
|
this.currentImgElement().style.viewTransitionName = transitionName;
|
|
1814
|
+
this.view.applyViewTransitionLayout(this.state);
|
|
1708
1815
|
});
|
|
1709
|
-
transition
|
|
1710
|
-
|
|
1816
|
+
if (!transition) {
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
this.isViewTransitionActive = true;
|
|
1820
|
+
transition.ready.catch(() => {
|
|
1821
|
+
cleanup();
|
|
1711
1822
|
});
|
|
1712
|
-
transition
|
|
1823
|
+
transition.finished.then(cleanup, cleanup);
|
|
1713
1824
|
}
|
|
1714
1825
|
// doOpen() の呼び出し元でこの分岐に来る時点で showAnimation !== false が保証されている
|
|
1715
1826
|
addAppearEffect(trigger, item) {
|
|
@@ -1818,10 +1929,14 @@ var SmartPhoto = class {
|
|
|
1818
1929
|
if (getWindowWidth2() === winWidthBefore && getWindowHeight2() === winHeightBefore) {
|
|
1819
1930
|
return;
|
|
1820
1931
|
}
|
|
1932
|
+
if (this.isViewTransitionActive) {
|
|
1933
|
+
this.pendingViewTransitionResync = true;
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1821
1936
|
this.resetTranslateCurrent();
|
|
1822
1937
|
this.setPosByCurrentIndex();
|
|
1823
1938
|
this.setSizeByScreen();
|
|
1824
|
-
this.
|
|
1939
|
+
this.commit();
|
|
1825
1940
|
});
|
|
1826
1941
|
}
|
|
1827
1942
|
openPhoto(item, trigger) {
|
|
@@ -1843,25 +1958,42 @@ var SmartPhoto = class {
|
|
|
1843
1958
|
}
|
|
1844
1959
|
doHideEffect(dir) {
|
|
1845
1960
|
return new Promise((resolve) => {
|
|
1961
|
+
if (this.state.options.showAnimation === false) {
|
|
1962
|
+
resolve();
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1846
1965
|
const dialog = this.view.refs.dialog;
|
|
1847
|
-
const
|
|
1966
|
+
const item = currentItem(this.state);
|
|
1967
|
+
const li = item ? this.currentLiElement() : null;
|
|
1848
1968
|
const height = getWindowHeight2();
|
|
1849
|
-
const
|
|
1850
|
-
|
|
1969
|
+
const img = this.currentImgElement();
|
|
1970
|
+
let frozenTransform = null;
|
|
1971
|
+
if (img) {
|
|
1972
|
+
const rendered = getComputedStyle(img).transform;
|
|
1973
|
+
if (rendered && rendered !== "none") {
|
|
1974
|
+
img.style.transform = rendered;
|
|
1975
|
+
frozenTransform = img.style.transform;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
if (li && item) {
|
|
1979
|
+
const offsetY = dir === "top" ? -height : height;
|
|
1980
|
+
li.style.transform = `translate(${item.translateX}px,${item.translateY + offsetY}px)`;
|
|
1981
|
+
}
|
|
1982
|
+
const finish = (e) => {
|
|
1851
1983
|
if (this.finishHideEffect !== finish) {
|
|
1852
1984
|
return;
|
|
1853
1985
|
}
|
|
1986
|
+
if (e && e.target !== dialog) {
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1854
1989
|
this.finishHideEffect = null;
|
|
1855
1990
|
dialog.removeEventListener("transitionend", finish, true);
|
|
1856
|
-
if (img && img.style.transform ===
|
|
1991
|
+
if (img && frozenTransform && img.style.transform === frozenTransform) {
|
|
1857
1992
|
img.style.transform = "";
|
|
1858
1993
|
}
|
|
1859
1994
|
resolve();
|
|
1860
1995
|
};
|
|
1861
1996
|
this.finishHideEffect = finish;
|
|
1862
|
-
if (img) {
|
|
1863
|
-
img.style.transform = applied;
|
|
1864
|
-
}
|
|
1865
1997
|
dialog.addEventListener("transitionend", finish, true);
|
|
1866
1998
|
this.scheduleTimeout(finish, this.state.options.animationSpeed + 100);
|
|
1867
1999
|
});
|
|
@@ -1931,7 +2063,9 @@ var SmartPhoto = class {
|
|
|
1931
2063
|
const item = currentItem(this.state);
|
|
1932
2064
|
this.state.viewer.onMove = false;
|
|
1933
2065
|
setArrow(this.state);
|
|
1934
|
-
this.
|
|
2066
|
+
if (this.state.viewer.isOpen) {
|
|
2067
|
+
this.commit();
|
|
2068
|
+
}
|
|
1935
2069
|
if (this.state.viewer.oldIndex !== this.state.viewer.currentIndex) {
|
|
1936
2070
|
this.fireEvent("change");
|
|
1937
2071
|
}
|
|
@@ -2016,7 +2150,21 @@ var SmartPhoto = class {
|
|
|
2016
2150
|
}
|
|
2017
2151
|
this.slideList();
|
|
2018
2152
|
},
|
|
2019
|
-
|
|
2153
|
+
// 主要ライトボックスのデファクトスタンダード(PhotoSwipe: bgClickAction
|
|
2154
|
+
// 'close' / imageClickAction 'zoom-or-close'、Fancybox: backdropClick
|
|
2155
|
+
// 'close'、GLightbox: closeOnOutsideClick、lightGallery: closable)に合わせ、
|
|
2156
|
+
// 写真の上のタップはズーム、写真の外(背景)のタップは閉じる。ズームの
|
|
2157
|
+
// 余地がない(scaleBorder <= 1 で zoomPhoto() が何もしない)写真の上の
|
|
2158
|
+
// タップも、無反応にせず 'zoom-or-close' に倣って閉じる
|
|
2159
|
+
onTap: (target) => {
|
|
2160
|
+
const img = this.currentImgElement();
|
|
2161
|
+
const onPhoto = !!img && target instanceof Node && img.contains(target);
|
|
2162
|
+
if (onPhoto && this.canZoomCurrentPhoto()) {
|
|
2163
|
+
this.zoomPhoto();
|
|
2164
|
+
} else {
|
|
2165
|
+
this.hidePhoto();
|
|
2166
|
+
}
|
|
2167
|
+
},
|
|
2020
2168
|
onGestureStart: () => {
|
|
2021
2169
|
this.fireEvent("gesturestart");
|
|
2022
2170
|
this.view.updatePhotoTransform(this.state);
|
|
@@ -13,6 +13,8 @@ export default class SmartPhoto {
|
|
|
13
13
|
private lastTriggerElement;
|
|
14
14
|
private isFiringPublicCloseEvent;
|
|
15
15
|
private finishHideEffect;
|
|
16
|
+
private isViewTransitionActive;
|
|
17
|
+
private pendingViewTransitionResync;
|
|
16
18
|
private timeouts;
|
|
17
19
|
private loadAllFired;
|
|
18
20
|
private syncedGroupId;
|
|
@@ -25,6 +27,7 @@ export default class SmartPhoto {
|
|
|
25
27
|
gotoSlide(index: number): void;
|
|
26
28
|
hidePhoto(dir?: "top" | "bottom"): void;
|
|
27
29
|
zoomPhoto(): void;
|
|
30
|
+
private canZoomCurrentPhoto;
|
|
28
31
|
zoomOutPhoto(): void;
|
|
29
32
|
addNewItem(element: HTMLElement): SmartPhotoItem;
|
|
30
33
|
show(indexOrId?: ItemId, opts?: ShowOptions): void;
|
|
@@ -47,9 +50,11 @@ export default class SmartPhoto {
|
|
|
47
50
|
private setSizeByScreen;
|
|
48
51
|
private resetTranslateCurrent;
|
|
49
52
|
private currentImgElement;
|
|
53
|
+
private currentLiElement;
|
|
50
54
|
private syncDialog;
|
|
51
55
|
private commit;
|
|
52
56
|
private initPhoto;
|
|
57
|
+
private syncFillScale;
|
|
53
58
|
private supportsViewTransition;
|
|
54
59
|
private openPhotoWithViewTransition;
|
|
55
60
|
private addAppearEffect;
|
|
@@ -40,6 +40,7 @@ export interface ResolvedSmartPhotoOptions {
|
|
|
40
40
|
verticalGravity: boolean;
|
|
41
41
|
useOrientationApi: boolean;
|
|
42
42
|
useHistoryApi: boolean;
|
|
43
|
+
useViewTransitionApi: boolean;
|
|
43
44
|
swipeTopToClose: boolean;
|
|
44
45
|
swipeBottomToClose: boolean;
|
|
45
46
|
swipeOffset: number;
|
|
@@ -141,7 +142,7 @@ export interface GestureCallbacks {
|
|
|
141
142
|
onSwipeStart(): void;
|
|
142
143
|
onSwipeMove(): void;
|
|
143
144
|
onSwipeEnd(result: SwipeEndResult): void;
|
|
144
|
-
onTap(): void;
|
|
145
|
+
onTap(target: EventTarget | null): void;
|
|
145
146
|
onGestureStart(): void;
|
|
146
147
|
onGestureMove(): void;
|
|
147
148
|
onGestureEnd(): void;
|
package/lib/types/core/view.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export interface View {
|
|
|
34
34
|
render(state: State): void;
|
|
35
35
|
syncSlides(items: Item[], state: State): void;
|
|
36
36
|
updatePhotoTransform(state: State): void;
|
|
37
|
+
applyViewTransitionLayout(state: State): void;
|
|
37
38
|
updateListTransform(state: State): void;
|
|
38
39
|
showAppearEffect(effect: AppearEffect): void;
|
|
39
40
|
removeAppearEffect(): void;
|
package/lib/types/lib/util.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const isSmartPhone: () => boolean;
|
|
2
|
+
export declare const isWebKit: () => boolean;
|
|
2
3
|
declare function deepExtend(out: Record<string, unknown>, ...args: unknown[]): Record<string, unknown>;
|
|
3
4
|
export declare const extend: typeof deepExtend;
|
|
4
5
|
export declare const triggerEvent: (el: Element, eventName: string, options?: unknown) => void;
|