Google Map 开发(二):根据方向传感器对 Marker 进行旋转

Stella981
• 阅读 1126

这是最近做的一个小功能,虽然很简单,网上却很少有相关例子,关于怎么使用地磁和加速度传感器的例子是有了,怎么旋转 Google Map Marker 也能 Google 到一些,但是结合起来就基本没看到,也可能是我搜索方式不对,所以还是自己来实现了。

首先找找 Google Map Marker 相关的文档,如何使用可以参见这个:

https://developers.google.com/maps/documentation/android-sdk/marker?hl=zh-cn

对于 Marker 类可以参考:

https://developers.google.com/android/reference/com/google/android/gms/maps/model/Marker?hl=zh-cn

(2018/06/29 验证)

Marker 有一个很重要的属性:Anchor,请记者这个小东西,后面要用到它,官方的解释是 :

The point on the image that will be placed at the LatLng position of the marker. This defaults to 50% from the left of the image and at the bottom of the image.

接着说说怎么利用方向传感器,在 Android 中,方位是通过加速度传感器和地磁传感器共同确定。

sensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
Sensor magnetic = null;
if (sensorManager != null) {
    magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
Sensor acceleromter = null;
if (sensorManager != null) {
    acceleromter = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
if (sensorManager != null) {
    sensorManager.registerListener(sensorEventListener, magnetic, SensorManager.SENSOR_DELAY_GAME);
}
if (sensorManager != null) {
    sensorManager.registerListener(sensorEventListener, acceleromter, SensorManager.SENSOR_DELAY_GAME);
}

在获取到传感器的数据后,可以获取用户此时旋转了多少度,然后再对 Marker 进行旋转。

private SensorEventListener sensorEventListener = new SensorEventListener() {
      @Override
      public void onSensorChanged(SensorEvent event) {
       
      }
      @Override
      public void onAccuracyChanged(Sensor sensor, int accuracy) {
      }
 };

我们的逻辑代码就写在 onSensorChanged 方法里,准备两个 float 类型的数据,分别存储地磁传感器和加速度传感器的数据。

 float[] magneticValues = new float[3];
 float[] acceleromterValues = new float[3];

传感器的数据更新是非常快的,为了避免 Marker 旋转像是遇到了鬼一样,我们对时间间隔和更新角度信息做个显示,定义两个变量分别表示上次旋转的角度和上次传感器数据更新的时间。

private float lastRotateDegree;
private long lastUpdatetime;

将传感器数据赋值给数组:

 // 判断数据来源于哪个传感器
 if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
     acceleromterValues = event.values.clone();
 } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
     magneticValues = event.values.clone();
 }

为了得到传感器的航向角、俯仰角、横滚角等数据,我们需要计算一个旋转矩阵,不过 SensorManager 已经提供了,只需要调用就可以了,并用新的数组保存他们。

float[] R = new float[9];
float[] values = new float[3];
SensorManager.getRotationMatrix(R, null, acceleromterValues, magneticValues);
SensorManager.getOrientation(R, values);

接下来计算出旋转角度,并用 0~360° 表示。

 float roteteDegree = -(float) Math.toDegrees(values[0]);
 if (roteteDegree < 0) roteteDegree = 360 + roteteDegree;
 if (roteteDegree < 0 || roteteDegree > 360) return;

计算本次旋转角度更新的度数,定义如果在 0.5°之间是属于抖动,直接过滤掉,不予更新。

float offset = roteteDegree - lastRotateDegree;
if (Math.abs(offset) < 0.5f) return;

在得到了 roteteDegree 的值后,就已经可以把角度传递给 Marker,Google Map Marker 中的 setRotation 方法可以让 Marker 进行旋转。

 gUserMarker.setRotation(roteteDegree);

好了,真机运行看看,emmm... Marker 的旋转十分奇怪啊,怎么以边界为原点进行旋转,而不是以中心点旋转,这就像一个圆形的门牌,最上面边缘的钉子掉了一样。这时再回顾看看 Marker 类中 Anchor,setAnchor 可以设定它的值,文档地址:

https://developers.google.com/android/reference/com/google/android/gms/maps/model/Marker?hl=zh-cn#setAnchor(float,%20float)

官方画了一个直击灵魂的图表示这个属性值是什么作用:

Google Map 开发(二):根据方向传感器对 Marker 进行旋转

所以,给它设定 0.5,0.5 就圆点居中了,不信阔以试一试~

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这