terriajs
Version:
Geospatial data visualization platform.
174 lines (154 loc) • 5.47 kB
JSX
import createReactClass from "create-react-class";
import PropTypes from "prop-types";
import React from "react";
import defined from "terriajs-cesium/Source/Core/defined";
import Ellipsoid from "terriajs-cesium/Source/Core/Ellipsoid";
import Rectangle from "terriajs-cesium/Source/Core/Rectangle";
import MapInteractionMode from "../../../Models/MapInteractionMode";
import Loader from "../../Loader";
import LocationItem from "../../LocationItem.jsx";
import { withTranslation } from "react-i18next";
import { observer } from "mobx-react";
import { runInAction, reaction } from "mobx";
import Styles from "./satellite-imagery-time-filter-section.scss";
const SatelliteImageryTimeFilterSection = observer(
createReactClass({
displayName: "SatelliteImageryTimeFilterSection",
propTypes: {
item: PropTypes.object,
t: PropTypes.func.isRequired
},
removeFilter() {
this.props.item.removeTimeFilterFeature();
},
zoomTo() {
const feature = this.props.item.timeFilterFeature;
const position =
feature !== undefined && feature.position !== undefined
? feature.position.getValue(this.props.item.currentTime)
: undefined;
if (defined(position)) {
const cartographic = Ellipsoid.WGS84.cartesianToCartographic(position);
this.props.item.terria.currentViewer.zoomTo(
new Rectangle(
cartographic.longitude - 0.0005,
cartographic.latitude - 0.0005,
cartographic.longitude + 0.0005,
cartographic.latitude + 0.0005
)
);
}
},
newLocation() {
const { t } = this.props;
// Cancel any feature picking already in progress.
const terria = this.props.item.terria;
const pickPointMode = new MapInteractionMode({
message: t("satellite.pickPoint"),
onCancel: () => runInAction(() => terria.mapInteractionModeStack.pop())
});
runInAction(() => terria.mapInteractionModeStack.push(pickPointMode));
// Set up a reaction to observe pickedFeatures and filter the items
// discrete times
const disposer = reaction(
() => pickPointMode.pickedFeatures,
async (pickedFeatures) => {
runInAction(() => {
pickPointMode.customUi = function () {
return <Loader message={t("satellite.querying")} />;
};
});
await pickedFeatures.allFeaturesAvailablePromise;
if (
terria.mapInteractionModeStack[
terria.mapInteractionModeStack.length - 1
] !== pickPointMode
) {
// already cancelled
disposer();
return;
}
const item = this.props.item;
const thisLayerFeature = pickedFeatures.features.filter((feature) => {
return (
item.mapItems.find(
(mapItem) =>
mapItem.imageryProvider &&
mapItem.imageryProvider ===
feature.imageryLayer?.imageryProvider
) !== undefined
);
})[0];
if (thisLayerFeature !== undefined) {
try {
item.setTimeFilterFeature(
thisLayerFeature,
pickedFeatures.providerCoords
);
} catch (e) {
terria.raiseErrorToUser(e);
}
}
runInAction(() => terria.mapInteractionModeStack.pop());
disposer();
}
);
},
render() {
if (!this.props.item.canFilterTimeByFeature) {
return null;
}
const feature = this.props.item.timeFilterFeature;
if (feature === undefined) {
return this.renderNoFeatureSelected();
} else {
return this.renderFeatureSelected(feature);
}
},
renderNoFeatureSelected() {
const { t } = this.props;
return (
<div className={Styles.inactive}>
<div className={Styles.btnGroup}>
<button className={Styles.btn} onClick={this.newLocation}>
{t("satellite.filterByLocation")}
</button>
</div>
</div>
);
},
renderFeatureSelected(feature) {
const { t } = this.props;
// TODO: if the feature itself doesn't have a position, we should be able to use the position the user clicked on.
const position =
feature.position !== undefined
? feature.position.getValue(this.props.item.currentTime)
: undefined;
return (
<div
className={Styles.active}
css={`
background: ${(p) => p.theme.colorPrimary};
`}
>
<div className={Styles.infoGroup}>
<div>{t("satellite.infoGroup")}</div>
<LocationItem position={position} />
</div>
<div className={Styles.btnGroup}>
<button className={Styles.btn} onClick={this.removeFilter}>
{t("satellite.removeFilter")}
</button>
<button className={Styles.btn} onClick={this.zoomTo}>
{t("satellite.zoomTo")}
</button>
<button className={Styles.btn} onClick={this.newLocation}>
{t("satellite.newLocation")}
</button>
</div>
</div>
);
}
})
);
export default withTranslation()(SatelliteImageryTimeFilterSection);