kopia lustrzana https://github.com/OpenDroneMap/WebODM
Camera thumb zoom
rodzic
7b0c4d49f4
commit
16c7b0e2de
|
@ -17,6 +17,10 @@ class ImagePopup extends React.Component {
|
||||||
error: "",
|
error: "",
|
||||||
loading: true,
|
loading: true,
|
||||||
expandThumb: false,
|
expandThumb: false,
|
||||||
|
|
||||||
|
translateX: 0,
|
||||||
|
translateY: 0,
|
||||||
|
scale: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +34,17 @@ class ImagePopup extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(){
|
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(){
|
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) => {
|
onFullscreenChange = (e) => {
|
||||||
|
@ -51,20 +61,55 @@ class ImagePopup extends React.Component {
|
||||||
this.setState({loading: false});
|
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 = () => {
|
onImgClick = () => {
|
||||||
const { expandThumb } = this.state;
|
const { expandThumb } = this.state;
|
||||||
|
|
||||||
if (!expandThumb){
|
if (!expandThumb){
|
||||||
this.image.requestFullscreen();
|
this.image.requestFullscreen();
|
||||||
this.setState({ loading: true, expandThumb: true});
|
this.setState({ loading: true, expandThumb: true, translateX: 0, translateY: 0, scale: 1});
|
||||||
}else{
|
}else{
|
||||||
document.exitFullscreen();
|
document.exitFullscreen();
|
||||||
this.setState({ expandThumb: false });
|
this.setState({ expandThumb: false, translateX: 0, translateY: 0, scale: 1 });
|
||||||
|
this.image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
const { error, loading, expandThumb } = this.state;
|
const { error, loading, expandThumb, translateX, translateY, scale } = this.state;
|
||||||
const { feature, task } = this.props;
|
const { feature, task } = this.props;
|
||||||
|
|
||||||
const downloadImageLink = `/api/projects/${task.project}/tasks/${task.id}/images/download/${feature.properties.filename}`;
|
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>
|
{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> : ""}
|
{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>,
|
||||||
<div key="download-image">
|
<div key="download-image">
|
||||||
<a href={downloadImageLink}><i className="fa fa-image"></i> {_("Download Image")}</a>
|
<a href={downloadImageLink}><i className="fa fa-image"></i> {_("Download Image")}</a>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
div.image{
|
div.image{
|
||||||
|
overflow: hidden;
|
||||||
a{
|
a{
|
||||||
cursor: zoom-in;
|
cursor: zoom-in;
|
||||||
}
|
}
|
||||||
|
@ -28,11 +29,13 @@
|
||||||
top: 45%;
|
top: 45%;
|
||||||
}
|
}
|
||||||
a{
|
a{
|
||||||
cursor: zoom-out;
|
cursor: zoom-in;
|
||||||
}
|
}
|
||||||
img{
|
img{
|
||||||
|
image-rendering: pixelated;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
transform-origin: 0 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue