@omnedia/ngx-globe
Version:
A simple component library to create a container with an animated and interactive globe.
215 lines (210 loc) • 11.1 kB
JavaScript
import * as i1 from '@angular/common';
import { isPlatformBrowser, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { PLATFORM_ID, Input, ViewChild, Inject, ChangeDetectionStrategy, Component } from '@angular/core';
import createGlobe from 'cobe';
class NgxGlobeComponent {
cdr;
platformId;
globeWrapperElement;
globeCanvas;
styleClass;
rotationSpeed = 0.005;
set globeOptions(options) {
this.globeSize = options.width ?? this.globeSize;
this.style["--globe-size"] = this.globeSize + "px";
this.setGlobeOptions(options);
if (this.globeInitialized) {
this.setCanvasSize();
this.initGlobe();
}
}
set globeCanvasSize(size) {
this.globeSize = size;
this.cobeOptions.width = this.globeSize;
this.cobeOptions.height = this.globeSize;
this.style["--globe-size"] = size + "px";
if (this.globeInitialized) {
this.setCanvasSize();
this.initGlobe();
}
}
style = {};
globeSize;
globeInitialized = false;
globe;
cobeOptions = {
devicePixelRatio: 2,
width: this.globeSize ?? 600,
height: this.globeSize ?? 600,
phi: 0,
theta: 0.3,
dark: 0,
diffuse: 0.4,
scale: 1,
mapSamples: 16000,
mapBrightness: 1.2,
baseColor: [1, 1, 1],
markerColor: [251 / 255, 100 / 255, 21 / 255],
glowColor: [1, 1, 1],
offset: [0, 0],
markers: [
{ location: [14.5995, 120.9842], size: 0.03 },
{ location: [19.076, 72.8777], size: 0.1 },
{ location: [23.8103, 90.4125], size: 0.05 },
{ location: [30.0444, 31.2357], size: 0.07 },
{ location: [39.9042, 116.4074], size: 0.08 },
{ location: [-23.5505, -46.6333], size: 0.1 },
{ location: [19.4326, -99.1332], size: 0.1 },
{ location: [40.7128, -74.006], size: 0.1 },
{ location: [34.6937, 135.5022], size: 0.05 },
{ location: [41.0082, 28.9784], size: 0.06 },
],
};
pointerInteracting = null;
pointerInteractionMovement = 0;
globeRotation = 0;
intersectionObserver;
isAnimating = false;
constructor(cdr, platformId) {
this.cdr = cdr;
this.platformId = platformId;
}
ngAfterViewInit() {
this.initCanvas();
if (isPlatformBrowser(this.platformId)) {
this.intersectionObserver = new IntersectionObserver(([entry]) => {
this.renderContents(entry.isIntersecting);
});
this.intersectionObserver.observe(this.globeCanvas.nativeElement);
}
}
ngOnDestroy() {
this.globe?.destroy();
window.removeEventListener("resize", () => this.setCanvasSize());
}
initCanvas() {
if (!this.globeSize) {
let width = 600;
let height = 600;
if (this.globeWrapperElement.nativeElement.parentElement?.parentElement) {
const domRect = this.globeWrapperElement.nativeElement.parentElement.parentElement.getBoundingClientRect();
width = domRect.width;
height = domRect.height;
}
this.globeSize = width < height ? width : height;
this.cobeOptions.width = this.globeSize;
this.cobeOptions.height = this.globeSize;
this.style["--globe-size"] = this.globeSize + "px";
}
this.cobeOptions.width = this.globeSize;
this.cobeOptions.height = this.globeSize;
this.setCanvasSize();
this.initGlobe();
}
setCanvasSize() {
this.globeCanvas.nativeElement.width = this.globeSize ?? 600;
this.globeCanvas.nativeElement.height = this.globeSize ?? 600;
this.cdr.detectChanges();
}
renderContents(isIntersecting) {
if (isIntersecting && !this.isAnimating) {
this.isAnimating = true;
this.globe?.toggle(true);
}
else if (!isIntersecting && this.isAnimating) {
this.isAnimating = false;
this.globe?.toggle(false);
}
}
initGlobe() {
let phi = this.cobeOptions.phi;
let cobeOptions = {
...this.cobeOptions,
onRender: (state) => {
if (!this.pointerInteracting) {
phi += this.rotationSpeed;
}
state.phi = phi + this.globeRotation;
},
};
this.globe = createGlobe(this.globeCanvas.nativeElement, cobeOptions);
this.globeInitialized = true;
window.addEventListener("resize", () => this.setCanvasSize());
this.globeCanvas.nativeElement.width = this.globeSize ?? 600;
this.globeCanvas.nativeElement.height = this.globeSize ?? 600;
}
updatePointerInteraction(value) {
this.pointerInteracting = value;
this.globeCanvas.nativeElement.style.cursor = value ? "grabbing" : "grab";
}
updateMovement(clientX) {
if (this.pointerInteracting !== null) {
const delta = clientX - this.pointerInteracting;
this.pointerInteractionMovement = delta;
this.globeRotation = delta / 200;
}
}
setGlobeOptions(options) {
this.cobeOptions.width = options.width ?? this.cobeOptions.width;
this.cobeOptions.height = options.height ?? this.cobeOptions.height;
this.cobeOptions.phi = options.phi ?? this.cobeOptions.phi;
this.cobeOptions.theta = options.theta ?? this.cobeOptions.theta;
this.cobeOptions.mapSamples =
options.mapSamples ?? this.cobeOptions.mapSamples;
this.cobeOptions.mapBrightness =
options.mapBrightness ?? this.cobeOptions.mapBrightness;
this.cobeOptions.mapBaseBrightness =
options.mapBaseBrightness ?? this.cobeOptions.mapBaseBrightness;
this.cobeOptions.baseColor =
options.baseColor ?? this.cobeOptions.baseColor;
this.cobeOptions.markerColor =
options.markerColor ?? this.cobeOptions.markerColor;
this.cobeOptions.glowColor =
options.glowColor ?? this.cobeOptions.glowColor;
this.cobeOptions.markers = options.markers ?? this.cobeOptions.markers;
this.cobeOptions.diffuse = options.diffuse ?? this.cobeOptions.diffuse;
this.cobeOptions.devicePixelRatio =
options.devicePixelRatio ?? this.cobeOptions.devicePixelRatio;
this.cobeOptions.dark = options.dark ?? this.cobeOptions.dark;
this.cobeOptions.opacity = options.opacity ?? this.cobeOptions.opacity;
this.cobeOptions.offset = options.offset ?? this.cobeOptions.offset;
this.cobeOptions.scale = options.scale ?? this.cobeOptions.scale;
this.cobeOptions.context = options.context ?? this.cobeOptions.context;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: NgxGlobeComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.2", type: NgxGlobeComponent, isStandalone: true, selector: "om-globe", inputs: { styleClass: "styleClass", rotationSpeed: "rotationSpeed", globeOptions: "globeOptions", globeCanvasSize: ["globeSize", "globeCanvasSize"] }, viewQueries: [{ propertyName: "globeWrapperElement", first: true, predicate: ["OmGlobeWrapper"], descendants: true }, { propertyName: "globeCanvas", first: true, predicate: ["globeCanvas"], descendants: true }], ngImport: i0, template: "<div class=\"om-globe\" [ngStyle]=\"style\" #OmGlobeWrapper>\r\n <div class=\"om-globe-background\">\r\n <canvas (pointerdown)=\"updatePointerInteraction($event.clientX - pointerInteractionMovement)\"\r\n (pointerup)=\"updatePointerInteraction(null)\" (pointerout)=\"updatePointerInteraction(null)\"\r\n (mousemove)=\"updateMovement($event.clientX)\" (touchmove)=\"updateMovement($event.touches[0].clientX)\"\r\n width=\"1000\" height=\"1000\" #globeCanvas></canvas>\r\n </div>\r\n</div>\r\n", styles: [".om-globe{--globe-size: 600px;position:relative;width:var(--globe-size);height:var(--globe-size);overflow:hidden}.om-globe .om-globe-background{position:absolute;width:100%;max-width:var(--globe-size);aspect-ratio:1/1;margin-left:auto;margin-right:auto;inset:0}.om-globe .om-globe-background canvas{width:100%;height:100%;contain:layout paint size;opacity:1;cursor:grab}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: NgxGlobeComponent, decorators: [{
type: Component,
args: [{ selector: "om-globe", standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"om-globe\" [ngStyle]=\"style\" #OmGlobeWrapper>\r\n <div class=\"om-globe-background\">\r\n <canvas (pointerdown)=\"updatePointerInteraction($event.clientX - pointerInteractionMovement)\"\r\n (pointerup)=\"updatePointerInteraction(null)\" (pointerout)=\"updatePointerInteraction(null)\"\r\n (mousemove)=\"updateMovement($event.clientX)\" (touchmove)=\"updateMovement($event.touches[0].clientX)\"\r\n width=\"1000\" height=\"1000\" #globeCanvas></canvas>\r\n </div>\r\n</div>\r\n", styles: [".om-globe{--globe-size: 600px;position:relative;width:var(--globe-size);height:var(--globe-size);overflow:hidden}.om-globe .om-globe-background{position:absolute;width:100%;max-width:var(--globe-size);aspect-ratio:1/1;margin-left:auto;margin-right:auto;inset:0}.om-globe .om-globe-background canvas{width:100%;height:100%;contain:layout paint size;opacity:1;cursor:grab}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }], propDecorators: { globeWrapperElement: [{
type: ViewChild,
args: ["OmGlobeWrapper"]
}], globeCanvas: [{
type: ViewChild,
args: ["globeCanvas"]
}], styleClass: [{
type: Input,
args: ["styleClass"]
}], rotationSpeed: [{
type: Input,
args: ["rotationSpeed"]
}], globeOptions: [{
type: Input,
args: ["globeOptions"]
}], globeCanvasSize: [{
type: Input,
args: ["globeSize"]
}] } });
/*
* Public API Surface of ngx-globe
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgxGlobeComponent };
//# sourceMappingURL=omnedia-ngx-globe.mjs.map