mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: image preview enhancement (#682)
This commit is contained in:
@ -1,16 +1,33 @@
|
||||
import { useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import * as utils from "../helpers/utils";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
import "../less/preview-image-dialog.less";
|
||||
|
||||
const MIN_SCALE = 0.5;
|
||||
const MAX_SCALE = 5;
|
||||
const SCALE_UNIT = 0.25;
|
||||
|
||||
interface Props extends DialogProps {
|
||||
imgUrls: string[];
|
||||
initialIndex: number;
|
||||
}
|
||||
|
||||
interface State {
|
||||
angle: number;
|
||||
scale: number;
|
||||
originX: number;
|
||||
originY: number;
|
||||
}
|
||||
|
||||
const PreviewImageDialog: React.FC<Props> = ({ destroy, imgUrls, initialIndex }: Props) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
||||
const [state, setState] = useState<State>({
|
||||
angle: 0,
|
||||
scale: 1,
|
||||
originX: -1,
|
||||
originY: -1,
|
||||
});
|
||||
|
||||
const handleCloseBtnClick = () => {
|
||||
destroy();
|
||||
@ -39,6 +56,38 @@ const PreviewImageDialog: React.FC<Props> = ({ destroy, imgUrls, initialIndex }:
|
||||
}
|
||||
};
|
||||
|
||||
const handleImgRotate = (event: React.MouseEvent, angle: number) => {
|
||||
const curImgAngle = (state.angle + angle + 360) % 360;
|
||||
setState({
|
||||
...state,
|
||||
originX: -1,
|
||||
originY: -1,
|
||||
angle: curImgAngle,
|
||||
});
|
||||
};
|
||||
|
||||
const handleImgContainerScroll = (event: React.WheelEvent) => {
|
||||
const offsetX = event.nativeEvent.offsetX;
|
||||
const offsetY = event.nativeEvent.offsetY;
|
||||
const sign = event.deltaY < 0 ? 1 : -1;
|
||||
const curAngle = Math.max(MIN_SCALE, Math.min(MAX_SCALE, state.scale + sign * SCALE_UNIT));
|
||||
setState({
|
||||
...state,
|
||||
originX: offsetX,
|
||||
originY: offsetY,
|
||||
scale: curAngle,
|
||||
});
|
||||
};
|
||||
|
||||
const getImageComputedStyle = () => {
|
||||
return {
|
||||
transform: `scale(${state.scale}) rotate(${state.angle}deg)`,
|
||||
transformOrigin: `${state.originX === -1 ? "center" : `${state.originX}px`} ${
|
||||
state.originY === -1 ? "center" : `${state.originY}px`
|
||||
}`,
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="btns-container">
|
||||
@ -48,9 +97,20 @@ const PreviewImageDialog: React.FC<Props> = ({ destroy, imgUrls, initialIndex }:
|
||||
<button className="btn" onClick={handleDownloadBtnClick}>
|
||||
<Icon.Download className="icon-img" />
|
||||
</button>
|
||||
<button className="btn" onClick={(e) => handleImgRotate(e, -90)}>
|
||||
<Icon.RotateCcw className="icon-img" />
|
||||
</button>
|
||||
<button className="btn" onClick={(e) => handleImgRotate(e, 90)}>
|
||||
<Icon.RotateCw className="icon-img" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="img-container" onClick={handleImgContainerClick}>
|
||||
<img onClick={(e) => e.stopPropagation()} src={imgUrls[currentIndex]} />
|
||||
<img
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
src={imgUrls[currentIndex]}
|
||||
onWheel={handleImgContainerScroll}
|
||||
style={getImageComputedStyle()}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
Reference in New Issue
Block a user