Skip to content
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

Unified component event structure #347

Merged
merged 1 commit into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/Mapillary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,22 @@ ComponentService.register(ZoomComponent);
// Mapillary module
export { isFallbackSupported, isSupported } from "./utils/Support";

// Component types
export { Component } from "./component/Component";
export { ComponentEvent } from "./component/events/ComponentEvent";
export { ComponentSize } from "./component/utils/ComponentSize";
export {
ComponentGeometryEvent,
ComponentHoverEvent,
ComponentMarkerEvent,
ComponentPlayEvent,
ComponentStateEvent,
ComponentTagModeEvent,
} from "./component/events/ComponentStateEvent";
export { IComponent } from "./component/interfaces/IComponent";

// Viewer types
export { Alignment } from "./viewer/enums/Alignment";
export { ComponentSize } from "./component/utils/ComponentSize";
export { IViewer } from "./viewer/interfaces/IViewer";
export { ICustomRenderer } from "./viewer/interfaces/ICustomRenderer";
export { PointOfView } from "./viewer/interfaces/PointOfView";
Expand Down
55 changes: 50 additions & 5 deletions src/component/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,28 @@ import { ComponentConfiguration } from "./interfaces/ComponentConfiguration";
import { Container } from "../viewer/Container";
import { Navigator } from "../viewer/Navigator";
import { EventEmitter } from "../utils/EventEmitter";
import { SubscriptionHolder } from "../utils/SubscriptionHolder";
import { IComponent } from "./interfaces/IComponent";
import { ComponentEvent } from "./events/ComponentEvent";

export abstract class Component
<TConfiguration extends ComponentConfiguration>
extends EventEmitter
implements IComponent {

export abstract class Component<TConfiguration extends ComponentConfiguration> extends EventEmitter {
public static componentName: string = "not_worthy";

protected _activated: boolean;
protected _container: Container;
protected _name: string;
protected _navigator: Navigator;
protected readonly _subscriptions: SubscriptionHolder;

protected _activated$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
protected _activated$: BehaviorSubject<boolean> =
new BehaviorSubject<boolean>(false);
protected _configuration$: Observable<TConfiguration>;
protected _configurationSubject$: Subject<TConfiguration> = new Subject<TConfiguration>();
protected _configurationSubject$: Subject<TConfiguration> =
new Subject<TConfiguration>();

constructor(name: string, container: Container, navigator: Navigator) {
super();
Expand All @@ -36,6 +46,7 @@ export abstract class Component<TConfiguration extends ComponentConfiguration> e
this._container = container;
this._name = name;
this._navigator = navigator;
this._subscriptions = new SubscriptionHolder();

this._configuration$ =
this._configurationSubject$.pipe(
Expand All @@ -56,6 +67,12 @@ export abstract class Component<TConfiguration extends ComponentConfiguration> e
this._configuration$.subscribe(() => { /*noop*/ });
}

/**
* Get activated.
*
* @returns {boolean} Value indicating if the component is
* currently active.
*/
public get activated(): boolean {
return this._activated;
}
Expand Down Expand Up @@ -89,6 +106,7 @@ export abstract class Component<TConfiguration extends ComponentConfiguration> e
return this._name;
}

/** @ignore */
public activate(conf?: TConfiguration): void {
if (this._activated) {
return;
Expand All @@ -103,10 +121,16 @@ export abstract class Component<TConfiguration extends ComponentConfiguration> e
this._activated$.next(true);
}

public configure(conf: TConfiguration): void {
this._configurationSubject$.next(conf);
/**
* Configure the component.
*
* @param configuration Component configuration.
*/
public configure(configuration: TConfiguration): void {
this._configurationSubject$.next(configuration);
}

/** @ignore */
public deactivate(): void {
if (!this._activated) {
return;
Expand All @@ -119,6 +143,27 @@ export abstract class Component<TConfiguration extends ComponentConfiguration> e
this._activated$.next(false);
}

/** @inheritdoc */
public fire<T>(
type: ComponentEvent,
event: T): void {
super.fire(type, event);
}

/** @inheritdoc */
public off<T>(
type: ComponentEvent,
handler: (event: T) => void): void {
super.off(type, handler);
}

/** @inheritdoc */
public on<T>(
type: ComponentEvent,
handler: (event: T) => void): void {
super.on(type, handler);
}

/**
* Detect the viewer's new width and height and resize the component's
* rendered elements accordingly if applicable.
Expand Down
12 changes: 4 additions & 8 deletions src/component/attribution/AttributionComponent.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import * as vd from "virtual-dom";

import {
combineLatest as observableCombineLatest,
Subscription,
} from "rxjs";
import { combineLatest as observableCombineLatest } from "rxjs";

import { map } from "rxjs/operators";

Expand All @@ -19,14 +16,13 @@ import { Navigator } from "../../viewer/Navigator";

export class AttributionComponent extends Component<ComponentConfiguration> {
public static componentName: string = "attribution";
private _disposable: Subscription;

constructor(name: string, container: Container, navigator: Navigator) {
super(name, container, navigator);
}

protected _activate(): void {
this._disposable = observableCombineLatest(
this._subscriptions.push(observableCombineLatest(
this._navigator.stateService.currentNode$,
this._container.renderService.size$).pipe(
map(
Expand All @@ -36,11 +32,11 @@ export class AttributionComponent extends Component<ComponentConfiguration> {
vnode: this._getAttributionNode(node.creatorUsername, node.id, node.capturedAt, size.width),
};
}))
.subscribe(this._container.domRenderer.render$);
.subscribe(this._container.domRenderer.render$));
}

protected _deactivate(): void {
this._disposable.unsubscribe();
this._subscriptions.unsubscribe();
}

protected _getDefaultConfiguration(): ComponentConfiguration {
Expand Down
64 changes: 31 additions & 33 deletions src/component/bearing/BearingComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
combineLatest as observableCombineLatest,
Observable,
Subject,
Subscription,
} from "rxjs";

import {
Expand Down Expand Up @@ -34,6 +33,7 @@ import { ComponentSize } from "../utils/ComponentSize";
import { Container } from "../../viewer/Container";
import { Navigator } from "../../viewer/Navigator";
import { isSpherical } from "../../geo/Geo";
import { SubscriptionHolder } from "../../utils/SubscriptionHolder";

type NodeFov = [number, number];

Expand Down Expand Up @@ -73,10 +73,7 @@ export class BearingComponent extends Component<BearingConfiguration> {
private _animationSpeed: number;
private _unitBezier: UnitBezier;

private _renderSubscription: Subscription;
private _fovSubscription: Subscription;
private _fovAnimationSubscription: Subscription;

/** @ignore */
constructor(name: string, container: Container, navigator: Navigator) {
super(name, container, navigator);

Expand All @@ -91,23 +88,26 @@ export class BearingComponent extends Component<BearingConfiguration> {
}

protected _activate(): void {
const cameraBearingFov$: Observable<[number, number]> = this._container.renderService.renderCamera$.pipe(
map(
(rc: RenderCamera): [number, number] => {
let vFov: number = this._spatial.degToRad(rc.perspective.fov);
let hFov: number = rc.perspective.aspect === Number.POSITIVE_INFINITY ?
Math.PI :
Math.atan(rc.perspective.aspect * Math.tan(0.5 * vFov)) * 2;
const subs = this._subscriptions;

return [this._spatial.azimuthalToBearing(rc.rotation.phi), hFov];
}),
distinctUntilChanged(
(a1: [number, number], a2: [number, number]): boolean => {
return Math.abs(a2[0] - a1[0]) < this._distinctThreshold &&
Math.abs(a2[1] - a1[1]) < this._distinctThreshold;
}));
const cameraBearingFov$ =
this._container.renderService.renderCamera$.pipe(
map(
(rc: RenderCamera): [number, number] => {
let vFov: number = this._spatial.degToRad(rc.perspective.fov);
let hFov: number = rc.perspective.aspect === Number.POSITIVE_INFINITY ?
Math.PI :
Math.atan(rc.perspective.aspect * Math.tan(0.5 * vFov)) * 2;

return [this._spatial.azimuthalToBearing(rc.rotation.phi), hFov];
}),
distinctUntilChanged(
(a1: [number, number], a2: [number, number]): boolean => {
return Math.abs(a2[0] - a1[0]) < this._distinctThreshold &&
Math.abs(a2[1] - a1[1]) < this._distinctThreshold;
}));

const nodeFov$: Observable<NodeFov> = observableCombineLatest(
const nodeFov$ = observableCombineLatest(
this._navigator.stateService.currentState$.pipe(
distinctUntilChanged(
undefined,
Expand Down Expand Up @@ -150,7 +150,7 @@ export class BearingComponent extends Component<BearingConfiguration> {
Math.abs(hFovRight2 - hFovRight1) < this._distinctThreshold;
}));

const offset$: Observable<number> = observableCombineLatest(
const offset$ = observableCombineLatest(
this._navigator.stateService.currentState$.pipe(
distinctUntilChanged(
undefined,
Expand All @@ -165,9 +165,9 @@ export class BearingComponent extends Component<BearingConfiguration> {
return offset;
}));

const nodeFovOperation$: Subject<NodeFovOperation> = new Subject<NodeFovOperation>();
const nodeFovOperation$ = new Subject<NodeFovOperation>();

const smoothNodeFov$: Observable<NodeFov> = nodeFovOperation$.pipe(
const smoothNodeFov$ = nodeFovOperation$.pipe(
scan(
(state: NodeFovState, operation: NodeFovOperation): NodeFovState => {
return operation(state);
Expand All @@ -185,7 +185,7 @@ export class BearingComponent extends Component<BearingConfiguration> {
];
}));

this._fovSubscription = nodeFov$.pipe(
subs.push(nodeFov$.pipe(
map(
(nbf: NodeFov): NodeFovOperation => {
return (state: NodeFovState): NodeFovState => {
Expand All @@ -207,9 +207,9 @@ export class BearingComponent extends Component<BearingConfiguration> {
};
};
}))
.subscribe(nodeFovOperation$);
.subscribe(nodeFovOperation$));

this._fovAnimationSubscription = nodeFov$.pipe(
subs.push(nodeFov$.pipe(
switchMap(
(): Observable<number> => {
return this._container.renderService.renderCameraFrame$.pipe(
Expand Down Expand Up @@ -238,17 +238,17 @@ export class BearingComponent extends Component<BearingConfiguration> {
};
};
}))
.subscribe(nodeFovOperation$);
.subscribe(nodeFovOperation$));

const nodeBearingFov$: Observable<NodeBearingFov> = observableCombineLatest(
const nodeBearingFov$ = observableCombineLatest(
offset$,
smoothNodeFov$).pipe(
map(
([offset, fov]: [number, NodeFov]): NodeBearingFov => {
return [offset, fov[0], fov[1]];
}));

this._renderSubscription = observableCombineLatest(
subs.push(observableCombineLatest(
cameraBearingFov$,
nodeBearingFov$,
this._configuration$,
Expand Down Expand Up @@ -280,13 +280,11 @@ export class BearingComponent extends Component<BearingConfiguration> {
]),
};
}))
.subscribe(this._container.domRenderer.render$);
.subscribe(this._container.domRenderer.render$));
}

protected _deactivate(): void {
this._renderSubscription.unsubscribe();
this._fovSubscription.unsubscribe();
this._fovAnimationSubscription.unsubscribe();
this._subscriptions.unsubscribe();
}

protected _getDefaultConfiguration(): BearingConfiguration {
Expand Down
Loading