在 Openlayer 中根据设备方向旋转地图
Rotate map based on device orientation in Openlayer
我正在 Openlayers 中使用 osm 编写应用程序。我在调整方向时遇到问题。我确定设备的方向。保持图标固定并旋转地图会显示可笑的地方。但是,使用设备的方向,它只会在您旋转图标时显示正确的位置。可能与图标的第一方面有关,但我无法解决问题。我该如何解决这个问题?
var rota_;
var vectorSource = new ol.source.Vector(),
url_osrm_nearest = '//router.project-osrm.org/nearest/v1/driving/',
url_osrm_route = '//router.project-osrm.org/route/v1/driving/',
icon_url = '//cdn.rawgit.com/openlayers/ol3/master/examples/data/icon.png',
vectorLayer = new ol.layer.Vector({
source: vectorSource
}),
styles = {
route: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6, color: [40, 40, 40, 0.8]
})
}),
icon: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: icon_url
})
})
};
const view = new ol.View({
center: [10,10],
zoom: 7,
projection: 'EPSG:4326'
});
const map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
vectorLayer
],
target: 'map',
view: view,
});
const geolocation = new ol.Geolocation({
// enableHighAccuracy must be set to true to have the heading value.
trackingOptions: {
enableHighAccuracy: true,
},
projection: view.getProjection(),
});
window.addEventListener("deviceorientation", handleOrientation, true);
geolocation.setTracking(1);
const iconCar = new ol.Feature({
name: 'Null Island',
population: 4000,
rainfall: 500,
size: [5, 5],
});
const iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0,5, 1],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'https://banner2.cleanpng.com/20180426/wye/kisspng-gps-navigation-systems-computer-icons-arrow-transparent-triangle-5ae25abfa4fff1.7727401715247838076759.jpg',
rotateWithView: "false",
scale: 0.1,
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
})
});
iconCar.setStyle(iconStyle);
new ol.layer.Vector({
map: map,
source: new ol.source.Vector({
features: [iconCar],
}),
});
function compassHeading(alpha, beta, gamma) {
// Convert degrees to radians
var alphaRad = alpha * (Math.PI / 180);
var betaRad = beta * (Math.PI / 180);
var gammaRad = gamma * (Math.PI / 180);
// Calculate equation components
var cA = Math.cos(alphaRad);
var sA = Math.sin(alphaRad);
var cB = Math.cos(betaRad);
var sB = Math.sin(betaRad);
var cG = Math.cos(gammaRad);
var sG = Math.sin(gammaRad);
// Calculate A, B, C rotation components
var rA = - cA * sG - sA * sB * cG;
var rB = - sA * sG + cA * sB * cG;
var rC = - cB * cG;
// Calculate compass heading
var compassHeading = Math.atan(rA / rB);
// Convert from half unit circle to whole unit circle
if(rB < 0) {
compassHeading += Math.PI;
}else if(rA < 0) {
compassHeading += 2 * Math.PI;
}
// Convert radians to degrees
//compassHeading *= 180 / Math.PI;
return compassHeading;
}
function locate()
{
const coordinates = geolocation.getPosition();
iconCar.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null);
map.getView().fit(iconCar.getGeometry(),{maxZoom: 16});
}
function handleOrientation(event) {
absolute = event.absolute;
alpha = event.alpha;
beta = event.beta;
gamma = event.gamma;
if(isNaN(rota_))
{
rota_ = compassHeading(alpha, beta, gamma);
view.setCenter([boylam,enlem]);
//iconStyle.getImage().setRotateWithView(1);
iconStyle.getImage().setRotation(rota_);
}
else
{
eski_yon = rota_;
rota_ = compassHeading(alpha, beta, gamma);
}
if(rota_ != null && !isNaN(rota_))
{
iconStyle.getImage().setRotateWithView(0);
map.getView().setRotation(rota_);
}
}
html,body,#map { width:100%; height:100%; margin:0; }
#map {
position: absolute;
z-index: 5;
}
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.9.0/build/ol.js"></script>
<link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.9.0/css/ol.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "map"> </div>
我不知道为什么,但我将 alpha 乘以 -1 并将 beta 固定为 90 度。问题已解决。
function compassHeading(alpha, beta, gamma) {
var alphaRad = -alpha * (Math.PI / 180);
var betaRad = beta * (Math.PI / 180);
var gammaRad = gamma * (Math.PI / 180);
betaRad = 1.5707963268;
var cA = Math.cos(alphaRad);
var sA = Math.sin(alphaRad);
var cB = Math.cos(betaRad);
var sB = Math.sin(betaRad);
var cG = Math.cos(gammaRad);
var sG = Math.sin(gammaRad);
var rA = - cA * sG - sA * sB * cG;
var rB = - sA * sG + cA * sB * cG;
var rC = - cB * cG;
var compassHeading = Math.atan(rA / rB);
if(rB < 0) {
compassHeading += Math.PI;
}else if(rA < 0) {
compassHeading += 2 * Math.PI;
}
return compassHeading;
}
我正在 Openlayers 中使用 osm 编写应用程序。我在调整方向时遇到问题。我确定设备的方向。保持图标固定并旋转地图会显示可笑的地方。但是,使用设备的方向,它只会在您旋转图标时显示正确的位置。可能与图标的第一方面有关,但我无法解决问题。我该如何解决这个问题?
var rota_;
var vectorSource = new ol.source.Vector(),
url_osrm_nearest = '//router.project-osrm.org/nearest/v1/driving/',
url_osrm_route = '//router.project-osrm.org/route/v1/driving/',
icon_url = '//cdn.rawgit.com/openlayers/ol3/master/examples/data/icon.png',
vectorLayer = new ol.layer.Vector({
source: vectorSource
}),
styles = {
route: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6, color: [40, 40, 40, 0.8]
})
}),
icon: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: icon_url
})
})
};
const view = new ol.View({
center: [10,10],
zoom: 7,
projection: 'EPSG:4326'
});
const map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
vectorLayer
],
target: 'map',
view: view,
});
const geolocation = new ol.Geolocation({
// enableHighAccuracy must be set to true to have the heading value.
trackingOptions: {
enableHighAccuracy: true,
},
projection: view.getProjection(),
});
window.addEventListener("deviceorientation", handleOrientation, true);
geolocation.setTracking(1);
const iconCar = new ol.Feature({
name: 'Null Island',
population: 4000,
rainfall: 500,
size: [5, 5],
});
const iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0,5, 1],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'https://banner2.cleanpng.com/20180426/wye/kisspng-gps-navigation-systems-computer-icons-arrow-transparent-triangle-5ae25abfa4fff1.7727401715247838076759.jpg',
rotateWithView: "false",
scale: 0.1,
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
})
});
iconCar.setStyle(iconStyle);
new ol.layer.Vector({
map: map,
source: new ol.source.Vector({
features: [iconCar],
}),
});
function compassHeading(alpha, beta, gamma) {
// Convert degrees to radians
var alphaRad = alpha * (Math.PI / 180);
var betaRad = beta * (Math.PI / 180);
var gammaRad = gamma * (Math.PI / 180);
// Calculate equation components
var cA = Math.cos(alphaRad);
var sA = Math.sin(alphaRad);
var cB = Math.cos(betaRad);
var sB = Math.sin(betaRad);
var cG = Math.cos(gammaRad);
var sG = Math.sin(gammaRad);
// Calculate A, B, C rotation components
var rA = - cA * sG - sA * sB * cG;
var rB = - sA * sG + cA * sB * cG;
var rC = - cB * cG;
// Calculate compass heading
var compassHeading = Math.atan(rA / rB);
// Convert from half unit circle to whole unit circle
if(rB < 0) {
compassHeading += Math.PI;
}else if(rA < 0) {
compassHeading += 2 * Math.PI;
}
// Convert radians to degrees
//compassHeading *= 180 / Math.PI;
return compassHeading;
}
function locate()
{
const coordinates = geolocation.getPosition();
iconCar.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null);
map.getView().fit(iconCar.getGeometry(),{maxZoom: 16});
}
function handleOrientation(event) {
absolute = event.absolute;
alpha = event.alpha;
beta = event.beta;
gamma = event.gamma;
if(isNaN(rota_))
{
rota_ = compassHeading(alpha, beta, gamma);
view.setCenter([boylam,enlem]);
//iconStyle.getImage().setRotateWithView(1);
iconStyle.getImage().setRotation(rota_);
}
else
{
eski_yon = rota_;
rota_ = compassHeading(alpha, beta, gamma);
}
if(rota_ != null && !isNaN(rota_))
{
iconStyle.getImage().setRotateWithView(0);
map.getView().setRotation(rota_);
}
}
html,body,#map { width:100%; height:100%; margin:0; }
#map {
position: absolute;
z-index: 5;
}
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.9.0/build/ol.js"></script>
<link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.9.0/css/ol.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "map"> </div>
我不知道为什么,但我将 alpha 乘以 -1 并将 beta 固定为 90 度。问题已解决。
function compassHeading(alpha, beta, gamma) {
var alphaRad = -alpha * (Math.PI / 180);
var betaRad = beta * (Math.PI / 180);
var gammaRad = gamma * (Math.PI / 180);
betaRad = 1.5707963268;
var cA = Math.cos(alphaRad);
var sA = Math.sin(alphaRad);
var cB = Math.cos(betaRad);
var sB = Math.sin(betaRad);
var cG = Math.cos(gammaRad);
var sG = Math.sin(gammaRad);
var rA = - cA * sG - sA * sB * cG;
var rB = - sA * sG + cA * sB * cG;
var rC = - cB * cG;
var compassHeading = Math.atan(rA / rB);
if(rB < 0) {
compassHeading += Math.PI;
}else if(rA < 0) {
compassHeading += 2 * Math.PI;
}
return compassHeading;
}