@panoramax/web-viewer
Version:
Panoramax web viewer for geolocated pictures
156 lines (138 loc) • 4.66 kB
JavaScript
import { LitElement, html, css, nothing } from "lit";
import { faSvg, iconify } from "../styles";
import { fa, moreIcons } from "../../utils/widgets";
import { faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight";
import { faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft";
import { onceParentAvailable } from "../../utils/widgets";
import "iconify-icon";
/**
* Annotations list shows listing of tagged picture areas.
* It uses the parent component currently selected picture.
*
* @class Panoramax.components.menus.AnnotationsList
* @element pnx-annotations-list
* @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
* @example
* ```html
* <pnx-annotations-list _parent=${viewer} />
* ```
*/
export default class AnnotationsList extends LitElement {
/** @private */
static styles = [ faSvg, iconify, css`
.annotation { background: var(--white); }
` ];
/** @private */
static properties = {
_meta: {state: true},
_selectedAnnotation: {state: true},
_presets: {state: true},
};
constructor() {
super();
this._selectedAnnotation = null;
this._presets = {};
moreIcons();
}
/** @private */
connectedCallback() {
super.connectedCallback();
this._onPicChange();
onceParentAvailable(this).then(() => {
this._parent.psv?.addEventListener("picture-loaded", this._onPicChange.bind(this));
this._parent.psv?.addEventListener("annotation-click", e => {
const aPos = this._meta.properties?.annotations?.findIndex(a => a.id === e.detail.annotationId);
if(aPos >= 0) { this._onListItemClick(Object.assign({nb: aPos+1}, this._meta.properties.annotations[aPos])); }
});
this._parent.psv?.addEventListener("annotations-unfocused", () => {
this._onListItemClick(null);
});
});
}
/** @private */
_onPicChange() {
this._meta = this._parent?.psv?.getPictureMetadata();
delete this._prevPsvView;
this._selectedAnnotation = null;
// Load presets for annotations
if(this._meta && this._parent?.presetsManager) {
this._presets = {};
if(this._meta.properties?.annotations?.length > 0) {
this._meta.properties.annotations.map(a => this._parent.presetsManager.getPreset(a).then(p => {
this._presets[a.id] = p;
this.requestUpdate();
}));
}
}
}
/** @private */
_onListItemHover(a) {
if(a) {
// Save position before hover to allow reset after
if(!this._prevPsvView) { this._prevPsvView = [this._parent.psv.getZoomLevel(), this._parent.psv.getPosition()]; }
this._parent.psv.focusOnAnnotation(a.id);
}
else {
this._parent.psv.unfocusAnnotation();
// Restore previous PSV position
if(this._prevPsvView) {
this._parent.psv.zoom(this._prevPsvView[0]);
this._parent.psv.rotate(this._prevPsvView[1]);
delete this._prevPsvView;
}
}
}
/** @private */
_onListItemClick(a) {
this._selectedAnnotation = a;
this._onListItemHover(a);
}
/** @private */
render() {
/* eslint-disable indent */
if(!this._meta) { return nothing; }
return this._selectedAnnotation === null
? html`<div class="list">
${this._meta.properties.annotations.map((a,i) => html`
<pnx-list-item
title=${
this._presets[a.id]?.name
|| this._parent?._t.pnx.semantics_features_default_title.replace("{nb}", i+1)
}
subtitle=${this._parent?._t.pnx.semantics_features_subtitle.replace("{nb}", a.semantics.length)}
=${() => this._onListItemClick(Object.assign({nb: i+1}, a))}
=${() => this._onListItemHover(Object.assign({nb: i+1}, a))}
=${() => this._onListItemHover(null)}
>
<iconify-icon
slot="icon"
icon=${this._presets[a.id]?.iconify || "fa6-solid:cube"}
style="font-size: 1.5em"
></iconify-icon>
${fa(faChevronRight, {transform: {size: 24}, attributes: {slot: "action"}})}
</pnx-list-item>
`)}
</div>`
: html`<div class="annotation">
<pnx-list-item
title=${
this._presets[this._selectedAnnotation.id]?.name
|| this._parent?._t.pnx.semantics_features_default_title.replace("{nb}", this._selectedAnnotation.nb)
}
=${() => this._onListItemClick(null)}
>
${fa(faArrowLeft, {transform: {size: 24}, attributes: {slot: "icon"}})}
<iconify-icon
slot="icon"
icon=${this._presets[this._selectedAnnotation.id]?.iconify || "fa6-solid:cube"}
style="font-size: 1.5em"
></iconify-icon>
</pnx-list-item>
<pnx-semantics-table
._t=${this._parent?._t}
.source=${this._selectedAnnotation}
/>
</div>`;
}
}
customElements.define("pnx-annotations-list", AnnotationsList);