UNPKG

@google/model-viewer

Version:

Easily display interactive 3D models on the web and in AR!

134 lines (112 loc) 3.78 kB
import {css, customElement, html, LitElement, property} from 'lit-element'; import {ImageComparisonConfig, ScenarioConfig} from '../common.js'; import {ConfigReader} from '../config-reader.js'; @customElement('renderer-harness') export class RendererConfiguration extends LitElement { @property({type: String, attribute: 'scenario-name'}) scenarioName: string|null = null; @property({type: String, attribute: 'config-url'}) configUrl: string|null = null; @property({type: Boolean, attribute: 'hide-ui'}) hideUi: boolean = false; @property({type: Object}) protected config: ImageComparisonConfig|null = null; @property({type: Object}) protected scenario: ScenarioConfig|null = null; connectedCallback() { super.connectedCallback(); const {queryParameters} = this; this.configUrl = queryParameters.config || '../../config.json'; this.scenarioName = queryParameters.scenario || null; this.hideUi = 'hide-ui' in queryParameters || false; } protected get queryParameters(): {[index: string]: string} { return self.location.search.slice(1).split('&').reduce( (queryParameters, parameter) => { const [key, value] = parameter.split('='); queryParameters[key] = decodeURIComponent(value); return queryParameters; }, {} as {[index: string]: string}); } async updated(changedProperties: Map<string, any>) { super.updated(changedProperties); if (changedProperties.has('configUrl')) { if (this.configUrl == null) { this.config = null; } else { this.config = await (await fetch(this.configUrl)).json() } } if (changedProperties.has('scenarioName') || changedProperties.has('config')) { if (this.scenarioName == null || this.config == null) { this.scenario = null; } else { this.scenario = (new ConfigReader(this.config)).scenarioConfig(this.scenarioName); this.dispatchEvent(new CustomEvent( 'scenario-change', {detail: {scenario: this.scenario}})); } const previousScenarioName = changedProperties.get('scenarioName'); if (previousScenarioName != null && this.scenarioName != null) { const url = new URL(window.location.toString()); url.search = url.search.replace( `scenario=${encodeURIComponent(previousScenarioName)}`, `scenario=${encodeURIComponent(this.scenarioName)}`); history.pushState(null, document.title, url.toString()); } } } static get styles() { return css` :host { display: flex; flex-direction: column; font-family: system-ui, sans-serif; color: #fafafa; } #widgets { display: flex; flex-direction: row; align-items: center; justify-content: space-between; background-color: #444; padding: 0 1em; min-height: 4em; } #widgets > * { margin-right: 1em; } #widgets.hidden { display: none; } #renderer { max-width: 100%; overflow: auto; } `; } render() { const widgets = []; if (this.config != null) { const scenarioOptions = this.config.scenarios.map( scenario => html`<option ?selected="${ scenario.name === this.scenarioName}">${scenario.name}</option>`); widgets.push(html` <select @change="${ (event: Event) => this.scenarioName = (event.target != null ? (event.target as HTMLSelectElement).value : this.scenarioName)}"> ${scenarioOptions} </select>`); } return html` <div id="widgets" class="${this.hideUi ? 'hidden' : ''}"> <h2><slot name="title"></slot></h2> ${widgets} </div> <div id="renderer" .style="${this.hideUi ? 'overflow: visible' : ''}"> <slot name="renderer"></slot> </div> `; } }