proximity and propagator demo

This commit is contained in:
“chrisshank” 2024-12-02 16:16:44 -08:00
parent d9df421dde
commit 62d8da10bf
6 changed files with 232 additions and 75 deletions

View File

@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Proximity And Propagators</title>
<style>
* {
box-sizing: border-box;
}
html {
height: 100%;
}
body {
min-height: 100%;
position: relative;
margin: 0;
}
folk-map,
geo-wiki {
display: block;
height: 100%;
width: 100%;
}
geo-wiki {
display: block;
background: white;
border: solid 2px black;
border-radius: 5px;
ul {
height: 100%;
overflow: auto;
margin: 0;
scroll-padding-block-end: 1rem;
}
}
folk-cluster {
display: block;
position: absolute;
inset: 0 0 0 0;
pointer-events: none;
background-color: #b4d8f63b;
}
folk-weather {
display: block;
background: white;
border: solid 2px black;
border-radius: 5px;
padding: 1rem;
}
folk-event-propagator {
display: block;
position: absolute;
inset: 0 0 0 0;
pointer-events: none;
}
</style>
</head>
<body>
<folk-shape x="25" y="500">
<label>Lat: <input type="range" min="40.5" max="41" step="0.001" value="40.76845173617708" /></label>
</folk-shape>
<folk-proximity>
<folk-shape id="g1" x="25" y="100" width="400" height="200">
<folk-map coordinates="40.76845173617708, -73.97983074188234" zoom="15"></folk-map>
</folk-shape>
<folk-shape id="g3" x="400" y="300" width="500" height="300">
<geo-wiki></geo-wiki>
</folk-shape>
<folk-shape id="g4" x="450" y="100">
<folk-weather></folk-weather>
</folk-shape>
</folk-proximity>
<folk-event-propagator
source="input[type='range']"
target="folk-map"
triggers="input"
expression="lat: from.value"
></folk-event-propagator>
<script type="module">
import { FolkShape } from '../src/folk-shape.ts';
import { FolkEventPropagator } from '../src/folk-event-propagator.ts';
import { FolkMap } from '../src/folk-map.ts';
import { FolkWeather } from '../src/folk-weather.ts';
import { FolkCluster, FolkProximity } from '../src/folk-proximity.ts';
import { GeoWiki } from './src/geo-wiki.ts';
FolkCluster.registerElement({
constructor: FolkMap,
events: {
recenter: (e) => ({
lat: e.target.coordinates.lat,
lng: e.target.coordinates.lng,
}),
},
onAdd: (element) => ({
lat: element.coordinates.lat,
lng: element.coordinates.lng,
}),
});
FolkCluster.registerElement({
constructor: FolkWeather,
onUpdate(element, data, changes) {
const lat = data.get('lat');
const lng = data.get('lng');
if (lat && lng) {
element.coordinates = [lat, lng];
}
},
});
FolkCluster.registerElement({
constructor: GeoWiki,
onUpdate(element, data, changes) {
const lat = data.get('lat');
const lng = data.get('lng');
if (lat && lng) {
element.coordinates = [lat, lng];
}
},
});
FolkShape.define();
FolkMap.define();
FolkCluster.define();
FolkProximity.define();
FolkWeather.define();
GeoWiki.define();
FolkEventPropagator.define();
</script>
</body>
</html>

View File

@ -80,69 +80,7 @@
import { FolkMap } from '../src/folk-map.ts';
import { FolkWeather } from '../src/folk-weather.ts';
import { FolkCluster, FolkProximity } from '../src/folk-proximity.ts';
class GeoWiki extends HTMLElement {
static tagName = 'geo-wiki';
static define() {
customElements.define(this.tagName, this);
}
static observedAttributes = ['coordinates'];
#coordinates = [0, 0];
#results = [];
get coordinates() {
return this.#coordinates;
}
set coordinates(coordinates) {
this.setAttribute('coordinates', coordinates.join(', '));
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'coordinates') {
this.#coordinates = newValue.split(',').map((str) => Number(str)) || [0, 0];
this.searchWiki(this.#coordinates);
}
}
async searchWiki([lat, long]) {
const params = new URLSearchParams({
action: 'query',
format: 'json',
list: 'geosearch',
gscoord: `${lat}|${long}`,
gsradius: '1000',
gslimit: '50',
origin: '*',
});
// https://www.mediawiki.org/wiki/API:Geosearch
this.#results = await fetch(`https://en.wikipedia.org/w/api.php?${params}`)
.then((response) => response.json())
.then((data) => data?.query?.geosearch ?? []);
this.#renderResults();
}
#renderResults() {
this.firstElementChild?.remove();
const list = document.createElement('ul');
for (const result of this.#results) {
const li = document.createElement('li');
const a = document.createElement('a');
a.href = `https://en.wikipedia.org/wiki/${result.title}`;
a.textContent = result.title;
li.appendChild(a);
list.appendChild(li);
}
this.appendChild(list);
}
}
import { GeoWiki } from './src/geo-wiki.ts';
FolkCluster.registerElement({
constructor: FolkMap,
@ -160,7 +98,6 @@
FolkCluster.registerElement({
constructor: FolkWeather,
onAdd: console.log,
onUpdate(element, data, changes) {
const lat = data.get('lat');
const lng = data.get('lng');

64
demo/src/geo-wiki.ts Normal file
View File

@ -0,0 +1,64 @@
type LatLng = [number, number];
export class GeoWiki extends HTMLElement {
static tagName = 'geo-wiki';
static define() {
customElements.define(this.tagName, this);
}
static observedAttributes = ['coordinates'];
#coordinates: LatLng = [0, 0];
#results: any[] = [];
get coordinates() {
return this.#coordinates;
}
set coordinates(coordinates) {
this.setAttribute('coordinates', coordinates.join(', '));
}
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
if (name === 'coordinates') {
this.#coordinates = ((newValue || '').split(',').map((str) => Number(str)) || [0, 0]) as LatLng;
this.searchWiki(this.#coordinates);
}
}
async searchWiki([lat, long]: LatLng) {
const params = new URLSearchParams({
action: 'query',
format: 'json',
list: 'geosearch',
gscoord: `${lat}|${long}`,
gsradius: '1000',
gslimit: '50',
origin: '*',
});
// https://www.mediawiki.org/wiki/API:Geosearch
this.#results = await fetch(`https://en.wikipedia.org/w/api.php?${params}`)
.then((response) => response.json())
.then((data) => data?.query?.geosearch ?? []);
this.#renderResults();
}
#renderResults() {
this.firstElementChild?.remove();
const list = document.createElement('ul');
for (const result of this.#results) {
const li = document.createElement('li');
const a = document.createElement('a');
a.href = `https://en.wikipedia.org/wiki/${result.title}`;
a.textContent = result.title;
li.appendChild(a);
list.appendChild(li);
}
this.appendChild(list);
}
}

View File

@ -288,8 +288,6 @@ export class RecordPlayer extends HTMLElement {
this.#audio.pause();
this.#audio.currentTime = 0;
this.dispatchEvent(new Event('stopped', { bubbles: true }));
// console.log(a);
}
handleEvent(event: Event) {

View File

@ -34,17 +34,29 @@ export class FolkMap extends HTMLElement {
constructor() {
super();
this.handleEvent = this.handleEvent.bind(this);
const shadow = this.attachShadow({ mode: 'open' });
shadow.adoptedStyleSheets.push(styles);
shadow.appendChild(this.#container);
}
get coordinates() {
get lat() {
return this.coordinates.lat;
}
set lat(lat) {
this.coordinates = [lat, this.lng];
}
get lng() {
return this.coordinates.lng;
}
set lng(lng) {
this.coordinates = [this.lat, lng];
}
get coordinates(): LatLng {
return this.#map.getCenter();
}
set coordinates(coordinates) {
set coordinates(coordinates: LatLngExpression) {
this.#map.setView(coordinates);
}
@ -64,7 +76,7 @@ export class FolkMap extends HTMLElement {
})
);
this.#map.on('zoom', this.handleEvent);
// Move end includes changes to zoom
this.#map.on('moveend', this.handleEvent);
this.#map.setView(
@ -73,13 +85,12 @@ export class FolkMap extends HTMLElement {
);
}
handleEvent(event: LeafletEvent) {
handleEvent = (event: LeafletEvent) => {
switch (event.type) {
case 'zoom':
case 'moveend': {
this.dispatchEvent(new RecenterEvent());
break;
}
}
}
};
}

View File

@ -15,7 +15,7 @@ export interface ElementConfig<E extends Element = Element> {
}
// TODO don't hard code this
const PROXIMITY = 50;
const PROXIMITY = 100;
declare global {
interface HTMLElementTagNameMap {