Skip to content

Commit

Permalink
feat: allow to control from outside control
Browse files Browse the repository at this point in the history
  • Loading branch information
Kanahiro committed Dec 29, 2024
1 parent bb741a9 commit 0e736ff
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 52 deletions.
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

## examples

- RasterTiles: https://mug-jp.github.io/maplibre-gl-temporal-control/raster.html
- VectorTiles: https://mug-jp.github.io/maplibre-gl-temporal-control/vector.html
- RasterTiles: <https://mug-jp.github.io/maplibre-gl-temporal-control/raster.html>
- VectorTiles: <https://mug-jp.github.io/maplibre-gl-temporal-control/vector.html>

## usage

Expand Down Expand Up @@ -49,11 +49,18 @@ const temporalControl = new TemporalControl(temporalFrames, {
performance: true // set when rendering is too slow, but frames which are not current are shown mostly transparent
});
map.addControl(temporalControl);

// you can control programatically
temporalControl.prev()
temporalControl.next()
temporalControl.play()
temporalControl.pause()
temporalControl.setLoopEnabled(true)
```

### Tips

- In frames, You must set layer-objects corresponding to in map.
- Layers set in frames must be added in map
- when `performance: true`, not-current frames are shown as opacity=0.000000000000000000001
- this option may not be neccesary for ordinary usecases
- In frames, You must set layer-objects corresponding to in map.
- Layers set in frames must be added in map
- when `performance: true`, not-current frames are shown as opacity=0.000000000000000000001
- this option may not be neccesary for ordinary usecases
11 changes: 9 additions & 2 deletions example/raster.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,23 @@
</head>
<body style="margin: 0">
<a
class="github-fork-ribbon left-top"
class="github-fork-ribbon right-top"
href="https://github.com/mug-jp/maplibre-gl-temporal-control"
data-ribbon="Fork me on GitHub"
title="Fork me on GitHub"
>Fork me on GitHub</a
>
<div
id="map"
style="width: 100%; height: 100vh; height: 100dvh; background-color: #222"
style="width: 100%; height: 640px; background-color: #222"
></div>
<div>
<button id="btn-loop">loop</button>
<button id="btn-prev">prev</button>
<button id="btn-pause">pause</button>
<button id="btn-play">play</button>
<button id="btn-next">next</button>
</div>
<script type="module" src="./raster.ts"></script>
</body>
</html>
26 changes: 26 additions & 0 deletions example/raster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,30 @@ nowcast.getTimeData().then((timedata) => {
interval: 100,
});
map.addControl(temporalControl);

// control from outside
const btnPrev = document.getElementById('btn-prev')!;
btnPrev.addEventListener('click', () => {
temporalControl.prev();
});

const btnNext = document.getElementById('btn-next')!;
btnNext.addEventListener('click', () => {
temporalControl.next();
});

const btnPlay = document.getElementById('btn-play')!;
btnPlay.addEventListener('click', () => {
temporalControl.play();
});

const btnPause = document.getElementById('btn-pause')!;
btnPause.addEventListener('click', () => {
temporalControl.pause();
});

const btnLoop = document.getElementById('btn-loop')!;
btnLoop.addEventListener('click', () => {
temporalControl.setLoopEnabled(!temporalControl.isLoopEnabled());
});
});
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
},
"homepage": "https://github.com/mug-jp/maplibre-gl-temporal-controller#readme",
"devDependencies": {
"@types/node": "^14.18.63",
"jma-utils": "^0.1.0",
"maplibre-gl": "5.0.0-pre.10",
"typescript": "^4.9.5",
Expand Down
13 changes: 2 additions & 11 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/icons.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// https://materialdesignicons.com/
export const pause =
export const pauseSvg =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>pause</title><path d="M14,19H18V5H14M6,19H10V5H6V19Z" /></svg>';
export const play =
export const playSvg =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>play</title><path d="M8,5.14V19.14L19,12.14L8,5.14Z" /></svg>';
export const reload =
export const reloadSvg =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>reload</title><path d="M2 12C2 16.97 6.03 21 11 21C13.39 21 15.68 20.06 17.4 18.4L15.9 16.9C14.63 18.25 12.86 19 11 19C4.76 19 1.64 11.46 6.05 7.05C10.46 2.64 18 5.77 18 12H15L19 16H19.1L23 12H20C20 7.03 15.97 3 11 3C6.03 3 2 7.03 2 12Z" /></svg>';
export const skipBackward =
export const skipBackwardSvg =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>skip-backward</title><path d="M20,5V19L13,12M6,5V19H4V5M13,5V19L6,12" /></svg>';
export const skipForward =
export const skipForwardSvg =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>skip-forward</title><path d="M4,5V19L11,12M18,5V19H20V5M11,5V19L18,12" /></svg>';
111 changes: 84 additions & 27 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import type {
ControlPosition,
} from 'maplibre-gl';

import { play, pause, reload, skipBackward, skipForward } from './icons';
import {
playSvg,
pauseSvg,
reloadSvg,
skipBackwardSvg,
skipForwardSvg,
} from './icons';

const ACTIVE_BUTTON_COLOR = 'rgb(204, 204, 204)';

Expand All @@ -23,11 +29,13 @@ const makeImg = (svg: string): HTMLImageElement => {
return img;
};

let timerId: number | undefined;

const makeContainer = ({
length,
interval,
onSliderValueChange,
}: ContainerOptions): [HTMLDivElement, HTMLDivElement, HTMLInputElement] => {
}: ContainerOptions) => {
// outest div
const container = document.createElement('div');
container.classList.add('maplibregl-ctrl');
Expand Down Expand Up @@ -63,18 +71,21 @@ const makeContainer = ({
buttonsDiv.style.margin = '4px 0 0 0';

// loop button
const setLoopEnabled = (enabled: boolean) => {
loopButton.style.backgroundColor = enabled ? ACTIVE_BUTTON_COLOR : '';
};
const isLoopEnabled = () =>
loopButton.style.backgroundColor === ACTIVE_BUTTON_COLOR;
const loopButton = document.createElement('button');
loopButton.appendChild(makeImg(reload));
loopButton.appendChild(makeImg(reloadSvg));
loopButton.style.border = '0';
loopButton.style.borderRadius = '0';
loopButton.style.marginRight = '16px';
loopButton.style.height = '24px';
loopButton.style.borderRadius = '4px';
loopButton.onclick = () => {
loopButton.style.backgroundColor =
loopButton.style.backgroundColor === '' ? ACTIVE_BUTTON_COLOR : '';
};
loopButton.onclick = () => setLoopEnabled(!isLoopEnabled());
buttonsDiv.appendChild(loopButton);

const decrement = () => {
slider.value = String(Math.max(0, Number(slider.value) - 1));
onSliderValueChange();
Expand All @@ -97,42 +108,48 @@ const makeContainer = ({

// prev button
const prevButton = document.createElement('button');
prevButton.appendChild(makeImg(skipBackward));
prevButton.appendChild(makeImg(skipBackwardSvg));
prevButton.onclick = decrement;
prevButton.style.border = '0';
prevButton.style.height = '24px';
prevButton.style.borderRadius = '4px';

// pause button
const pause = () => {
if (timerId === undefined) return;
clearInterval(timerId);
timerId = undefined;
pauseButton.onclick = null;
playButton.style.backgroundColor = '';
};
const pauseButton = document.createElement('button');
pauseButton.appendChild(makeImg(pause));
pauseButton.appendChild(makeImg(pauseSvg));
pauseButton.style.border = '0';
pauseButton.style.height = '24px';
pauseButton.style.borderRadius = '4px';
pauseButton.onclick = pause;

// play button
const playButton = document.createElement('button');
playButton.appendChild(makeImg(play));
playButton.style.border = '0';
playButton.style.height = '24px';
playButton.style.borderRadius = '4px';
playButton.onclick = () => {
if (playButton.style.backgroundColor === ACTIVE_BUTTON_COLOR) return;

const isPlaying = () =>
playButton.style.backgroundColor === ACTIVE_BUTTON_COLOR;
const play = () => {
if (isPlaying()) return;
playButton.style.backgroundColor = ACTIVE_BUTTON_COLOR;
const timerId = setInterval(() => {
timerId = setInterval(() => {
increment();
}, interval);
pauseButton.onclick = () => {
clearInterval(timerId);
pauseButton.onclick = null;
playButton.style.backgroundColor = '';
};
};

const playButton = document.createElement('button');
playButton.appendChild(makeImg(playSvg));
playButton.style.border = '0';
playButton.style.height = '24px';
playButton.style.borderRadius = '4px';
playButton.onclick = play;

// next button
const nextButton = document.createElement('button');
nextButton.appendChild(makeImg(skipForward));
nextButton.appendChild(makeImg(skipForwardSvg));
nextButton.style.border = '0';
nextButton.style.height = '24px';
nextButton.style.borderRadius = '4px';
Expand All @@ -145,7 +162,18 @@ const makeContainer = ({

container.appendChild(buttonsDiv);

return [container, titleDiv, slider];
return {
container,
titleDiv,
slider,
increment,
decrement,
isPlaying,
play,
pause,
isLoopEnabled,
setLoopEnabled,
};
};

type Position = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
Expand All @@ -170,6 +198,14 @@ export default class TemporalControl implements IControl {
private temporalSlider!: HTMLInputElement;
private temporalFrames: TemporalFrame[];

next: () => boolean;
prev: () => boolean;
play: () => void;
pause: () => void;
isPlaying: () => boolean;
isLoopEnabled: () => boolean;
setLoopEnabled: (enabled: boolean) => void;

constructor(temporalFrames: TemporalFrame[], options: Options = {}) {
this.temporalFrames = temporalFrames;
this.options = options;
Expand All @@ -180,8 +216,29 @@ export default class TemporalControl implements IControl {
onSliderValueChange: () => this.refresh(),
};

[this.container, this.containerTitle, this.temporalSlider] =
makeContainer(containerOptions);
const {
container,
titleDiv,
slider,
increment,
decrement,
play,
pause,
isPlaying,
isLoopEnabled,
setLoopEnabled,
} = makeContainer(containerOptions);

this.container = container;
this.containerTitle = titleDiv;
this.temporalSlider = slider;
this.next = increment;
this.prev = decrement;
this.play = play;
this.pause = pause;
this.isPlaying = isPlaying;
this.isLoopEnabled = isLoopEnabled;
this.setLoopEnabled = setLoopEnabled;
}

onAdd(map: Map) {
Expand Down

0 comments on commit 0e736ff

Please sign in to comment.