diff --git a/client/src/map/map.ts b/client/src/map/map.ts index b82feb05..7f4d641d 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -102,8 +102,6 @@ export class Map extends L.Map { constructor(ID: string){ /* Init the leaflet map */ super(ID, { - zoomSnap: 0, - zoomDelta: 0.25, preferCanvas: true, doubleClickZoom: false, zoomControl: false, diff --git a/client/src/map/rangecircle.ts b/client/src/map/rangecircle.ts new file mode 100644 index 00000000..2fa5d9b1 --- /dev/null +++ b/client/src/map/rangecircle.ts @@ -0,0 +1,56 @@ +// @ts-nocheck +// This is a horrible hack. But it is needed at the moment to ovveride a default behaviour of Leaflet. TODO please fix me the proper way. + +import { Circle, Point, Polyline } from 'leaflet'; + +/** + * This custom Circle object implements a faster render method for very big circles. When zoomed in, the default ctx.arc method + * is very slow since the circle is huge. Also, when zoomed in most of the circle points will be outside the screen and not needed. This + * simpler, faster renderer approximates the circle with line segements and only draws those currently visibile. + * A more refined version using arcs could be implemented but this works good enough. + */ +export class RangeCircle extends Circle { + _updatePath() { + if (!this._renderer._drawing || this._empty()) { return; } + var p = this._point, + ctx = this._renderer._ctx, + r = Math.max(Math.round(this._radius), 1), + s = (Math.max(Math.round(this._radiusY), 1) || r) / r; + + if (s !== 1) { + ctx.save(); + ctx.scale(1, s); + } + + let pathBegun = false; + let dtheta = Math.PI * 2 / 120; + for (let theta = 0; theta <= Math.PI * 2; theta += dtheta) { + let p1 = new Point(p.x + r * Math.cos(theta), p.y / s + r * Math.sin(theta)); + let p2 = new Point(p.x + r * Math.cos(theta + dtheta), p.y / s + r * Math.sin(theta + dtheta)); + let l1 = this._map.layerPointToLatLng(p1); + let l2 = this._map.layerPointToLatLng(p2); + let line = new Polyline([l1, l2]); + if (this._map.getBounds().intersects(line.getBounds())) { + if (!pathBegun) { + ctx.beginPath(); + ctx.moveTo(p1.x, p1.y); + pathBegun = true; + } + ctx.lineTo(p2.x, p2.y); + } + else { + if (pathBegun) { + this._renderer._fillStroke(ctx, this); + pathBegun = false; + } + } + } + + if (pathBegun) + this._renderer._fillStroke(ctx, this); + + if (s !== 1) + ctx.restore(); + + } +} \ No newline at end of file diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts index 47968e04..7f81f3f6 100644 --- a/client/src/unit/unit.ts +++ b/client/src/unit/unit.ts @@ -11,6 +11,7 @@ import { groundUnitDatabase } from './databases/groundunitdatabase'; import { navyUnitDatabase } from './databases/navyunitdatabase'; import { Weapon } from '../weapon/weapon'; import { Ammo, Contact, GeneralSettings, LoadoutBlueprint, ObjectIconOptions, Offset, Radio, TACAN, UnitData } from '../interfaces'; +import { RangeCircle } from "../map/rangecircle"; var pathIcon = new Icon({ iconUrl: '/resources/theme/images/markers/marker-icon.png', @@ -97,8 +98,8 @@ export class Unit extends CustomMarker { #pathMarkers: Marker[] = []; #pathPolyline: Polyline; #contactsPolylines: Polyline[] = []; - #engagementCircle: Circle; - #acquisitionCircle: Circle; + #engagementCircle: RangeCircle; + #acquisitionCircle: RangeCircle; #miniMapMarker: CircleMarker | null = null; #targetPositionMarker: TargetMarker; #targetPositionPolyline: Polyline; @@ -167,8 +168,8 @@ export class Unit extends CustomMarker { this.#pathPolyline.addTo(getApp().getMap()); this.#targetPositionMarker = new TargetMarker(new LatLng(0, 0)); this.#targetPositionPolyline = new Polyline([], { color: '#FF0000', weight: 3, opacity: 0.5, smoothFactor: 1 }); - this.#engagementCircle = new Circle(this.getPosition(), { radius: 0, weight: 4, opacity: 1, fillOpacity: 0, dashArray: "4 8", interactive: false, bubblingMouseEvents: false }); - this.#acquisitionCircle = new Circle(this.getPosition(), { radius: 0, weight: 2, opacity: 1, fillOpacity: 0, dashArray: "8 12", interactive: false, bubblingMouseEvents: false }); + this.#engagementCircle = new RangeCircle(this.getPosition(), { radius: 0, weight: 4, opacity: 1, fillOpacity: 0, dashArray: "4 8", interactive: false, bubblingMouseEvents: false }); + this.#acquisitionCircle = new RangeCircle(this.getPosition(), { radius: 0, weight: 2, opacity: 1, fillOpacity: 0, dashArray: "8 12", interactive: false, bubblingMouseEvents: false }); this.on('click', (e) => this.#onClick(e)); this.on('dblclick', (e) => this.#onDoubleClick(e)); @@ -225,7 +226,7 @@ export class Unit extends CustomMarker { case DataIndexes.alive: this.setAlive(dataExtractor.extractBool()); updateMarker = true; break; case DataIndexes.human: this.#human = dataExtractor.extractBool(); break; case DataIndexes.controlled: this.#controlled = dataExtractor.extractBool(); updateMarker = true; break; - case DataIndexes.coalition: this.#coalition = enumToCoalition(dataExtractor.extractUInt8()); updateMarker = true; this.#clearRanges(); break; + case DataIndexes.coalition: let newCoalition = enumToCoalition(dataExtractor.extractUInt8()); updateMarker = true; if (newCoalition != this.#coalition) this.#clearRanges(); this.#coalition = newCoalition; break; case DataIndexes.country: this.#country = dataExtractor.extractUInt8(); break; case DataIndexes.name: this.#name = dataExtractor.extractString(); break; case DataIndexes.unitName: this.#unitName = dataExtractor.extractString(); break; @@ -1342,8 +1343,9 @@ export class Unit extends CustomMarker { } }) - if (acquisitionRange !== this.#acquisitionCircle.getRadius()) + if (acquisitionRange !== this.#acquisitionCircle.getRadius()) { this.#acquisitionCircle.setRadius(acquisitionRange); + } if (engagementRange !== this.#engagementCircle.getRadius()) this.#engagementCircle.setRadius(engagementRange); @@ -1368,7 +1370,8 @@ export class Unit extends CustomMarker { break; } } - this.#acquisitionCircle.setLatLng(this.getPosition()); + if (this.getPosition() != this.#acquisitionCircle.getLatLng()) + this.#acquisitionCircle.setLatLng(this.getPosition()); } else { if (getApp().getMap().hasLayer(this.#acquisitionCircle)) @@ -1392,7 +1395,8 @@ export class Unit extends CustomMarker { break; } } - this.#engagementCircle.setLatLng(this.getPosition()); + if (this.getPosition() != this.#engagementCircle.getLatLng()) + this.#engagementCircle.setLatLng(this.getPosition()); } else { if (getApp().getMap().hasLayer(this.#engagementCircle))