Skip to content

Commit

Permalink
feat(globe): show single tile images on globes (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
pwambach authored Oct 23, 2019
1 parent 11c4f82 commit 9a5140a
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 1 deletion.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@
"sort-imports": 0,
"template-curly-spacing": [2, "never"],
"yield-star-spacing": 1,
"@typescript-eslint/no-use-before-define": [2, "nofunc"],
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/ban-ts-ignore": 0,
Expand Down
27 changes: 27 additions & 0 deletions src/scripts/components/globe/globe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ interface Props {
active: boolean;
view: GlobeView;
projection: GlobeProjection;
imageUrl: string | null;
onMouseEnter: () => void;
onChange: (view: GlobeView) => void;
onMoveEnd: (view: GlobeView) => void;
Expand All @@ -48,6 +49,7 @@ interface Props {
const Globe: FunctionComponent<Props> = ({
view,
projection,
imageUrl,
active,
onMouseEnter,
onChange,
Expand Down Expand Up @@ -129,6 +131,31 @@ const Globe: FunctionComponent<Props> = ({
setGlobeView(viewer, view);
}, [viewer, view, active]);

// update layer image when url changes
useEffect(() => {
if (!viewer) {
return;
}

const url = imageUrl;
const layers = viewer.scene.imageryLayers;
const oldLayer = layers.length > 1 && layers.get(1);

if (url) {
const imageProvider = new Cesium.SingleTileImageryProvider({url});
imageProvider.readyPromise.then(() => {
viewer.scene.imageryLayers.addImageryProvider(imageProvider);
// remove and destroy old layer if exists
// we do not clean it up in the useEffect clean function because we want
// to wait until the new layer is ready to prevent flickering
oldLayer && setTimeout(() => layers.remove(oldLayer, true), 100);
});
} else if (oldLayer) {
// remove old layer when no image should be shown anymore
layers.remove(oldLayer, true);
}
}, [viewer, imageUrl]);

return (
<div
className={styles.globe}
Expand Down
18 changes: 18 additions & 0 deletions src/scripts/components/globes/globes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import React, {
import {useSelector, useDispatch} from 'react-redux';

import {selectedLayersSelector} from '../../reducers/layers/selected';
import {detailedLayersSelector} from '../../reducers/layers/details';
import {globeViewSelector} from '../../reducers/globe/view';
import {timeSelector} from '../../reducers/globe/time';
import {projectionSelector} from '../../reducers/globe/projection';
import setGlobeViewAction from '../../actions/set-globe-view';
import Globe from '../globe/globe';
import {getLayerTileUrl} from '../../libs/get-layer-tile-url';

import {GlobeView} from '../../types/globe-view';

Expand All @@ -20,6 +23,8 @@ const Globes: FunctionComponent = () => {
const dispatch = useDispatch();
const projection = useSelector(projectionSelector);
const globalGlobeView = useSelector(globeViewSelector);
const detailedLayers = useSelector(detailedLayersSelector);
const time = useSelector(timeSelector);
const [currentView, setCurrentView] = useState(globalGlobeView);
const [isMainActive, setIsMainActive] = useState(true);
const selectedLayers = useSelector(selectedLayersSelector);
Expand All @@ -32,6 +37,17 @@ const Globes: FunctionComponent = () => {
[dispatch]
);

const mainImageUrl = getLayerTileUrl(
selectedLayers.main,
detailedLayers,
time
);
const compareImageUrl = getLayerTileUrl(
selectedLayers.compare,
detailedLayers,
time
);

// apply changes in the app state view to our local view copy
// we don't use the app state view all the time to keep store updates low
useEffect(() => {
Expand All @@ -44,6 +60,7 @@ const Globes: FunctionComponent = () => {
active={isMainActive}
view={currentView}
projection={projection}
imageUrl={mainImageUrl}
onMouseEnter={() => setIsMainActive(true)}
onChange={onChangeHandler}
onMoveEnd={onMoveEndHandler}
Expand All @@ -54,6 +71,7 @@ const Globes: FunctionComponent = () => {
active={!isMainActive}
view={currentView}
projection={projection}
imageUrl={compareImageUrl}
onMouseEnter={() => setIsMainActive(false)}
onChange={onChangeHandler}
onMoveEnd={onMoveEndHandler}
Expand Down
2 changes: 2 additions & 0 deletions src/scripts/config/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export default {
'https://storage.googleapis.com/esa-cfs-storage/layers/layers-{lang}.json',
layer:
'https://storage.googleapis.com/esa-cfs-storage/layers/{id}/metadata.json',
layerTiles:
'https://storage.googleapis.com/esa-cfs-tiles/test/{id}/{name}.jpg',
stories:
'https://storage.googleapis.com/esa-cfs-storage/stories/stories-{lang}.json',
story:
Expand Down
53 changes: 53 additions & 0 deletions src/scripts/libs/get-layer-tile-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import config from '../config/main';
import {replaceUrlPlaceholders} from '../libs/replace-url-placeholders';

import {DetailsById} from '../reducers/layers/details';

/**
* Returns the current layer tile url based on the time and the
* layer's availbale timestmaps
*/
export function getLayerTileUrl(
id: string | null,
detailedLayers: DetailsById,
time: number
): string | null {
if (!id) {
return null;
}

const layer = detailedLayers[id];

if (!layer) {
return null;
}

const layerTime = getLayerTime(time, layer.timestamps);
const date = new Date(layerTime);
const name = date
.toISOString()
.substr(0, 10)
.replace(/-/g, '');

return replaceUrlPlaceholders(config.api.layerTiles, {id, name});
}

/**
* Returns the best matching time of all layer timestamps
* based on the current global time
*/
function getLayerTime(sliderTime: number, timestamps: string[]): number {
const lastTimestamp = timestamps[timestamps.length - 1];
let time = Number(new Date(lastTimestamp));

for (let i = timestamps.length - 1; i > 0; i--) {
const layerTime = Number(new Date(timestamps[i]));

if (sliderTime > layerTime) {
time = layerTime;
break;
}
}

return time;
}
2 changes: 1 addition & 1 deletion src/scripts/reducers/layers/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import {State} from '../index';
import {Layer} from '../../types/layer';

type DetailsById = {[id: string]: Layer};
export type DetailsById = {[id: string]: Layer};

function detailsReducer(
state: DetailsById = {},
Expand Down

0 comments on commit 9a5140a

Please sign in to comment.