xamarin.forms - 使指南针始终指向 Xamarin 表单中的特定位置
问题描述
我正在尝试按照Xamarin.Essentials 实施 Compass:Compass以前往特定点。为了实现和测试,我添加了 SfCircularGauge ,它在相同的逻辑下运行良好。因为,我不想使用 XF,所以在没有 XF 的情况下尝试了它。但是在没有 XF 的情况下工作时,箭头不指向正确的方向,箭头只指向北方。计算和点是相同的,都是关于箭头没有指向正确的方向。(我在 iOS 中测试,没有在 Android 中检查)
double current_latitude = 25.2618616; // changed on Appearing
double current_longitude = 55.3254198; // changed on Appearing
readonly double QiblaLatitude = 21.4224779; //remains --> pointing to this location
readonly double QiblaLongitude = 39.8251832; //remains --> pointing to this location
readonly SensorSpeed speed = SensorSpeed.UI;
public MainPage()
{
InitializeComponent();
Compass.ReadingChanged += Compass_ReadingChanged;
if (!Compass.IsMonitoring) Compass.Start(speed);
}
void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
{
circularGauge.RotateTo(360 - e.Reading.HeadingMagneticNorth); // this is XF
compassImage.RotateTo(360 - e.Reading.HeadingMagneticNorth);
ImageArrow.RotateTo(360 - e.Reading.HeadingMagneticNorth);
PointToQibla();
}
private async void GetLocation()
{
try
{
var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromMilliseconds(10));
var location = await Geolocation.GetLocationAsync(request);
current_latitude = location.Latitude;
current_longitude = location.Longitude;
}
catch(Exception ex){System.Diagnostics.Debug.WriteLine(ex.Message);}
}
private double Mod(double a, double b)
{
return a - b * Math.Floor(a / b);
}
void PointToQibla()
{
double latt_from_radians = current_latitude * Math.PI / 180;
double long_from_radians = current_longitude * Math.PI / 180;
double latt_to_radians = QiblaLatitude * Math.PI / 180;
double lang_to_radians = QiblaLongitude * Math.PI / 180;
double bearing = Math.Atan2(Math.Sin(lang_to_radians - long_from_radians) * Math.Cos(latt_to_radians), (Math.Cos(latt_from_radians) * Math.Sin(latt_to_radians)) - (Math.Sin(latt_from_radians) * Math.Cos(latt_to_radians) * Math.Cos(lang_to_radians - long_from_radians)));
bearing = Mod(bearing, 2 * Math.PI);
double bearing_degree = bearing * 180 / Math.PI;
//normal arrow and XF
ImageArrow.Rotation = pointer1.Value = bearing_degree;
// Labels to show value
lblG.Text = LabelInfo.Text = string.Format("Lat: {0} Long: {1} degree:{2}", current_latitude,current_longitude,bearing_degree.ToString());
}
protected override void OnAppearing()
{
base.OnAppearing();
GetLocation();
}
XAML(XF 和普通)
<Grid Padding="20" BackgroundColor="White">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0">
<SyncfusionGauge:SfCircularGauge
x:Name="circularGauge"
BackgroundColor="Transparent"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand">
<SyncfusionGauge:SfCircularGauge.Scales>
<SyncfusionGauge:Scale x:Name="scale"
StartAngle="270"
StartValue="0"
EndValue="360"
Interval="45"
LabelOffset="0.75"
SweepAngle="360"
MinorTicksPerInterval="1"
ShowLastLabel="False"
ScaleStartOffset="0.99"
ScaleEndOffset="0.9"
LabelCreated="Scale_LabelCreated">
<SyncfusionGauge:Scale.Pointers>
<SyncfusionGauge:NeedlePointer x:Name="pointer1"
Type="Triangle"
LengthFactor="0.65"
KnobColor="White"
Thickness="25"
EnableAnimation="True">
<SyncfusionGauge:NeedlePointer.KnobRadius>
<OnPlatform x:TypeArguments="x:Double">
<On Platform="UWP"
Value="15" />
<On Platform="Android"
Value="25" />
<On Platform="iOS"
Value="25" />
</OnPlatform>
</SyncfusionGauge:NeedlePointer.KnobRadius>
</SyncfusionGauge:NeedlePointer>
</SyncfusionGauge:Scale.Pointers>
<SyncfusionGauge:Scale.MajorTickSettings>
<SyncfusionGauge:TickSettings StartOffset="0.9"
EndOffset="0.83"
Thickness="2" />
</SyncfusionGauge:Scale.MajorTickSettings>
<SyncfusionGauge:Scale.MinorTickSettings>
<SyncfusionGauge:TickSettings StartOffset="0.9"
EndOffset="0.85"
Thickness="2" />
</SyncfusionGauge:Scale.MinorTickSettings>
</SyncfusionGauge:Scale>
</SyncfusionGauge:SfCircularGauge.Scales>
</SyncfusionGauge:SfCircularGauge>
<Label x:Name="lblG" TextColor="Red"></Label>
</StackLayout>
<StackLayout Grid.Row="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" x:Name="compassImage" Source="compass.png"/>
<Image HorizontalOptions="Center" VerticalOptions="Center" Source="arrow.png" x:Name="ImageArrow"/>
<Label Grid.Row="1" x:Name="LabelInfo" TextColor="Blue"
VerticalOptions="Center" HorizontalOptions="Center" />
</Grid>
</StackLayout>
</Grid>
问题是箭头不指向特定方向,但它始终保持在北方。该项目也可以在GitHub 上找到
解决方案
我在如何在 Compass Windows Phone 8 上获得朝拜方向之后解决了这个谜团? . 更新后的代码如下所示;
void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
{
try
{
//Qibla lat and long
var qiblaLocation = new Location(QiblaLatitude, QiblaLongitude);
//current position
var position = new Location(current_latitude, current_longitude);
var res = DistanceCalculator.Bearing(position, qiblaLocation);
var TargetHeading = (360 - res) % 360;
var currentHeading = 360 - e.Reading.HeadingMagneticNorth;
Heading = currentHeading - TargetHeading;
Info = string.Format("Lat: {0} Long: {1} degree:{2}", current_latitude, current_longitude, Heading);
}catch(Exception ex){//log exception}
}
完整的项目在GitHub
推荐阅读
- php - Symfony 4 - 无法提交我的表单模式(路径错误)
- .net - 如何告诉 Roslyn C# 编译器使用特定版本的 .NET?
- javascript - 如何将 HTML 表单数据存储到特定文件夹中的 csv 文件?
- json - 还有另一种方法可以从 Fabric JS 获取 JSON 中存在的 Circle 对象吗?
- node.js - 如何识别哪些 npm 包只是对等依赖项?
- swift - UIScreenEdgePanGestureRecognizer 在 iOS 13 模拟器中不起作用
- assembly - 当我们减去两个标签的名称并将其存储在变量中时我们得到什么值
- nginx - Nginx WebDAV:禁止目录索引
- jquery - 如何仅过滤特定列中具有几乎相似值的记录的顶行?
- android - 托管 ARCore ancore 超过 24 小时