🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

react-image-zoom-in-place

Package Overview
Dependencies
Maintainers
0
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-image-zoom-in-place - npm Package Compare versions

Comparing version

to
0.0.6

222

lib/index.js

@@ -8,75 +8,35 @@ "use strict";

const utils_1 = require("./utils");
var InputMethod;
(function (InputMethod) {
InputMethod["Mouse"] = "Mouse";
InputMethod["Touch"] = "Touch";
})(InputMethod || (InputMethod = {}));
const INPUTMETHODLIFESPAN = 200; //ms
const RESOLUTIONTOZOOMMULTIPLIER = 100;
function ZoomableImage(props) {
const canvasRef = (0, react_1.useRef)(null);
const [image, setImage] = (0, react_1.useState)(null);
const [zoomPoint, setZoomPoint] = (0, react_1.useState)({
const [imageOffset, setImageOffset] = (0, react_1.useState)({
x: 0,
y: 0,
});
const [firstPoint, setFirstPoint] = (0, react_1.useState)({
x: 0,
y: 0,
});
const [secondPoint, setSecondPoint] = (0, react_1.useState)({
x: 0,
y: 0,
});
const [mouseLocation, setMouseLocation] = (0, react_1.useState)({
x: 0,
y: 0,
});
const [previousPinchDistance, setPreviousPinchDistance] = (0, react_1.useState)(0);
const [zoomLevel, setZoomLevel] = (0, react_1.useState)(1);
const [inputMethod, setInputMethod] = (0, react_1.useState)(null);
const [inputMethodTimestamp, setInputMethodTimestamp] = (0, react_1.useState)(0);
// Function to handle mouse move
const handleMouseMove = (event) => {
if (inputMethod != InputMethod.Mouse &&
inputMethod != null &&
Date.now() - inputMethodTimestamp < INPUTMETHODLIFESPAN) {
//touch screen state vars
const [previousPosition, setPerviousPosition] = (0, react_1.useState)(null);
const [previousDistance, setPreviousDistance] = (0, react_1.useState)(null);
if (image) {
(0, utils_1.renderAtPointAndZoom)(imageOffset.x, imageOffset.y, zoomLevel, canvasRef.current, image);
}
const updateLocation = (x, y, zoom) => {
const canvas = canvasRef.current;
if (!canvas)
return;
if (previousPosition) {
const zoomRatio = zoom / zoomLevel;
const deltaX = x - previousPosition.x;
const deltaY = y - previousPosition.y;
const newOffset = {
x: imageOffset.x - (x - imageOffset.x) * (zoomRatio - 1) + deltaX,
y: imageOffset.y - (y - imageOffset.y) * (zoomRatio - 1) + deltaY,
};
newOffset.x = Math.min(0, Math.max(newOffset.x, canvas.width - canvas.width * zoom));
newOffset.y = Math.min(0, Math.max(newOffset.y, canvas.height - canvas.height * zoom));
setImageOffset(newOffset);
}
const eventX = event.clientX;
const eventY = event.clientY;
setMouseLocation({
x: eventX,
y: eventY,
});
(0, utils_1.handleHover)(eventX, eventY, canvasRef.current, image, zoomLevel, props.width, props.height);
setPerviousPosition({ x: x, y: y });
setZoomLevel(zoom);
};
const handleMouseEnter = () => {
if (inputMethod != InputMethod.Mouse &&
inputMethod != null &&
Date.now() - inputMethodTimestamp < INPUTMETHODLIFESPAN) {
return;
}
setZoomLevel(props.zoom);
};
const handleMouseLeave = () => {
if (inputMethod != InputMethod.Mouse &&
inputMethod != null &&
Date.now() - inputMethodTimestamp < INPUTMETHODLIFESPAN) {
return;
}
(0, utils_1.resetZoom)(canvasRef.current, image, props.width, props.height);
setZoomLevel(props.zoom);
};
const handleMouseScroll = (event) => {
let newZoom = 1;
if (event.deltaY < 0) {
newZoom = Math.min(Math.max(1, zoomLevel + props.step), props.maxZoom);
}
else {
newZoom = Math.min(Math.max(1, zoomLevel - props.step), props.maxZoom);
}
setZoomLevel(newZoom);
(0, utils_1.handleHover)(mouseLocation.x, mouseLocation.y, canvasRef.current, image, newZoom, props.width, props.height);
};
(0, react_1.useEffect)(() => {

@@ -108,70 +68,94 @@ if (props.src == null) {

(0, react_1.useEffect)(() => {
if (!canvasRef.current)
return;
(0, utils_1.setCanvasDimensions)(canvasRef.current, image, props.width, props.height);
//image onload is not triggered for base64 images
if (image != null) {
(0, utils_1.resetZoom)(canvasRef.current, image, props.width, props.height);
setImageOffset({ x: 0, y: 0 });
setZoomLevel(1);
}
}, [image, props.width, props.height]);
const handleDragStart = (event) => {
if (event.touches.length === 1) {
setFirstPoint({
x: event.touches[0].clientX,
y: event.touches[0].clientY,
});
//mouse events
const handleMouseEnter = () => {
setZoomLevel(props.zoom);
};
// Function to handle mouse move
const handleMouseMove = (event) => {
const eventX = event.clientX;
const eventY = event.clientY;
const [x, y] = (0, utils_1.mouseLocationToImageOffset)(eventX, eventY, zoomLevel, canvasRef.current);
setImageOffset({
x: x,
y: y,
});
setPerviousPosition(null);
};
const handleMouseLeave = () => {
setImageOffset({
x: 0,
y: 0,
});
setZoomLevel(1);
setPerviousPosition(null);
};
const handleMouseScroll = (event) => {
let newZoom = 1;
if (event.deltaY < 0) {
newZoom = Math.min(Math.max(1, zoomLevel + props.step), props.maxZoom);
}
else if (event.touches.length === 2) {
setPreviousPinchDistance(Math.abs(event.touches[0].clientX - event.touches[1].clientX) +
Math.abs(event.touches[0].clientY - event.touches[1].clientY));
setSecondPoint({
x: event.touches[1].clientX,
y: event.touches[1].clientY,
});
else {
newZoom = Math.min(Math.max(1, zoomLevel - props.step), props.maxZoom);
}
const [x, y] = (0, utils_1.mouseLocationToImageOffset)(event.clientX, event.clientY, newZoom, canvasRef.current);
setImageOffset({
x: x,
y: y,
});
setZoomLevel(newZoom);
setPerviousPosition(null);
};
//touch screen events
const handleSingleTouchMove = (e) => {
if (!canvasRef.current || e.touches.length !== 1)
return;
const touch = e.touches[0];
const rect = canvasRef.current.getBoundingClientRect();
const x = Math.min(400, Math.max(0, touch.clientX - rect.left));
const y = Math.min(400, Math.max(0, touch.clientY - rect.top));
updateLocation(x, y, zoomLevel);
};
const handlePinchZoomMove = (e) => {
if (!canvasRef.current || e.touches.length !== 2)
return;
const touch1 = e.touches[0];
const touch2 = e.touches[1];
const currentDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY);
const midpointX = (touch1.clientX + touch2.clientX) / 2;
const midpointY = (touch1.clientY + touch2.clientY) / 2;
const rect = canvasRef.current.getBoundingClientRect();
const x = Math.min(400, Math.max(0, midpointX - rect.left));
const y = Math.min(400, Math.max(0, midpointY - rect.top));
let newZoomLevel = zoomLevel;
if (previousDistance) {
newZoomLevel =
zoomLevel +
(currentDistance - previousDistance) /
Math.max(rect.width, rect.height);
newZoomLevel = Math.max(1, Math.min(props.maxZoom, newZoomLevel));
}
updateLocation(x, y, newZoomLevel);
setPreviousDistance(currentDistance);
};
const handleDragMove = (event) => {
event.preventDefault();
if (event.touches.length >= 1) {
const canvas = canvasRef.current;
if (!canvas)
return;
const rect = canvas.getBoundingClientRect();
const changeX = firstPoint.x - event.touches[0].clientX;
let newX = zoomPoint.x + changeX / props.zoom;
newX = Math.max(0, Math.min(newX, rect.width));
const changeY = firstPoint.y - event.touches[0].clientY;
let newY = zoomPoint.y + changeY / props.zoom;
newY = Math.max(0, Math.min(newY, rect.height));
setZoomPoint({
x: newX,
y: newY,
});
setFirstPoint({
x: event.touches[0].clientX,
y: event.touches[0].clientY,
});
setInputMethod(InputMethod.Touch);
setInputMethodTimestamp(Date.now());
(0, utils_1.handleHover)(newX, newY, canvasRef.current, image, zoomLevel, props.width, props.height); //props.zoom
}
if (event.touches.length >= 2) {
const dist = Math.abs(firstPoint.x - event.touches[1].clientX) +
Math.abs(firstPoint.y - event.touches[1].clientY);
const newZoom = zoomLevel + (dist - previousPinchDistance) / RESOLUTIONTOZOOMMULTIPLIER;
setPreviousPinchDistance(dist);
setSecondPoint({
x: event.touches[1].clientX,
y: event.touches[1].clientY,
});
if (newZoom > 1 && newZoom < props.maxZoom) {
setZoomLevel(newZoom);
(0, utils_1.handleHover)(zoomPoint.x, zoomPoint.y, canvasRef.current, image, newZoom, props.width, props.height);
}
}
if (event.touches.length === 1)
handleSingleTouchMove(event);
if (event.touches.length === 2)
handlePinchZoomMove(event);
};
const handleDragEnd = (event) => {
setFirstPoint(secondPoint);
setInputMethod(InputMethod.Touch);
setInputMethodTimestamp(Date.now());
const resetDrag = (event) => {
setPerviousPosition(null);
setPreviousDistance(null);
};
return ((0, jsx_runtime_1.jsx)("div", { style: { height: "100%", width: "100%" }, children: (0, jsx_runtime_1.jsx)("a", { children: (0, jsx_runtime_1.jsx)("canvas", { style: { touchAction: "none" }, ref: canvasRef, width: props.width ? props.width : 1, height: props.height ? props.height : 1, onWheel: handleMouseScroll, onMouseEnter: handleMouseEnter, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, onTouchStart: handleDragStart, onTouchMove: handleDragMove, onTouchEnd: handleDragEnd, "aria-label": props.alt ? props.alt : "" }) }) }));
return ((0, jsx_runtime_1.jsx)("div", { style: { height: "100%", width: "100%" }, children: (0, jsx_runtime_1.jsx)("canvas", { style: { touchAction: "none" }, ref: canvasRef, width: props.width ? props.width : 1, height: props.height ? props.height : 1, onTouchStart: resetDrag, onTouchMove: handleDragMove, onTouchEnd: resetDrag, onMouseEnter: handleMouseEnter, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, onWheel: handleMouseScroll, "aria-label": props.alt ? props.alt : "" }) }));
}
export declare const setCanvasDimensions: (canvas: HTMLCanvasElement | null, image: HTMLImageElement | null, w?: number, h?: number) => void;
export declare const handleHover: (eventX: number, eventY: number, canvas: HTMLCanvasElement | null, image: HTMLImageElement | null, zoom: number, w?: number, h?: number) => void;
export declare const resetZoom: (canvas: HTMLCanvasElement | null, image: HTMLImageElement | null, w?: number, h?: number) => void;
export declare const renderAtPointAndZoom: (x: number, y: number, zoom: number, canvas: HTMLCanvasElement | null, image: HTMLImageElement | null) => void;
export declare function mouseLocationToImageOffset(eventX: number, eventY: number, zoom: number, canvas: HTMLCanvasElement | null): [number, number];
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resetZoom = exports.handleHover = exports.setCanvasDimensions = void 0;
exports.renderAtPointAndZoom = exports.setCanvasDimensions = void 0;
exports.mouseLocationToImageOffset = mouseLocationToImageOffset;
const setCanvasDimensions = (canvas, image, w, h) => {

@@ -27,3 +28,3 @@ if (!canvas)

exports.setCanvasDimensions = setCanvasDimensions;
const handleHover = (eventX, eventY, canvas, image, zoom, w, h) => {
const renderAtPointAndZoom = (x, y, zoom, canvas, image) => {
if (!canvas)

@@ -35,26 +36,17 @@ return;

if (image != null) {
// Get the canvas bounding rectangle for accurate calculations
const rect = canvas.getBoundingClientRect();
// Calculate mouse X and Y relative to the canvas
const mouseX = eventX - rect.left;
const mouseY = eventY - rect.top;
const x = -(mouseX / rect.width) * (zoom * rect.width - rect.width);
const y = -(mouseY / rect.height) * (zoom * rect.height - rect.height);
ctx.clearRect(0, 0, rect.width, rect.height);
ctx.drawImage(image, x, y, rect.width * zoom, rect.height * zoom);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(image, x, y, canvas.width * zoom, canvas.height * zoom);
}
};
exports.handleHover = handleHover;
const resetZoom = (canvas, image, w, h) => {
exports.renderAtPointAndZoom = renderAtPointAndZoom;
function mouseLocationToImageOffset(eventX, eventY, zoom, canvas) {
if (!canvas)
return;
const ctx = canvas.getContext("2d");
if (!ctx)
return;
if (image != null) {
const rect = canvas.getBoundingClientRect();
ctx.clearRect(0, 0, rect.width, rect.height);
ctx.drawImage(image, 0, 0, rect.width, rect.height);
}
};
exports.resetZoom = resetZoom;
return [0, 0];
const rect = canvas.getBoundingClientRect();
// Calculate mouse X and Y relative to the canvas
const mouseX = eventX - rect.left;
const mouseY = eventY - rect.top;
const x = -(mouseX / rect.width) * (zoom * rect.width - rect.width);
const y = -(mouseY / rect.height) * (zoom * rect.height - rect.height);
return [x, y];
}
{
"name": "react-image-zoom-in-place",
"version": "0.0.5",
"version": "0.0.6",
"description": "",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -9,3 +9,4 @@ # react-image-zoom-in-place

* Fix some glitches in the pinch zoom and dragging.
* Code cleanup
* Tests to ensure functioning in edge cases

@@ -12,0 +13,0 @@ ## Behavior