Camera thumb zoom

pull/1658/head
Piero Toffanin 2025-04-21 18:11:35 -04:00
rodzic 7b0c4d49f4
commit 16c7b0e2de
2 zmienionych plików z 58 dodań i 8 usunięć

Wyświetl plik

@ -17,6 +17,10 @@ class ImagePopup extends React.Component {
error: "",
loading: true,
expandThumb: false,
translateX: 0,
translateY: 0,
scale: 1
}
}
@ -30,11 +34,17 @@ class ImagePopup extends React.Component {
}
componentDidMount(){
if (this.image) this.image.addEventListener("fullscreenchange", this.onFullscreenChange);
if (this.image){
this.image.addEventListener("fullscreenchange", this.onFullscreenChange);
this.image.addEventListener("mousewheel", this.onMouseWheel);
}
}
componentWillUnmount(){
if (this.image) this.image.removeEventListener("fullscreenchange", this.onFullscreenChange);
if (this.image){
this.image.removeEventListener("fullscreenchange", this.onFullscreenChange);
this.image.removeEventListener("mousewheel", this.onMouseWheel);
}
}
onFullscreenChange = (e) => {
@ -51,20 +61,55 @@ class ImagePopup extends React.Component {
this.setState({loading: false});
}
onMouseWheel = e => {
if (!this.image || !this.state.expandThumb) return;
let { translateX, translateY, scale } = this.state;
const maxScale = 60;
const rect = this.image.querySelector("img").getBoundingClientRect();
const mouseX = e.clientX;
const mouseY = e.clientY;
const delta = -e.deltaY || e.wheelDelta || -e.detail;
const zoomFactor = 1.2;
const newScale = Math.max(1, delta > 0 ? scale * zoomFactor : scale / zoomFactor);
if (newScale > maxScale) return;
const imgX = (mouseX - rect.left) / scale;
const imgY = (mouseY - rect.top) / scale;
translateX -= imgX * (newScale - scale);
translateY -= imgY * (newScale - scale);
scale = newScale;
if (scale == 1){
translateX = 0;
translateY = 0;
}
this.setState({ translateX, translateY, scale });
}
onImgClick = () => {
const { expandThumb } = this.state;
if (!expandThumb){
this.image.requestFullscreen();
this.setState({ loading: true, expandThumb: true});
this.setState({ loading: true, expandThumb: true, translateX: 0, translateY: 0, scale: 1});
}else{
document.exitFullscreen();
this.setState({ expandThumb: false });
this.setState({ expandThumb: false, translateX: 0, translateY: 0, scale: 1 });
this.image
}
}
render(){
const { error, loading, expandThumb } = this.state;
const { error, loading, expandThumb, translateX, translateY, scale } = this.state;
const { feature, task } = this.props;
const downloadImageLink = `/api/projects/${task.project}/tasks/${task.id}/images/download/${feature.properties.filename}`;
@ -78,9 +123,11 @@ class ImagePopup extends React.Component {
: ""}
{error !== "" ? <div style={{marginTop: "8px"}}>{error}</div>
: [
<div key="image" className={`image ${expandThumb ? "fullscreen" : ""}`} style={{marginTop: "8px"}} ref={(domNode) => { this.image = domNode;}}>
<div key="image" className={`image ${expandThumb ? "fullscreen" : ""}`}
style={{marginTop: "8px"}}
ref={(domNode) => { this.image = domNode;}}>
{loading && expandThumb ? <div><i className="fa fa-circle-notch fa-spin fa-fw"></i></div> : ""}
<a onClick={this.onImgClick} href="javascript:void(0);" title={feature.properties.filename}><img style={{borderRadius: "4px"}} src={imageUrl} onLoad={this.imageOnLoad} onError={this.imageOnError} /></a>
<a onClick={this.onImgClick} href="javascript:void(0);" title={feature.properties.filename}><img style={{borderRadius: "4px", transform: `translate(${translateX}px, ${translateY}px) scale(${scale})`}} src={imageUrl} onLoad={this.imageOnLoad} onError={this.imageOnError} /></a>
</div>,
<div key="download-image">
<a href={downloadImageLink}><i className="fa fa-image"></i> {_("Download Image")}</a>

Wyświetl plik

@ -13,6 +13,7 @@
}
div.image{
overflow: hidden;
a{
cursor: zoom-in;
}
@ -28,11 +29,13 @@
top: 45%;
}
a{
cursor: zoom-out;
cursor: zoom-in;
}
img{
image-rendering: pixelated;
max-width: 100%;
max-height: 100%;
transform-origin: 0 0;
}
}
}