-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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: PopupWidget #8958
base: master
Are you sure you want to change the base?
POC: PopupWidget #8958
Changes from all commits
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, | ||
Comment on lines
+83
to
+84
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?