blob: 85c2f3dac29708691f339e2ee89c1c66a5145c8e [file] [log] [blame]
import {css, html, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {styleMap} from 'lit/directives/style-map.js';
import {Device, Notifiable, SimulationInfo, simulationState,} from './device-observer.js';
@customElement('ns-device-map')
export class DeviceMap extends LitElement implements Notifiable {
/**
* List of devices currently on the netsim.
*/
@property() deviceData: Device[] = [];
/**
* Index of the background image displayed.
*/
@property() imageIdx = 0;
/**
* Number of images available for the background.
*/
@property() numImages = 3;
@property({type: Boolean, reflect: true}) isometric: boolean = false;
connectedCallback() {
super.connectedCallback(); // eslint-disable-line
simulationState.registerObserver(this);
window.addEventListener('map-button-clicked', this.onChangeMap);
window.addEventListener(
'isometric-button-clicked', this.handleIsometricView);
}
disconnectedCallback() {
window.removeEventListener(
'isometric-button-clicked', this.handleIsometricView);
window.removeEventListener('map-button-clicked', this.onChangeMap);
simulationState.removeObserver(this);
super.disconnectedCallback(); // eslint-disable-line
}
static styles = css`
#dropzone {
margin-left: 200px;
margin-right: 200px;
transition: transform 2s, top 2s;
transform-style: preserve-3d;
}
.box {
position: relative;
width: 1000px; //40vw;
height: 1000px; //40vh;
border: solid 1px rgb(198, 210, 255);
margin: 2.5em auto;
}
.pattern0 {
background-image: url(./assets/grid-background.svg);
}
.pattern1 {
background-image: url(./assets/polar-background.svg);
background-size: 1150px 1150px;
background-position: center;
}
.pattern2 {
background-image: url(./assets/hexagonal-background.png);
background-size: 1175px 1175px;
background-position: center;
}
.container {
display: flex;
width: 100%;
}
.contentA {
flex: 2;
}
.contentB {
flex: 2;
}
ns-device-dragzone {
transform-style: inherit;
}
`;
onNotify(data: SimulationInfo): void {
this.deviceData = data.devices;
this.requestUpdate();
}
private onChangeMap = () => {
this.imageIdx = (this.imageIdx + 1) % this.numImages;
};
private handleIsometricView = () => {
this.isometric = !this.isometric;
};
render() {
const rainbow = [
'red',
'orange',
'yellow',
'green',
'blue',
'indigo',
'purple',
];
const viewStyle = this.isometric ?
`perspective(200rem) rotateX(60deg) rotateY(0deg) rotateZ(0deg) scale3d(0.8,0.8,0.8); top: 250px` :
'none; top: 0px;';
return html`
<ns-device-dropzone role="region" tabindex="0" aria-label="Device map">
<div id="dropzone" class="box pattern${this.imageIdx}">
${
this.deviceData.map(
(device, idx) => html`
${
device.visible === true ?
html`
<ns-device-dragzone
.action=${'move'}
style=${styleMap({
position: 'absolute',
left: `${device.position.x * 100}px`,
top: `${device.position.y * 100}px`,
})}
role="region"
tabindex="1"
aria-label="Position: ${
Math.round(device.position.x * 100)}, ${
Math.round(device.position.y * 100)}, ${
Math.round(device.position.z * 100)}"
aria-live="assertive"
>
<ns-cube-sprite
id=${device.name}
.color=${rainbow[idx % rainbow.length]}
.size=${'30px'}
.controls=${true}
yaw=${device.orientation.yaw}
pitch=${device.orientation.pitch}
roll=${device.orientation.roll}
posZ=${device.position.z * 100}
></ns-cube-sprite>
</ns-device-dragzone>
` :
html``}
`)}
</div>
<style>
#dropzone {
transform: ${viewStyle};
}
</style>
</ns-device-dropzone>
`;
}
}