nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

MeasuredLine.js (5340B)


      1 import L from 'leaflet';
      2 import '~/lib/leaflet.polyline-measure';
      3 
      4 L.Polyline.include({
      5         _printProgressWeight: 0.1,
      6         printWidthMm: 1,
      7 
      8         cloneForPrint: function(options) {
      9             options = L.Util.extend({}, this.options, options);
     10             const latlngs = this.getLatLngs().map((latlng) => latlng.clone());
     11             return new L.Polyline(latlngs, options);
     12         },
     13 
     14         _makelatLngToCanvasPixelTransformer: function(printOptions, shift) {
     15             const projectedBounds = printOptions.pixelBounds;
     16             const scale = projectedBounds.getSize().unscaleBy(printOptions.destPixelSize);
     17             const origin = projectedBounds.min;
     18             return function(latlng) {
     19                 return L.CRS.EPSG3857.latLngToPoint(latlng, printOptions.zoom)
     20                     .subtract(origin)
     21                     .add(L.point([shift, 0]))
     22                     .unscaleBy(scale);
     23             };
     24         },
     25 
     26         _shift: function(targetBounds, zoom) {
     27             const polylineBounds = this.getBounds();
     28             let shift = 0;
     29             const worldWidth = L.CRS.EPSG3857.getProjectedBounds(zoom).getSize().x;
     30             if (polylineBounds.isValid()) {
     31                 const polylineCenter = polylineBounds.getCenter();
     32                 const targetCenter = targetBounds.getCenter();
     33 
     34                 if (polylineCenter.lng < targetCenter.lng - 180) {
     35                     shift = 1;
     36                 } else if (polylineCenter.lng > targetCenter.lng + 180) {
     37                     shift = -1;
     38                 } else {
     39                     shift = 0;
     40                 }
     41             }
     42             return {lng: shift * 360, projected: worldWidth * shift};
     43         },
     44 
     45         _drawRaster: function(canvas, printOptions) {
     46             const latlngs = this.getLatLngs();
     47             const shift = this._shift(printOptions.latLngBounds, printOptions.zoom);
     48             const lineBounds = this.getBounds();
     49             if (latlngs.length < 2) {
     50                 return false;
     51             }
     52             const shiftedLineBounds = L.latLngBounds([
     53                 [lineBounds.getNorth(), lineBounds.getWest() + shift.lng],
     54                 [lineBounds.getSouth(), lineBounds.getEast() + shift.lng]
     55             ]);
     56             if (!shiftedLineBounds.intersects(printOptions.latLngBounds)) {
     57                 return false;
     58             }
     59 
     60             const ctx = canvas.getContext('2d');
     61             ctx.lineWidth = this.printWidthMm / 25.4 * printOptions.resolution;
     62             ctx.lineJoin = 'round';
     63             ctx.lineCap = 'round';
     64             ctx.strokeStyle = this.options.color;
     65             const transform = this._makelatLngToCanvasPixelTransformer(printOptions, shift.projected);
     66             let point;
     67             ctx.beginPath();
     68 
     69             point = transform(latlngs[0]);
     70             ctx.moveTo(point.x, point.y);
     71             for (let i = 1; i < latlngs.length; i++) {
     72                 point = transform(latlngs[i]);
     73                 ctx.lineTo(point.x, point.y);
     74             }
     75             ctx.stroke();
     76             return true;
     77         },
     78 
     79         getTilesInfo: async function(printOptions) {
     80             return {
     81                 iterateTilePromises: (function*() {
     82                     yield {
     83                         tilePromise: Promise.resolve({
     84                                 draw: (canvas) => this._drawRaster(canvas, printOptions),
     85                                 isOverlay: true
     86                             }
     87                         ),
     88                         abortLoading: () => {
     89                             // no actions needed
     90                         }
     91                     };
     92                 }).bind(this),
     93                 count: 1
     94             };
     95         }
     96     }
     97 );
     98 
     99 L.MeasuredLine.include({
    100         tickFontSizeMm: 2.5,
    101 
    102         cloneForPrint: function(options) {
    103             options = L.Util.extend({}, this.options, options);
    104             const latlngs = this.getLatLngs().map((latlng) => latlng.clone());
    105             return new L.MeasuredLine(latlngs, options);
    106         },
    107 
    108         _drawRaster: function(canvas, printOptions) {
    109             if (!L.Polyline.prototype._drawRaster.call(this, canvas, printOptions)) {
    110                 return;
    111             }
    112             if (!this.options.measureTicksShown) {
    113                 return;
    114             }
    115             const minTicksIntervalMeters = printOptions.scale * 1.5;
    116             const ctx = canvas.getContext('2d');
    117             const ticks = this.getTicksPositions(minTicksIntervalMeters);
    118             const ticksPixelSize = this.tickFontSizeMm / 25.4 * printOptions.resolution;
    119             const shift = this._shift(printOptions.latLngBounds, printOptions.zoom);
    120             const transform = this._makelatLngToCanvasPixelTransformer(printOptions, shift.projected);
    121             ctx.font = `bold ${ticksPixelSize}px verdana`;
    122             ctx.fillStyle = this.options.color;
    123             for (let tick of ticks) {
    124                 let m = tick.transformMatrix;
    125                 let label = '\u2501\u2501 ' + Math.round((tick.distanceValue / 10)) / 100 + ' km';
    126                 let position = transform(tick.position);
    127                 ctx.setTransform(m[0], m[1], m[2], m[3], position.x, position.y);
    128                 ctx.fillText(label, 0, ticksPixelSize * 0.3);
    129                 ctx.setTransform(1, 0, 0, 1, 0, 0);
    130             }
    131         }
    132     }
    133 );