-
Notifications
You must be signed in to change notification settings - Fork 24
Annotation UILayer and Tooltips #1004
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
Changes from all commits
9b7d799
78386eb
236f251
dacba1a
e4c7279
b69999d
87a24a4
7843ddb
51188da
93e13fd
903a9eb
20957f2
dfb66bf
aefe784
19a1694
f131056
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 |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| <script lang="ts"> | ||
| import { | ||
| defineComponent, PropType, Ref, | ||
| } from '@vue/composition-api'; | ||
| import { StateStyles } from '../../use/useStyling'; | ||
| import { ToolTipWidgetData } from './UILayerTypes'; | ||
| /* | ||
| This Component will be mounted indepedently of the main Vue App | ||
| on a GeoJS canvas element. To ensure reactivity between the main Vue App | ||
| and this element the props are passed in the initalization function instead of on a template. | ||
| This is why reactivate data in this component is utilizing PropType<Ref<data>>. | ||
| All references to reactive PropType<Ref<data>> need to be derefernced in the template as well. | ||
| */ | ||
| export default defineComponent({ | ||
| name: 'ToolTipWidget', | ||
| props: { | ||
| color: { | ||
| type: Function as PropType<(name: string) => string>, | ||
| required: true, | ||
| }, | ||
| stateStyling: { | ||
| type: Object as PropType<StateStyles>, | ||
| required: true, | ||
| }, | ||
| textSettings: { | ||
| type: Function as PropType<(name: string) => { showLabel: boolean; showConfidence: boolean }>, | ||
| default: () => ({ showLabel: true, showConfidence: true }), | ||
| }, | ||
| dataList: { | ||
| type: Object as PropType<Ref<ToolTipWidgetData[]>>, | ||
| default: () => [], | ||
| }, | ||
| selected: { | ||
| type: Object as PropType<Ref<number|null>>, | ||
|
Contributor
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 understand that because this component is being mounted as the root of the application, there's no parent to drive changes in its props, but it took me a little bit of code reading to figure that out. Could the UILayer class have a description comment block to describe this design choice, how it works, and what the special requirements of its widget components are? |
||
| required: true, | ||
| }, | ||
| }, | ||
| setup(props) { | ||
| const coloring = (data: ToolTipWidgetData) => { | ||
| if (data.trackId === props.selected.value) { | ||
| return props.stateStyling.selected.color; | ||
| } | ||
| return props.color(data.type); | ||
| }; | ||
| return { | ||
| coloring, | ||
| }; | ||
| }, | ||
| }); | ||
| </script> | ||
|
|
||
| <template> | ||
| <v-card | ||
| v-if="dataList.value.length" | ||
| dark | ||
| max-width="200px" | ||
| class="d-inline-flex pa-2" | ||
| > | ||
| <div> | ||
| <div | ||
| v-for="(item, index) in dataList.value" | ||
| :key="index" | ||
| > | ||
| <span | ||
| :style="{ color: coloring(item) }" | ||
| class="pr-1 pb-1" | ||
| > | ||
| █ | ||
| </span> | ||
| <span>{{ `${item.type}:${item.confidence.toFixed(2)}` }}</span> | ||
| </div> | ||
| </div> | ||
| </v-card> | ||
| </template> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import { createApp } from '@vue/composition-api'; | ||
| import { MediaController } from '../../components/annotators/mediaControllerType'; | ||
|
|
||
|
|
||
| interface WidgetPosition { | ||
| x: string | number; | ||
| y: string | number; | ||
| } | ||
| export interface DOMWidget { | ||
| canvas: () => HTMLElement; | ||
| isInViewport: () => boolean; | ||
| position: (pos: WidgetPosition) => WidgetPosition; | ||
| } | ||
| /** | ||
| * UILayer provides a way to add Reactive VUE DOM Widgets to GeoJS | ||
| * These widgets are created under their own Vue App and can't rely on parent elements | ||
| * for reactivity. | ||
| * Reactive properties for these components will need to be passed in as Refs and | ||
| * dereferenced inside of the Vue component to properly update. | ||
| * This will probably change once Vue 3 is adopted and <teleport> can be used | ||
| */ | ||
| export default class UILayer { | ||
| annotator: MediaController; | ||
|
|
||
| widgets: Record<string, DOMWidget>; | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| uiLayer: any; | ||
|
|
||
| constructor(annotator: MediaController) { | ||
| this.annotator = annotator; | ||
| this.widgets = {}; | ||
| this.uiLayer = this.annotator.geoViewerRef.value.createLayer('ui'); | ||
| } | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| addDOMWidget(name: string, component: any, props: any, position = { x: 0, y: 0 }) { | ||
| const widget: DOMWidget = this.uiLayer.createWidget('dom', { position }); | ||
| widget.canvas().setAttribute('id', name); | ||
| const parent = widget.canvas(); | ||
| const div = document.createElement('div'); | ||
| const element = parent.appendChild(div); | ||
| createApp(component, props).mount(element); | ||
| this.widgets[name] = widget; | ||
|
|
||
| return widget; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export interface ToolTipWidgetData { | ||
| type: string; | ||
| confidence: number; | ||
| trackId: number; | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.