-
Notifications
You must be signed in to change notification settings - Fork 2.2k
POC: InfoWidget #8958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
POC: InfoWidget #8958
Changes from 4 commits
e2d8e5a
ce3404f
6ab2d63
491743d
e5a4700
8bd02a6
95b5081
ddf97fc
6e3e689
6c18956
e3cb29f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
export {FullscreenWidget} from './fullscreen-widget'; | ||
export {CompassWidget} from './compass-widget'; | ||
export {PopupWidget} from './popup-widget'; | ||
export {ZoomWidget} from './zoom-widget'; | ||
|
||
export * from './themes'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* global document */ | ||
import {FlyToInterpolator, WebMercatorViewport, _GlobeViewport} from '@deck.gl/core'; | ||
import type {Deck, Viewport, Widget, WidgetPlacement} from '@deck.gl/core'; | ||
import {render} from 'preact'; | ||
|
||
interface PopupWidgetProps { | ||
id: string; | ||
/** | ||
* View to attach to and interact with. Required when using multiple views. | ||
*/ | ||
viewId?: string | null; | ||
/** | ||
* CSS inline style overrides. | ||
*/ | ||
style?: Partial<CSSStyleDeclaration>; | ||
/** | ||
* Additional CSS class. | ||
*/ | ||
className?: string; | ||
/** | ||
* Position at which to place popup | ||
*/ | ||
position: [number, number]; | ||
/** | ||
* Text of popup | ||
*/ | ||
text: string; | ||
} | ||
|
||
export class PopupWidget implements Widget<PopupWidgetProps> { | ||
id = 'popup'; | ||
props: PopupWidgetProps; | ||
viewId?: string | null = null; | ||
viewport?: Viewport; | ||
deck?: Deck<any>; | ||
element?: HTMLDivElement; | ||
|
||
constructor(props: PopupWidgetProps) { | ||
this.id = props.id || 'popup'; | ||
this.viewId = props.viewId || null; | ||
props.style = props.style || {}; | ||
props.position = props.position || [0, 0]; | ||
props.text = props.text || ''; | ||
this.props = props; | ||
} | ||
|
||
setProps(props: Partial<PopupWidgetProps>) { | ||
Object.assign(this.props, props); | ||
this.update(); | ||
} | ||
|
||
onViewportChange(viewport) { | ||
this.viewport = viewport; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A broader question since we have eye balls on widgets.. How should we handle if this has been added to no specific viewport, and there are multiple viewports? This remains an unsolved question in all of our viewport-dependent widgets. Currently, only the last viewport in the list will get the popup even if the I wonder if we a widget should be able to return multiple UI elements if there are multiple viewports around L66 in onAdd? Or if there should be some warning or documentation to say "you're using multiple viewports, so you should instantiate a widget-per-viewport and supply |
||
this.update(); | ||
} | ||
|
||
onAdd({deck, viewId}: {deck: Deck<any>, viewId: string | null}): HTMLDivElement { | ||
const {className} = this.props; | ||
const element = document.createElement('div'); | ||
element.classList.add('deck-widget', 'deck-widget-popup'); | ||
if (className) element.classList.add(className); | ||
const style = {margin: '0px', top: '0px', left: '0px', position: 'absolute'}; | ||
Object.entries(style).map(([key, value]) => element.style.setProperty(key, value as string)); | ||
this.deck = deck; | ||
if (!viewId) { | ||
this.viewport = deck.getViewports()[0]; | ||
} else { | ||
this.viewport = deck.getViewports().find(viewport => viewport.id === viewId); | ||
} | ||
this.element = element; | ||
this.update(); | ||
return element; | ||
} | ||
|
||
update() { | ||
const [longitude, latitude] = this.props.position; | ||
const [x, y] = this.viewport!.project([longitude, latitude]); | ||
const element = this.element; | ||
if (!element) { | ||
return; | ||
} | ||
const style = { | ||
background: 'rgba(255, 255, 255, 0.9)', | ||
padding: 10, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to use CSS variables and add theming for these. My approach has been to put styles that aren't 100% necessary for functionality in the stylesheet and theme examples in here. |
||
...this.props.style as any, | ||
perspective: 100, | ||
transform: `translate(${x}px, ${y}px)` | ||
} | ||
const ui = (<div style={style}>{this.props.text}</div>); | ||
render(ui, element); | ||
} | ||
|
||
onRemove() { | ||
this.deck = undefined; | ||
this.element = undefined; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the
PopupWidget
just take a callback instead, so we don't need to mess with it like this?