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
13 changes: 13 additions & 0 deletions src/base-gl-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ export interface IBaseGlLayerSettings {
};
setupClick?: (map: Map) => void;
setupContextMenu?: (map: Map) => void;
setupDblClick?: (map: Map) => void;
setupHover?: SetupHoverCallback;
sensitivity?: number;
sensitivityHover?: number;
vertexShaderSource?: (() => string) | string;
fragmentShaderSource?: (() => string) | string;
canvas?: HTMLCanvasElement;
click?: EventCallback;
dblClick?: EventCallback;
contextMenu?: EventCallback;
hover?: EventCallback;
hoverOff?: EventCallback;
Expand Down Expand Up @@ -237,6 +239,9 @@ export abstract class BaseGlLayer<
if (settings.click && settings.setupClick) {
settings.setupClick(this.map);
}
if (settings.dblClick && settings.setupDblClick) {
settings.setupDblClick(this.map);
}
if (settings.contextMenu && settings.setupContextMenu) {
settings.setupContextMenu(this.map);
}
Expand Down Expand Up @@ -422,6 +427,14 @@ export abstract class BaseGlLayer<
}
}

dblClick(e: LeafletMouseEvent, feature: any): boolean | undefined {
if (!this.settings.dblClick) return;
const result = this.settings.dblClick(e, feature);
if (result !== undefined) {
return result;
}
}

contextMenu(e: LeafletMouseEvent, feature: any): boolean | undefined {
if (!this.settings.contextMenu) return;
const result = this.settings.contextMenu(e, feature);
Expand Down
20 changes: 20 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class Glify {
longitudeKey = 1;
latitudeKey = 0;
clickSetupMaps: Map[] = [];
dblClickSetupMaps: Map[] = [];
contextMenuSetupMaps: Map[] = [];
hoverSetupMaps: Map[] = [];
shader = shader;
Expand Down Expand Up @@ -64,6 +65,7 @@ export class Glify {
points(settings: Partial<IPointsSettings>): Points {
const points = new this.Points({
setupClick: this.setupClick.bind(this),
setupDblClick: this.setupDblClick.bind(this),
setupContextMenu: this.setupContextMenu.bind(this),
setupHover: this.setupHover.bind(this),
latitudeKey: glify.latitudeKey,
Expand All @@ -83,6 +85,7 @@ export class Glify {
lines(settings: Partial<ILinesSettings>): Lines {
const lines = new this.Lines({
setupClick: this.setupClick.bind(this),
setupDblClick: this.setupDblClick.bind(this),
setupContextMenu: this.setupContextMenu.bind(this),
setupHover: this.setupHover.bind(this),
latitudeKey: this.latitudeKey,
Expand All @@ -102,6 +105,7 @@ export class Glify {
shapes(settings: Partial<IShapesSettings>): Shapes {
const shapes = new this.Shapes({
setupClick: this.setupClick.bind(this),
setupDblClick: this.setupDblClick.bind(this),
setupContextMenu: this.setupContextMenu.bind(this),
setupHover: this.setupHover.bind(this),
latitudeKey: this.latitudeKey,
Expand Down Expand Up @@ -134,6 +138,22 @@ export class Glify {
});
}

setupDblClick(map: Map): void {
if (this.dblClickSetupMaps.includes(map)) return;
this.dblClickSetupMaps.push(map);
map.on("dblclick", (e: LeafletMouseEvent) => {
let hit;
hit = this.Points.tryDblClick(e, map, this.pointsInstances);
if (hit !== undefined) return hit;

hit = this.Lines.tryDblClick(e, map, this.linesInstances);
if (hit !== undefined) return hit;

hit = this.Shapes.tryDblClick(e, map, this.shapesInstances);
if (hit !== undefined) return hit;
})
}

setupContextMenu(map: Map): void {
if (this.contextMenuSetupMaps.includes(map)) return;
this.clickSetupMaps.push(map);
Expand Down
83 changes: 83 additions & 0 deletions src/lines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,89 @@ export class Lines extends BaseGlLayer<ILinesSettings> {
}
}

// attempts to double click the top-most Lines instance
static tryDblClick(
e: LeafletMouseEvent,
map: Map,
instances: Lines[]
): boolean | undefined {
let foundFeature: Feature<LineString | MultiLineString> | null = null;
let foundLines: Lines | null = null;

instances.forEach((instance: Lines): void => {
const { latitudeKey, longitudeKey, sensitivity, weight, scale, active } =
instance;
if (!active) return;
if (instance.map !== map) return;
function checkClick(
coordinate: Position,
prevCoordinate: Position,
feature: Feature<LineString | MultiLineString>,
chosenWeight: number
): void {
const distance = latLngDistance(
e.latlng.lng,
e.latlng.lat,
prevCoordinate[longitudeKey],
prevCoordinate[latitudeKey],
coordinate[longitudeKey],
coordinate[latitudeKey]
);
if (distance <= sensitivity + chosenWeight / scale) {
foundFeature = feature;
foundLines = instance;
}
}
instance.data.features.forEach(
(feature: Feature<LineString | MultiLineString>, i: number): void => {
const chosenWeight =
typeof weight === "function" ? weight(i, feature) : weight;
const { coordinates, type } = feature.geometry;
if (type === "LineString") {
for (let i = 1; i < coordinates.length; i++) {
checkClick(
coordinates[i] as Position,
coordinates[i - 1] as Position,
feature,
chosenWeight
);
}
} else if (type === "MultiLineString") {
// TODO: Unit test
for (let i = 0; i < coordinates.length; i++) {
const coordinate = coordinates[i];
for (let j = 0; j < coordinate.length; j++) {
if (j === 0 && i > 0) {
const prevCoordinates = coordinates[i - 1];
const lastPositions =
prevCoordinates[prevCoordinates.length - 1];
checkClick(
lastPositions as Position,
coordinates[i][j] as Position,
feature,
chosenWeight
);
} else if (j > 0) {
checkClick(
coordinates[i][j] as Position,
coordinates[i][j - 1] as Position,
feature,
chosenWeight
);
}
}
}
}
}
);
});

if (foundLines && foundFeature) {
const result = (foundLines as Lines).dblClick(e, foundFeature);
return result !== undefined ? result : undefined;
}
}

// attempts to click the top-most Lines instance
static tryContextMenu(
e: LeafletMouseEvent,
Expand Down
44 changes: 44 additions & 0 deletions src/points.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,50 @@ export class Points extends BaseGlLayer<IPointsSettings> {
}
}

// attempts to click the top-most Points instance
static tryDblClick(
e: LeafletMouseEvent,
map: Map,
instances: Points[]
): boolean | undefined {
const closestFromEach: IPointVertex[] = [];
const instancesLookup: { [key: string]: Points } = {};
let result;
let settings: Partial<IPointsSettings> | null = null;
let pointLookup: IPointVertex | null;

instances.forEach((_instance: Points) => {
settings = _instance.settings;
if (!_instance.active) return;
if (_instance.map !== map) return;

pointLookup = _instance.lookup(e.latlng);
if (pointLookup === null) return;
instancesLookup[pointLookup.key] = _instance;
closestFromEach.push(pointLookup);
});

if (closestFromEach.length < 1) return;
if (!settings) return;

const found = this.closest(e.latlng, closestFromEach, map);

if (!found) return;

const instance = instancesLookup[found.key];
if (!instance) return;
const { sensitivity } = instance;
const foundLatLng = found.latLng;
const xy = map.latLngToLayerPoint(foundLatLng);

if (
pixelInCircle(xy, e.layerPoint, found.chosenSize * (sensitivity ?? 1))
) {
result = instance.dblClick(e, found.feature || found.latLng);
return result !== undefined ? result : true;
}
}

// attempts to click the top-most Points instance
static tryContextMenu(
e: LeafletMouseEvent,
Expand Down
29 changes: 29 additions & 0 deletions src/shapes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,35 @@ export class Shapes extends BaseGlLayer {
}
}

// attempts to double click the top-most Shapes instance
static tryDblClick(
e: LeafletMouseEvent,
map: Map,
instances: Shapes[]
): boolean | undefined {
let foundPolygon: Feature<Polygon, GeoJsonProperties> | null = null;
let foundShapes: Shapes | null = null;
instances.forEach(function (_instance: Shapes): void {
if (!_instance.active) return;
if (_instance.map !== map) return;
if (!_instance.polygonLookup) return;

const polygon = _instance.polygonLookup.search(
e.latlng.lng,
e.latlng.lat
);
if (polygon) {
foundShapes = _instance;
foundPolygon = polygon;
}
});

if (foundShapes && foundPolygon) {
const result = (foundShapes as Shapes).dblClick(e, foundPolygon);
return result !== undefined ? result : undefined;
}
}

// attempts to click the top-most Shapes instance
static tryContextMenu(
e: LeafletMouseEvent,
Expand Down