@bikariya/image-viewer 0.0.5 → 0.0.7

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/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bikariya/image-viewer",
3
3
  "configKey": "image-viewer",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -1,13 +1,9 @@
1
- type __VLS_Props = {
1
+ import type { ModalProps } from "#modals";
2
+ type __VLS_Props = ModalProps & {
2
3
  /**
3
4
  * 目标 `<img>` 元素
4
5
  */
5
6
  target: HTMLImageElement;
6
- /**
7
- * 过渡动画时长 (ms)
8
- * @default 400
9
- */
10
- duration?: number;
11
7
  /**
12
8
  * 放大后占窗口比率
13
9
  * @default 0.9
@@ -18,7 +14,6 @@ type __VLS_Props = {
18
14
  * @default false
19
15
  */
20
16
  clamp?: boolean;
21
- open?: boolean;
22
17
  };
23
18
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
24
19
  close: () => any;
@@ -1,11 +1,11 @@
1
1
  <script setup>
2
2
  import { computed, ref, useEventListener, usePointer, useTemplateRef } from "#imports";
3
- const { target, duration = 400, rate = 0.9, clamp } = defineProps({
4
- target: { type: null, required: true },
3
+ const { target, duration, rate = 0.9, clamp } = defineProps({
5
4
  duration: { type: Number, required: false },
5
+ open: { type: Boolean, required: false },
6
+ target: { type: null, required: true },
6
7
  rate: { type: Number, required: false },
7
- clamp: { type: Boolean, required: false },
8
- open: { type: Boolean, required: false }
8
+ clamp: { type: Boolean, required: false }
9
9
  });
10
10
  const emit = defineEmits(["close"]);
11
11
  const rootEl = useTemplateRef("root");
@@ -74,7 +74,7 @@ const { isHolding } = usePointer(rootEl, {
74
74
  const finalTop = top - (center.value.y - top) * (rate2 - 1);
75
75
  const finalWidth = startRect.width * rate2;
76
76
  const finalHeight = startRect.height * rate2;
77
- if (isOverLimit(finalWidth, finalHeight, rate2)) {
77
+ if (isSizeOutOfBounds(finalWidth, finalHeight, rate2)) {
78
78
  return;
79
79
  }
80
80
  rootEl.value.animate({
@@ -108,7 +108,7 @@ function onWheel(event) {
108
108
  const finalTop = top - (event.clientY - top) * (rate2 - 1);
109
109
  const finalWidth = width * rate2;
110
110
  const finalHeight = height * rate2;
111
- if (isOverLimit(finalWidth, finalHeight, rate2)) {
111
+ if (isSizeOutOfBounds(finalWidth, finalHeight, rate2)) {
112
112
  return;
113
113
  }
114
114
  rootEl.value.animate({
@@ -120,58 +120,67 @@ function onWheel(event) {
120
120
  }
121
121
  function onDoubleClick(event) {
122
122
  const { left, top, width, height } = rootEl.value.getBoundingClientRect();
123
- const { size: [coverWidth, coverHeight], advantageSide } = getFitSize("cover");
124
- if (width < coverWidth && height < coverHeight) {
125
- const [finalLeft, finalTop] = advantageSide === "height" ? [
126
- `calc(50% - ${Math.round(coverWidth / 2)}px)`,
127
- `${top - (event.clientY - top) * (coverHeight / height - 1)}px`
128
- ] : [
129
- `${left - (event.clientX - left) * (coverWidth / width - 1)}px`,
130
- `calc(50% - ${Math.round(coverHeight / 2)}px)`
131
- ];
123
+ const { containSize, coverSize, advantageSide } = getFitSize();
124
+ if (width < coverSize.width && height < coverSize.height) {
125
+ const centerLoc = {
126
+ left: `calc(50% - ${Math.round(coverSize.width / 2)}px)`,
127
+ top: `calc(50% - ${Math.round(coverSize.height / 2)}px)`
128
+ };
129
+ const pointerLoc = {
130
+ left: `${left - (event.clientX - left) * (coverSize.width / width - 1)}px`,
131
+ top: `${top - (event.clientY - top) * (coverSize.height / height - 1)}px`
132
+ };
132
133
  rootEl.value.animate({
133
- left: finalLeft,
134
- top: finalTop,
135
- width: Math.ceil(coverWidth) + "px",
136
- height: Math.ceil(coverHeight) + "px"
134
+ left: advantageSide === "height" ? centerLoc.left : pointerLoc.left,
135
+ top: advantageSide === "height" ? pointerLoc.top : centerLoc.top,
136
+ width: Math.ceil(coverSize.width) + "px",
137
+ height: Math.ceil(coverSize.height) + "px"
137
138
  }, options.value);
138
139
  } else {
139
- const { size: [containWidth, containHeight] } = getFitSize("contain");
140
140
  rootEl.value.animate({
141
- left: `calc(50% - ${Math.round(containWidth / 2)}px)`,
142
- top: `calc(50% - ${Math.round(containHeight / 2)}px)`,
143
- width: Math.floor(containWidth) + "px",
144
- height: Math.floor(containHeight) + "px"
141
+ left: `calc(50% - ${Math.round(containSize.width / 2)}px)`,
142
+ top: `calc(50% - ${Math.round(containSize.height / 2)}px)`,
143
+ width: Math.floor(containSize.width) + "px",
144
+ height: Math.floor(containSize.height) + "px"
145
145
  }, options.value);
146
146
  }
147
147
  }
148
148
  const onEnter = (el) => {
149
- const { size: [containWidth, containHeight] } = getFitSize("contain");
149
+ const { containSize } = getFitSize();
150
150
  el.animate([getOriginalKeyframe(), {
151
- top: `calc(50% - ${Math.round(containHeight / 2)}px)`,
152
- left: `calc(50% - ${Math.round(containWidth / 2)}px)`,
153
- width: Math.floor(containWidth) + "px",
154
- height: Math.floor(containHeight) + "px",
151
+ top: `calc(50% - ${Math.round(containSize.height / 2)}px)`,
152
+ left: `calc(50% - ${Math.round(containSize.width / 2)}px)`,
153
+ width: Math.floor(containSize.width) + "px",
154
+ height: Math.floor(containSize.height) + "px",
155
155
  clipPath: "inset(0)"
156
156
  }], options.value);
157
157
  };
158
158
  const onLeave = (el, done) => {
159
- const { left: elLeft, top: elTop } = el.getBoundingClientRect();
160
- const { scrollX: x, scrollY: y } = window;
159
+ const { left, top } = el.getBoundingClientRect();
160
+ const { scrollX, scrollY } = window;
161
161
  const animation = el.animate([{
162
- top: 2 * y + elTop + "px",
163
- left: 2 * x + elLeft + "px",
162
+ top: `calc(${2 * scrollY + top}px + 50dvh - 50svh)`,
163
+ left: `calc(${2 * scrollX + left}px + 50dvw - 50svw)`,
164
164
  clipPath: "inset(0)"
165
- }, getOriginalKeyframe(x, y)], options.value);
165
+ }, getOriginalKeyframe(scrollX, scrollY)], options.value);
166
166
  animation.addEventListener("finish", done);
167
167
  };
168
- function getFitSize(mode) {
168
+ function getFitSize() {
169
169
  const fixedWidth = window.innerWidth * rate;
170
170
  const fixedHeight = window.innerHeight * rate;
171
171
  const naturalRatio = target.naturalWidth / target.naturalHeight;
172
172
  const advantageSide = fixedWidth / fixedHeight > naturalRatio ? "height" : "width";
173
+ const widthSize = {
174
+ width: fixedWidth,
175
+ height: fixedWidth / naturalRatio
176
+ };
177
+ const heightSize = {
178
+ width: fixedHeight * naturalRatio,
179
+ height: fixedHeight
180
+ };
173
181
  return {
174
- size: +(advantageSide === "height") ^ +(mode === "cover") ? [fixedHeight * naturalRatio, fixedHeight] : [fixedWidth, fixedWidth / naturalRatio],
182
+ containSize: advantageSide === "height" ? heightSize : widthSize,
183
+ coverSize: advantageSide === "height" ? widthSize : heightSize,
175
184
  advantageSide
176
185
  };
177
186
  }
@@ -187,13 +196,13 @@ function getOriginalKeyframe(x = 0, y = 0) {
187
196
  let clipLeft = 0;
188
197
  let clipRight = 0;
189
198
  if (ratio > naturalRatio) {
190
- const fullHeight = naturalHeight * width / naturalWidth;
191
- clipTop = (fullHeight - height) * vertical;
192
- clipBottom = fullHeight - height - clipTop;
199
+ const rest = width / naturalRatio - height;
200
+ clipTop = rest * vertical;
201
+ clipBottom = rest - clipTop;
193
202
  } else {
194
- const fullWidth = naturalWidth * height / naturalHeight;
195
- clipLeft = (fullWidth - width) * horizontal;
196
- clipRight = fullWidth - width - clipLeft;
203
+ const rest = height * naturalRatio - width;
204
+ clipLeft = rest * horizontal;
205
+ clipRight = rest - clipLeft;
197
206
  }
198
207
  return {
199
208
  top: y + top - clipTop + "px",
@@ -203,7 +212,7 @@ function getOriginalKeyframe(x = 0, y = 0) {
203
212
  clipPath: `inset(${clipTop}px ${clipRight}px ${clipBottom}px ${clipLeft}px)`
204
213
  };
205
214
  }
206
- function isOverLimit(width, height, rate2) {
215
+ function isSizeOutOfBounds(width, height, rate2) {
207
216
  if (!clamp) {
208
217
  return false;
209
218
  }
@@ -1,13 +1,9 @@
1
- type __VLS_Props = {
1
+ import type { ModalProps } from "#modals";
2
+ type __VLS_Props = ModalProps & {
2
3
  /**
3
4
  * 目标 `<img>` 元素
4
5
  */
5
6
  target: HTMLImageElement;
6
- /**
7
- * 过渡动画时长 (ms)
8
- * @default 400
9
- */
10
- duration?: number;
11
7
  /**
12
8
  * 放大后占窗口比率
13
9
  * @default 0.9
@@ -18,7 +14,6 @@ type __VLS_Props = {
18
14
  * @default false
19
15
  */
20
16
  clamp?: boolean;
21
- open?: boolean;
22
17
  };
23
18
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
24
19
  close: () => any;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bikariya/image-viewer",
3
3
  "type": "module",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
5
5
  "description": "Bikariya image viewer for Nuxt",
6
6
  "author": "KazariEX",
7
7
  "license": "MIT",
@@ -15,8 +15,8 @@
15
15
  "dist"
16
16
  ],
17
17
  "dependencies": {
18
- "@bikariya/modals": "",
19
- "@nuxt/kit": "^4.3.0"
18
+ "@nuxt/kit": "^4.3.1",
19
+ "@bikariya/modals": "0.0.7"
20
20
  },
21
21
  "scripts": {
22
22
  "build": "nuxt-module-build build",