Merge pull request #13171 from mike-000/4326-scale-bar
Correct scale bar in EPSG:4326
This commit is contained in:
18
examples/projection-and-scale.html
Normal file
18
examples/projection-and-scale.html
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Projection and Scale
|
||||
shortdesc: Example of maintaining scale when changing projection.
|
||||
docs: >
|
||||
Example of maintaining scale when changing projection.
|
||||
`getPointResolution()` is used to calculate the resolution for the
|
||||
new projection which corresponds to that for the old projection.
|
||||
tags: "projection, scale"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
<div>
|
||||
<label for="view-projection">View projection</label>
|
||||
<select id="view-projection">
|
||||
<option value="EPSG:3857">Spherical Mercator (EPSG:3857)</option>
|
||||
<option value="EPSG:4326" selected>WGS 84 (EPSG:4326)</option>
|
||||
</select>
|
||||
</div>
|
||||
68
examples/projection-and-scale.js
Normal file
68
examples/projection-and-scale.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import OSM from '../src/ol/source/OSM.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {ScaleLine, defaults as defaultControls} from '../src/ol/control.js';
|
||||
import {
|
||||
getPointResolution,
|
||||
get as getProjection,
|
||||
transform,
|
||||
} from '../src/ol/proj.js';
|
||||
|
||||
const viewProjSelect = document.getElementById('view-projection');
|
||||
const projection = getProjection(viewProjSelect.value);
|
||||
|
||||
const scaleControl = new ScaleLine({
|
||||
units: 'metric',
|
||||
bar: true,
|
||||
steps: 4,
|
||||
text: true,
|
||||
minWidth: 140,
|
||||
});
|
||||
|
||||
const map = new Map({
|
||||
controls: defaultControls().extend([scaleControl]),
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM(),
|
||||
}),
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: transform([0, 52], 'EPSG:4326', projection),
|
||||
zoom: 6,
|
||||
projection: projection,
|
||||
}),
|
||||
});
|
||||
|
||||
function onChangeProjection() {
|
||||
const currentView = map.getView();
|
||||
const currentProjection = currentView.getProjection();
|
||||
const newProjection = getProjection(viewProjSelect.value);
|
||||
const currentResolution = currentView.getResolution();
|
||||
const currentCenter = currentView.getCenter();
|
||||
const currentRotation = currentView.getRotation();
|
||||
const newCenter = transform(currentCenter, currentProjection, newProjection);
|
||||
const currentPointResolution = getPointResolution(
|
||||
currentProjection,
|
||||
1,
|
||||
currentCenter,
|
||||
'm'
|
||||
);
|
||||
const newPointResolution = getPointResolution(
|
||||
newProjection,
|
||||
1,
|
||||
newCenter,
|
||||
'm'
|
||||
);
|
||||
const newResolution =
|
||||
(currentResolution * currentPointResolution) / newPointResolution;
|
||||
const newView = new View({
|
||||
center: newCenter,
|
||||
resolution: newResolution,
|
||||
rotation: currentRotation,
|
||||
projection: newProjection,
|
||||
});
|
||||
map.setView(newView);
|
||||
}
|
||||
viewProjSelect.addEventListener('change', onChangeProjection);
|
||||
@@ -484,12 +484,12 @@ class ScaleLine extends Control {
|
||||
const resolution = getPointResolution(
|
||||
this.viewState_.projection,
|
||||
this.viewState_.resolution,
|
||||
this.viewState_.center
|
||||
this.viewState_.center,
|
||||
ProjUnits.METERS
|
||||
);
|
||||
const dpi = this.dpi_ || DEFAULT_DPI;
|
||||
const mpu = this.viewState_.projection.getMetersPerUnit();
|
||||
const inchesPerMeter = 1000 / 25.4;
|
||||
return parseFloat(resolution.toString()) * mpu * inchesPerMeter * dpi;
|
||||
return parseFloat(resolution.toString()) * inchesPerMeter * dpi;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -640,5 +640,49 @@ describe('ol.control.ScaleLine', function () {
|
||||
expect(text.slice(0, 4)).to.be('1 : ');
|
||||
expect(text.replace(/^1|\D/g, '')).to.eql(69885283);
|
||||
});
|
||||
it('it corresponds to the resolution in EPSG:4326', function () {
|
||||
const ctrl = new ScaleLine({
|
||||
bar: true,
|
||||
text: true,
|
||||
});
|
||||
ctrl.setMap(map);
|
||||
map.setView(
|
||||
new View({
|
||||
center: [0, 0],
|
||||
zoom: 2,
|
||||
multiWorld: true,
|
||||
projection: 'EPSG:4326',
|
||||
})
|
||||
);
|
||||
map.renderSync();
|
||||
const element = document.querySelector('.ol-scale-text', map.getTarget());
|
||||
expect(element).to.not.be(null);
|
||||
expect(element).to.be.a(HTMLDivElement);
|
||||
const text = element.innerText;
|
||||
expect(text.slice(0, 4)).to.be('1 : ');
|
||||
expect(text.replace(/^1|\D/g, '')).to.eql(139614359);
|
||||
});
|
||||
it('it changes with latitude in EPSG:4326', function () {
|
||||
const ctrl = new ScaleLine({
|
||||
bar: true,
|
||||
text: true,
|
||||
});
|
||||
ctrl.setMap(map);
|
||||
map.setView(
|
||||
new View({
|
||||
center: [0, 60],
|
||||
zoom: 2,
|
||||
multiWorld: true,
|
||||
projection: 'EPSG:4326',
|
||||
})
|
||||
);
|
||||
map.renderSync();
|
||||
const element = document.querySelector('.ol-scale-text', map.getTarget());
|
||||
expect(element).to.not.be(null);
|
||||
expect(element).to.be.a(HTMLDivElement);
|
||||
const text = element.innerText;
|
||||
expect(text.slice(0, 4)).to.be('1 : ');
|
||||
expect(text.replace(/^1|\D/g, '')).to.eql(104710728);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user