Skip to content
Open
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
66 changes: 21 additions & 45 deletions lib/Map/Leaflet/ImageryProviderLeafletGridLayer.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import L from "leaflet";
import {
autorun,
computed,
IReactionDisposer,
observable,
makeObservable
} from "mobx";
import { autorun, IReactionDisposer, observable, makeObservable } from "mobx";
import Cartographic from "terriajs-cesium/Source/Core/Cartographic";
import CesiumEvent from "terriajs-cesium/Source/Core/Event";
import CesiumMath from "terriajs-cesium/Source/Core/Math";
import SplitDirection from "terriajs-cesium/Source/Scene/SplitDirection";
import Leaflet from "../../Models/Leaflet";
import ImageryProvider from "terriajs-cesium/Source/Scene/ImageryProvider";
import getClipsForSplitter from "./getClipsForSplitter";

export interface ImageryProviderWithGridLayerSupport extends ImageryProvider {
requestImageForCanvas: (
Expand Down Expand Up @@ -70,50 +65,31 @@ export default class ImageryProviderLeafletGridLayer extends L.GridLayer {
return;
}

if (
this.splitDirection === SplitDirection.NONE ||
!this.leaflet.size ||
!this.leaflet.nw ||
!this.leaflet.se
) {
container.style.clipPath = "none";
return;
}

const clips = getClipsForSplitter({
size: this.leaflet.size,
nw: this.leaflet.nw,
se: this.leaflet.se,
splitPosition: this.splitPosition
});

if (this.splitDirection === SplitDirection.LEFT) {
const { left: clipLeft } = this._clipsForSplitter;
container.style.clip = clipLeft;
} else if (this.splitDirection === SplitDirection.RIGHT) {
const { right: clipRight } = this._clipsForSplitter;
container.style.clip = clipRight;
container.style.clipPath = clips.left;
} else {
container.style.clip = "auto";
container.style.clipPath = clips.right;
}
});
}

@computed
get _clipsForSplitter() {
let clipLeft = "";
let clipRight = "";
let clipPositionWithinMap;
let clipX;

if (this.leaflet.size && this.leaflet.nw && this.leaflet.se) {
clipPositionWithinMap = this.leaflet.size.x * this.splitPosition;
clipX = Math.round(this.leaflet.nw.x + clipPositionWithinMap);
clipLeft =
"rect(" +
[this.leaflet.nw.y, clipX, this.leaflet.se.y, this.leaflet.nw.x].join(
"px,"
) +
"px)";
clipRight =
"rect(" +
[this.leaflet.nw.y, this.leaflet.se.x, this.leaflet.se.y, clipX].join(
"px,"
) +
"px)";
}

return {
left: clipLeft,
right: clipRight,
clipPositionWithinMap: clipPositionWithinMap,
clipX: clipX
};
}

createTile(tilePoint: L.Coords, done: L.DoneCallback) {
const canvas = L.DomUtil.create(
"canvas",
Expand Down
65 changes: 21 additions & 44 deletions lib/Map/Leaflet/ImageryProviderLeafletTileLayer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import i18next from "i18next";
import L, { TileEvent } from "leaflet";
import {
autorun,
computed,
IReactionDisposer,
observable,
makeObservable
} from "mobx";
import { autorun, IReactionDisposer, observable, makeObservable } from "mobx";
import Cartesian2 from "terriajs-cesium/Source/Core/Cartesian2";
import Cartographic from "terriajs-cesium/Source/Core/Cartographic";
import CesiumCredit from "terriajs-cesium/Source/Core/Credit";
Expand All @@ -21,6 +15,7 @@ import SplitDirection from "terriajs-cesium/Source/Scene/SplitDirection";
import isDefined from "../../Core/isDefined";
import TerriaError from "../../Core/TerriaError";
import Leaflet from "../../Models/Leaflet";
import getClipsForSplitter from "./getClipsForSplitter";
import getUrlForImageryTile from "../ImageryProvider/getUrlForImageryTile";
import { ProviderCoords } from "../PickedFeatures/PickedFeatures";

Expand Down Expand Up @@ -97,49 +92,31 @@ export default class ImageryProviderLeafletTileLayer extends L.TileLayer {
return;
}

if (
this.splitDirection === SplitDirection.NONE ||
!this.leaflet.size ||
!this.leaflet.nw ||
!this.leaflet.se
) {
container.style.clipPath = "none";
return;
}

const clips = getClipsForSplitter({
size: this.leaflet.size,
nw: this.leaflet.nw,
se: this.leaflet.se,
splitPosition: this.splitPosition
});

if (this.splitDirection === SplitDirection.LEFT) {
const { left: clipLeft } = this._clipsForSplitter;
container.style.clip = clipLeft;
} else if (this.splitDirection === SplitDirection.RIGHT) {
const { right: clipRight } = this._clipsForSplitter;
container.style.clip = clipRight;
container.style.clipPath = clips.left;
} else {
container.style.clip = "auto";
container.style.clipPath = clips.right;
}
});
}

@computed
get _clipsForSplitter() {
let clipLeft = "";
let clipRight = "";
let clipPositionWithinMap;
let clipX;

if (this.leaflet.size && this.leaflet.nw && this.leaflet.se) {
clipPositionWithinMap = this.leaflet.size.x * this.splitPosition;
clipX = Math.round(this.leaflet.nw.x + clipPositionWithinMap);
clipLeft =
"rect(" +
[this.leaflet.nw.y, clipX, this.leaflet.se.y, this.leaflet.nw.x].join(
"px,"
) +
"px)";
clipRight =
"rect(" +
[this.leaflet.nw.y, this.leaflet.se.x, this.leaflet.se.y, clipX].join(
"px,"
) +
"px)";
}
return {
left: clipLeft,
right: clipRight,
clipPositionWithinMap: clipPositionWithinMap,
clipX: clipX
};
}

_tileOnError(_done: unknown, _tile: unknown, _e: unknown) {
// Do nothing, we'll handle tile errors separately.
}
Expand Down
82 changes: 74 additions & 8 deletions lib/Map/Leaflet/LeafletVisualizer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import L, { LatLngBounds, LatLngBoundsLiteral, PolylineOptions } from "leaflet";
import { autorun, IReactionDisposer, makeObservable, observable } from "mobx";
import AssociativeArray from "terriajs-cesium/Source/Core/AssociativeArray";
import Cartesian2 from "terriajs-cesium/Source/Core/Cartesian2";
import Cartesian3 from "terriajs-cesium/Source/Core/Cartesian3";
Expand All @@ -17,8 +18,10 @@ import EntityCollection from "terriajs-cesium/Source/DataSources/EntityCollectio
import PolylineDashMaterialProperty from "terriajs-cesium/Source/DataSources/PolylineDashMaterialProperty";
import PolylineGlowMaterialProperty from "terriajs-cesium/Source/DataSources/PolylineGlowMaterialProperty";
import Property from "terriajs-cesium/Source/DataSources/Property";
import SplitDirection from "terriajs-cesium/Source/Scene/SplitDirection";
import isDefined from "../../Core/isDefined";
import { convertCesiumDashNumberToDashArray } from "../../Models/Catalog/Esri/esriStyleToTableStyle";
import getClipsForSplitter from "./getClipsForSplitter";
import LeafletScene from "./LeafletScene";

interface PointDetails {
Expand Down Expand Up @@ -98,26 +101,45 @@ const tmpImage =
*/
let prevBoundsType = 0;

let paneCounter = 0;

/**
* A {@link Visualizer} which maps {@link Entity#point} to Leaflet primitives.
**/
class LeafletGeomVisualizer {
export class LeafletGeomVisualizer {
private readonly _featureGroup: L.FeatureGroup;
private readonly _entitiesToVisualize: AssociativeArray;
private readonly _entityHash: EntityHash;
private readonly _disposeSplitterReaction: IReactionDisposer;

readonly paneName: string;
readonly paneElement: HTMLElement;

@observable splitDirection: SplitDirection = SplitDirection.NONE;
@observable splitPosition: number = 0.5;

constructor(
readonly leafletScene: LeafletScene,
readonly entityCollection: EntityCollection
) {
makeObservable(this);

this.paneName = `terriajs-geom-visualizer-${paneCounter++}`;
this.paneElement = leafletScene.map.createPane(this.paneName);
this.paneElement.style.zIndex = "500";

entityCollection.collectionChanged.addEventListener(
this._onCollectionChanged,
this
);
this._featureGroup = L.featureGroup().addTo(leafletScene.map);
this._featureGroup = L.featureGroup([], { pane: this.paneName }).addTo(
leafletScene.map
);
this._entitiesToVisualize = new AssociativeArray();
this._entityHash = {};

this._disposeSplitterReaction = this._reactToSplitterChange();

this._onCollectionChanged(
entityCollection,
entityCollection.values,
Expand All @@ -126,6 +148,33 @@ class LeafletGeomVisualizer {
);
}

private _reactToSplitterChange(): IReactionDisposer {
return autorun(() => {
if (this.splitDirection === SplitDirection.NONE) {
this.paneElement.style.clipPath = "none";
return;
}

const map = this.leafletScene.map;
const size = map.getSize();
const nw = map.containerPointToLayerPoint([0, 0]);
const se = map.containerPointToLayerPoint(size);

const clips = getClipsForSplitter({
size,
nw,
se,
splitPosition: this.splitPosition
});

if (this.splitDirection === SplitDirection.LEFT) {
this.paneElement.style.clipPath = clips.left;
} else {
this.paneElement.style.clipPath = clips.right;
}
});
}

private _onCollectionChanged(
_entityCollection: EntityCollection,
added: Entity[],
Expand Down Expand Up @@ -302,7 +351,8 @@ class LeafletGeomVisualizer {
fillOpacity: color.alpha,
color: outlineColor.toCssColorString(),
weight: outlineWidth,
opacity: outlineColor.alpha
opacity: outlineColor.alpha,
pane: this.paneName
};

layer = details.layer = L.circleMarker(
Expand Down Expand Up @@ -445,7 +495,10 @@ class LeafletGeomVisualizer {

let redrawIcon = false;
if (!isDefined(geomLayer)) {
const markerOptions = { icon: L.icon({ iconUrl: tmpImage }) };
const markerOptions = {
icon: L.icon({ iconUrl: tmpImage }),
pane: this.paneName
};
marker = L.marker(latlng, markerOptions);
marker.on("click", featureClicked.bind(undefined, this, entity));
marker.on("mousedown", featureMousedown.bind(undefined, this, entity));
Expand Down Expand Up @@ -574,7 +627,10 @@ class LeafletGeomVisualizer {

let redrawLabel = false;
if (!isDefined(geomLayer)) {
const markerOptions = { icon: L.icon({ iconUrl: tmpImage }) };
const markerOptions = {
icon: L.icon({ iconUrl: tmpImage }),
pane: this.paneName
};
marker = L.marker(latlng, markerOptions);
marker.on("click", featureClicked.bind(undefined, this, entity));
marker.on("mousedown", featureMousedown.bind(undefined, this, entity));
Expand Down Expand Up @@ -719,7 +775,8 @@ class LeafletGeomVisualizer {
fillOpacity: fillColor.alpha,
weight: outline ? outlineWidth : 0.0,
color: outlineColor.toCssColorString(),
opacity: outlineColor.alpha
opacity: outlineColor.alpha,
pane: this.paneName
};

if (outline && dashArray) {
Expand Down Expand Up @@ -857,7 +914,8 @@ class LeafletGeomVisualizer {
fillOpacity: fillColor.alpha,
weight: outline ? outlineWidth : 0.0,
color: outlineColor.toCssColorString(),
opacity: outlineColor.alpha
opacity: outlineColor.alpha,
pane: this.paneName
};

if (outline && dashArray) {
Expand Down Expand Up @@ -989,7 +1047,8 @@ class LeafletGeomVisualizer {
const polylineOptions: PolylineOptions = {
color: color.toCssColorString(),
weight: width,
opacity: color.alpha
opacity: color.alpha,
pane: this.paneName
};

if (dashArray) {
Expand Down Expand Up @@ -1044,6 +1103,8 @@ class LeafletGeomVisualizer {
* Removes and destroys all primitives created by this instance.
*/
destroy() {
this._disposeSplitterReaction();

const entities = this._entitiesToVisualize.values;
const entityHash = this._entityHash;

Expand All @@ -1056,6 +1117,11 @@ class LeafletGeomVisualizer {
this
);
this.leafletScene.map.removeLayer(this._featureGroup);

if (this.paneElement.parentNode) {
this.paneElement.parentNode.removeChild(this.paneElement);
}

return destroyObject(this);
}

Expand Down
31 changes: 31 additions & 0 deletions lib/Map/Leaflet/getClipsForSplitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
type Point = { readonly x: number; readonly y: number };

type ClipInputs = {
readonly size: Point;
readonly nw: Point;
readonly se: Point;
readonly splitPosition: number;
};

type ClipResult = {
readonly left: string;
readonly right: string;
readonly clipX: number;
};

export default function getClipsForSplitter({
size,
nw,
se,
splitPosition
}: ClipInputs): ClipResult {
const clipX = Math.round(nw.x + size.x * splitPosition);
const left =
`polygon(${nw.x}px ${nw.y}px, ${clipX}px ${nw.y}px, ` +
`${clipX}px ${se.y}px, ${nw.x}px ${se.y}px)`;
const right =
`polygon(${clipX}px ${nw.y}px, ${se.x}px ${nw.y}px, ` +
`${se.x}px ${se.y}px, ${clipX}px ${se.y}px)`;

return { left, right, clipX };
}
Loading