You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@bikariya/image-viewer

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bikariya/image-viewer - npm Package Compare versions

Comparing version
0.0.4
to
0.0.5
+1
-1
dist/module.json
{
"name": "@bikariya/image-viewer",
"configKey": "image-viewer",
"version": "0.0.4",
"version": "0.0.5",
"builder": {

@@ -6,0 +6,0 @@ "@nuxt/module-builder": "1.0.2",

type __VLS_Props = {
/**
* 目标 `<img>` 元素
*/
target: HTMLImageElement;
/**
* 过渡动画时长 (ms)
* @default 400
*/
duration?: number;
isOpening?: boolean;
/**
* 放大后占窗口比率
* @default 0.9
*/
rate?: number;
/**
* 是否限制缩放比例
* @default false
*/
clamp?: boolean;
open?: boolean;
};

@@ -6,0 +23,0 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {

<script setup>
import { computed, ref, useEventListener, usePointer, useTemplateRef } from "#imports";
const props = defineProps({
const { target, duration = 400, rate = 0.9, clamp } = defineProps({
target: { type: null, required: true },
duration: { type: Number, required: false },
isOpening: { type: Boolean, required: false }
rate: { type: Number, required: false },
clamp: { type: Boolean, required: false },
open: { type: Boolean, required: false }
});
const emit = defineEmits(["close"]);
const rootEl = useTemplateRef("root");
const rate = 0.9;
useEventListener("keydown", (event) => {
if (event.key === "Escape") {
emit("close");
}
});
const options = computed(() => {
return {
duration: props.duration ?? 400,
duration,
easing: "ease",

@@ -22,5 +28,3 @@ fill: "forwards"

const pointers = ref({});
const fingers = computed(() => {
return Object.values(pointers.value).slice(0, 2);
});
const fingers = computed(() => Object.values(pointers.value).slice(0, 2));
const center = computed(() => getCenter("current"));

@@ -72,7 +76,12 @@ const distance = computed(() => getDistance("current"));

const finalTop = top - (center.value.y - top) * (rate2 - 1);
const finalWidth = startRect.width * rate2;
const finalHeight = startRect.height * rate2;
if (isOverLimit(finalWidth, finalHeight, rate2)) {
return;
}
rootEl.value.animate({
left: finalLeft + "px",
top: finalTop + "px",
width: startRect.width * rate2 + "px",
height: startRect.height * rate2 + "px"
width: finalWidth + "px",
height: finalHeight + "px"
}, {

@@ -102,24 +111,48 @@ duration: 0,

const finalTop = top - (event.clientY - top) * (rate2 - 1);
const finalWidth = width * rate2;
const finalHeight = height * rate2;
if (isOverLimit(finalWidth, finalHeight, rate2)) {
return;
}
rootEl.value.animate({
left: finalLeft + "px",
top: finalTop + "px",
width: width * rate2 + "px",
height: height * rate2 + "px"
width: finalWidth + "px",
height: finalHeight + "px"
}, options.value);
}
useEventListener("keydown", (event) => {
if (event.key === "Escape") {
emit("close");
function onDoubleClick(event) {
const { left, top, width, height } = rootEl.value.getBoundingClientRect();
const { size: [coverWidth, coverHeight], advantageSide } = getFitSize("cover");
if (width < coverWidth && height < coverHeight) {
const [finalLeft, finalTop] = advantageSide === "height" ? [
`calc(50% - ${Math.round(coverWidth / 2)}px)`,
`${top - (event.clientY - top) * (coverHeight / height - 1)}px`
] : [
`${left - (event.clientX - left) * (coverWidth / width - 1)}px`,
`calc(50% - ${Math.round(coverHeight / 2)}px)`
];
rootEl.value.animate({
left: finalLeft,
top: finalTop,
width: Math.ceil(coverWidth) + "px",
height: Math.ceil(coverHeight) + "px"
}, options.value);
} else {
const { size: [containWidth, containHeight] } = getFitSize("contain");
rootEl.value.animate({
left: `calc(50% - ${Math.round(containWidth / 2)}px)`,
top: `calc(50% - ${Math.round(containHeight / 2)}px)`,
width: Math.floor(containWidth) + "px",
height: Math.floor(containHeight) + "px"
}, options.value);
}
});
}
const onEnter = (el) => {
const fixedWidth = window.innerWidth * rate;
const fixedHeight = window.innerHeight * rate;
const naturalRatio = props.target.naturalWidth / props.target.naturalHeight;
const [finalWidth, finalHeight] = fixedWidth / fixedHeight > naturalRatio ? [fixedHeight * naturalRatio, fixedHeight] : [fixedWidth, fixedWidth / naturalRatio];
const { size: [containWidth, containHeight] } = getFitSize("contain");
el.animate([getOriginalKeyframe(), {
top: `calc(50% - ${Math.floor(finalHeight / 2)}px)`,
left: `calc(50% - ${Math.floor(finalWidth / 2)}px)`,
width: Math.floor(finalWidth) + "px",
height: Math.floor(finalHeight) + "px",
top: `calc(50% - ${Math.round(containHeight / 2)}px)`,
left: `calc(50% - ${Math.round(containWidth / 2)}px)`,
width: Math.floor(containWidth) + "px",
height: Math.floor(containHeight) + "px",
clipPath: "inset(0)"

@@ -138,6 +171,16 @@ }], options.value);

};
function getFitSize(mode) {
const fixedWidth = window.innerWidth * rate;
const fixedHeight = window.innerHeight * rate;
const naturalRatio = target.naturalWidth / target.naturalHeight;
const advantageSide = fixedWidth / fixedHeight > naturalRatio ? "height" : "width";
return {
size: +(advantageSide === "height") ^ +(mode === "cover") ? [fixedHeight * naturalRatio, fixedHeight] : [fixedWidth, fixedWidth / naturalRatio],
advantageSide
};
}
function getOriginalKeyframe(x = 0, y = 0) {
const { left, top, width, height } = props.target.getBoundingClientRect();
const { naturalWidth, naturalHeight } = props.target;
const { objectPosition } = getComputedStyle(props.target);
const { left, top, width, height } = target.getBoundingClientRect();
const { naturalWidth, naturalHeight } = target;
const { objectPosition } = getComputedStyle(target);
const [horizontal, vertical] = objectPosition.split(" ").map((pos) => Number(pos.slice(0, -1)) / 100);

@@ -167,2 +210,12 @@ const ratio = width / height;

}
function isOverLimit(width, height, rate2) {
if (!clamp) {
return false;
}
if (rate2 > 1) {
return width > Math.max(window.innerWidth, target.width, target.naturalWidth) && height > Math.max(window.innerHeight, target.height, target.naturalHeight);
} else {
return width < Math.min(window.innerWidth, target.width, target.naturalWidth) && height < Math.min(window.innerHeight, target.height, target.naturalHeight);
}
}
</script>

@@ -173,3 +226,3 @@

<img
v-if="isOpening"
v-if="open"
ref="root"

@@ -179,2 +232,3 @@ class="bikariya-image-viewer"

:draggable="false"
@dblclick="onDoubleClick"
@wheel.prevent="onWheel"

@@ -181,0 +235,0 @@ />

type __VLS_Props = {
/**
* 目标 `<img>` 元素
*/
target: HTMLImageElement;
/**
* 过渡动画时长 (ms)
* @default 400
*/
duration?: number;
isOpening?: boolean;
/**
* 放大后占窗口比率
* @default 0.9
*/
rate?: number;
/**
* 是否限制缩放比例
* @default false
*/
clamp?: boolean;
open?: boolean;
};

@@ -6,0 +23,0 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {

{
"name": "@bikariya/image-viewer",
"type": "module",
"version": "0.0.4",
"version": "0.0.5",
"description": "Bikariya image viewer for Nuxt",

@@ -6,0 +6,0 @@ "author": "KazariEX",