kopia lustrzana https://github.com/OpenDroneMap/WebODM
SwitchModeButton for changing 2D <--> 3D views
rodzic
17c3b937bb
commit
1214c069d3
|
@ -156,8 +156,18 @@ button i.glyphicon{
|
|||
background-color: #dddddd;
|
||||
}
|
||||
|
||||
.btn.btn-white{
|
||||
background-color: #fff;
|
||||
color: #111;
|
||||
|
||||
&:hover{
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu>li>a{
|
||||
padding-left: 10px;
|
||||
color: #222;
|
||||
.fa, .glyphicon{
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import React from 'react';
|
||||
import './css/ModelView.scss';
|
||||
import ErrorMessage from './components/ErrorMessage';
|
||||
import SwitchModeButton from './components/SwitchModeButton';
|
||||
import AssetDownloadButtons from './components/AssetDownloadButtons';
|
||||
import Standby from './components/Standby';
|
||||
import $ from 'jquery';
|
||||
|
||||
|
@ -1053,7 +1055,11 @@ class ModelView extends React.Component {
|
|||
message="Loading textured model..."
|
||||
ref={(domNode) => { this.texturedModelStandby = domNode; }}
|
||||
/>
|
||||
<SwitchModeButton
|
||||
task={this.props.task}
|
||||
type="modelToMap" />
|
||||
</div>
|
||||
<AssetDownloadButtons task={this.props.task} direction="up" />
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import React from 'react';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
import ReactDOM from 'react-dom';
|
||||
import '../css/Map.scss';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import Leaflet from 'leaflet';
|
||||
|
@ -11,6 +13,7 @@ import '../vendor/leaflet/Leaflet.Autolayers/css/leaflet.auto-layers.css';
|
|||
import '../vendor/leaflet/Leaflet.Autolayers/leaflet-autolayers';
|
||||
import $ from 'jquery';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import SwitchModeButton from './SwitchModeButton';
|
||||
import AssetDownloads from '../classes/AssetDownloads';
|
||||
|
||||
class Map extends React.Component {
|
||||
|
@ -33,7 +36,8 @@ class Map extends React.Component {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
error: ""
|
||||
error: "",
|
||||
switchButtonTask: null // When this is set to a task, show a switch mode button to view the 3d model
|
||||
};
|
||||
|
||||
this.imageryLayers = [];
|
||||
|
@ -99,11 +103,26 @@ class Map extends React.Component {
|
|||
tms: info.scheme === 'tms'
|
||||
}).addTo(this.map);
|
||||
|
||||
// Associate metadata with this layer
|
||||
meta.name = info.name;
|
||||
layer[Symbol.for("meta")] = meta;
|
||||
|
||||
// Show 3D switch button only if we have a single orthophoto
|
||||
const task = {
|
||||
id: meta.task,
|
||||
project: meta.project
|
||||
};
|
||||
|
||||
if (tiles.length === 1){
|
||||
this.setState({switchButtonTask: task});
|
||||
}
|
||||
|
||||
// For some reason, getLatLng is not defined for tileLayer?
|
||||
// We need this function if other code calls layer.openPopup()
|
||||
layer.getLatLng = function(){
|
||||
return this.options.bounds.getCenter();
|
||||
};
|
||||
|
||||
layer.bindPopup(`<div class="title">${info.name}</div>
|
||||
<div>Bounds: [${layer.options.bounds.toBBoxString().split(",").join(", ")}]</div>
|
||||
<ul class="asset-links">
|
||||
|
@ -111,11 +130,15 @@ class Map extends React.Component {
|
|||
return `<li><a href="${asset.downloadUrl(meta.project, meta.task)}">${asset.label}</a></li>`;
|
||||
}).join("")}
|
||||
</ul>
|
||||
`);
|
||||
|
||||
// Associate metadata with this layer
|
||||
meta.name = info.name;
|
||||
layer[Symbol.for("meta")] = meta;
|
||||
<button
|
||||
onclick="location.href='/3d/project/${task.project}/task/${task.id}/';"
|
||||
type="button"
|
||||
class="switchModeButton btn btn-sm btn-default btn-white">
|
||||
<i class="fa fa-cube"></i> 3D
|
||||
</button>
|
||||
`);
|
||||
|
||||
|
||||
this.imageryLayers.push(layer);
|
||||
|
||||
|
@ -180,8 +203,11 @@ class Map extends React.Component {
|
|||
<ErrorMessage bind={[this, 'error']} />
|
||||
<div
|
||||
style={{height: "100%"}}
|
||||
ref={(domNode) => (this.container = domNode)}
|
||||
/>
|
||||
ref={(domNode) => (this.container = domNode)}>
|
||||
<SwitchModeButton
|
||||
task={this.state.switchButtonTask}
|
||||
type="mapToModel" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -302,12 +302,6 @@ class ProjectListItem extends React.Component {
|
|||
<button type="button" className="btn btn-default btn-sm" onClick={this.viewMap}>
|
||||
<i className="fa fa-globe"></i> View Map
|
||||
</button>
|
||||
<button type="button" className="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||
<span className="caret"></span>
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
<li><a href="javascript:alert('TODO!');"><i className="fa fa-cube"></i> 3D View</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<span className="project-name">
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import React from 'react';
|
||||
import '../css/SwitchModeButton.scss';
|
||||
|
||||
class SwitchModeButton extends React.Component {
|
||||
static defaultProps = {
|
||||
task: null,
|
||||
type: "mapToModel"
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
task: React.PropTypes.object, // The object should contain two keys: {id: <taskId>, project: <projectId>}
|
||||
type: React.PropTypes.string // Either "mapToModel" or "modelToMap"
|
||||
};
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.icon = this.icon.bind(this);
|
||||
this.text = this.text.bind(this);
|
||||
|
||||
}
|
||||
|
||||
handleClick(){
|
||||
if (this.props.task){
|
||||
const prefix = this.props.type === 'mapToModel' ? '3d' : 'map';
|
||||
location.href = `/${prefix}/project/${this.props.task.project}/task/${this.props.task.id}/`;
|
||||
}
|
||||
}
|
||||
|
||||
icon(){
|
||||
return this.props.type === 'mapToModel' ? 'fa-cube' : 'fa-globe';
|
||||
}
|
||||
|
||||
text(){
|
||||
return this.props.type === 'mapToModel' ? '3D' : '2D';
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<button
|
||||
onClick={this.handleClick}
|
||||
type="button"
|
||||
className={"switchModeButton btn btn-sm btn-default btn-white " + (!this.props.task ? "hide" : "")}>
|
||||
<i className={"fa " + (this.icon())}></i> {this.text()}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SwitchModeButton;
|
|
@ -192,6 +192,9 @@ class TaskListItem extends React.Component {
|
|||
addActionButton(" View Orthophoto", "btn-primary", "fa fa-globe", () => {
|
||||
location.href = `/map/project/${task.project}/task/${task.id}/`;
|
||||
});
|
||||
addActionButton(" View 3D Assets", "btn-primary", "fa fa-cube", () => {
|
||||
location.href = `/3d/project/${task.project}/task/${task.id}/`;
|
||||
});
|
||||
}
|
||||
|
||||
if ([statusCodes.QUEUED, statusCodes.RUNNING, null].indexOf(task.status) !== -1 &&
|
||||
|
|
|
@ -9,5 +9,12 @@
|
|||
margin-top: 8px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.switchModeButton{
|
||||
bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-control-measure.leaflet-control{
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
|
@ -27,4 +27,33 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.switchModeButton{
|
||||
bottom: 12px;
|
||||
}
|
||||
.asset-download-buttons{
|
||||
position: relative;
|
||||
top: -48px;
|
||||
left: 12px;
|
||||
|
||||
&.open{
|
||||
.dropdown-toggle{
|
||||
background-color: #f4f4f4;
|
||||
color: #111;
|
||||
}
|
||||
button{
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
button{
|
||||
background-color: #fff;
|
||||
color: #111;
|
||||
border-width: 1px;
|
||||
|
||||
&:hover{
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.switchModeButton{
|
||||
border-width: 1px;
|
||||
position: absolute;
|
||||
z-index: 2000;
|
||||
bottom: 24px;
|
||||
right: 12px;
|
||||
}
|
Ładowanie…
Reference in New Issue