- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
背景
之前似乎已经在 SO 上提出了许多类似的问题(最值得注意的是 android google maps not loading the map when using GoogleMap.AnimateCamera() 和 How can I smoothly pan a GoogleMap in Android? ),但是在这些线程中发布的答案或评论都没有让我对如何做到这一点有一个坚定的想法。
我最初认为它会像调用 animateCamera(CameraUpdateFactory.newLatLng(), duration, callback)
一样简单。但就像上面第一个链接的 OP,我得到的只是一张灰色或非常模糊的 map ,直到动画完成,即使我把它放慢到几十秒!
我设法找到并实现了this helper class这很好地允许瓷砖沿途渲染,但即使延迟为 0,每个动画之间也存在明显的延迟。
代码
好的,是时候写一些代码了。这是(稍作修改的)助手类:
package com.coopmeisterfresh.googlemaps.NativeModules;
import android.os.Handler;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.GoogleMap;
import java.util.ArrayList;
import java.util.List;
public class CameraUpdateAnimator implements GoogleMap.OnCameraIdleListener {
private final GoogleMap mMap;
private final GoogleMap.OnCameraIdleListener mOnCameraIdleListener;
private final List<Animation> cameraUpdates = new ArrayList<>();
public CameraUpdateAnimator(GoogleMap map, GoogleMap.
OnCameraIdleListener onCameraIdleListener) {
mMap = map;
mOnCameraIdleListener = onCameraIdleListener;
}
public void add(CameraUpdate cameraUpdate, boolean animate, long delay) {
if (cameraUpdate != null) {
cameraUpdates.add(new Animation(cameraUpdate, animate, delay));
}
}
public void clear() {
cameraUpdates.clear();
}
public void execute() {
mMap.setOnCameraIdleListener(this);
executeNext();
}
private void executeNext() {
if (cameraUpdates.isEmpty()) {
mOnCameraIdleListener.onCameraIdle();
} else {
final Animation animation = cameraUpdates.remove(0);
new Handler().postDelayed(() -> {
if (animation.mAnimate) {
mMap.animateCamera(animation.mCameraUpdate);
} else {
mMap.moveCamera(animation.mCameraUpdate);
}
}, animation.mDelay);
}
}
@Override
public void onCameraIdle() {
executeNext();
}
private static class Animation {
private final CameraUpdate mCameraUpdate;
private final boolean mAnimate;
private final long mDelay;
public Animation(CameraUpdate cameraUpdate, boolean animate, long delay) {
mCameraUpdate = cameraUpdate;
mAnimate = animate;
mDelay = delay;
}
}
}
以及我实现它的代码:
// This is actually a React Native Component class, but I doubt that should matter...?
public class NativeGoogleMap extends SimpleViewManager<MapView> implements
OnMapReadyCallback, OnRequestPermissionsResultCallback {
// ...Other unrelated methods removed for brevity
private void animateCameraToPosition(LatLng targetLatLng, float targetZoom) {
// googleMap is my GoogleMap instance variable; it
// gets properly initialised in another class method
CameraPosition currPosition = googleMap.getCameraPosition();
LatLng currLatLng = currPosition.target;
float currZoom = currPosition.zoom;
double latDelta = targetLatLng.latitude - currLatLng.latitude;
double lngDelta = targetLatLng.longitude - currLatLng.longitude;
double latInc = latDelta / 5;
double lngInc = lngDelta / 5;
float zoomInc = 0;
float minZoom = googleMap.getMinZoomLevel();
float maxZoom = googleMap.getMaxZoomLevel();
if (lngInc > 15 && currZoom > minZoom) {
zoomInc = (minZoom - currZoom) / 5;
}
CameraUpdateAnimator animator = new CameraUpdateAnimator(googleMap,
() -> googleMap.animateCamera(CameraUpdateFactory.zoomTo(
targetZoom), 5000, null));
for (double nextLat = currLatLng.latitude, nextLng = currLatLng.
longitude, nextZoom = currZoom; Math.abs(nextLng) < Math.abs(
targetLatLng.longitude);) {
nextLat += latInc;
nextLng += lngInc;
nextZoom += zoomInc;
animator.add(CameraUpdateFactory.newLatLngZoom(new
LatLng(nextLat, nextLng), (float)nextZoom), true);
}
animator.execute();
}
}
问题
最佳答案
这是我使用您的实用框架播放器的尝试。
几点注意事项:
SphericalUtil.interpolate
. animate
不能使用函数,因为它在每一步都引入了自己的弹跳球效果,这是不受欢迎的。所以给定相当多的步骤move
可以使用功能。 // flag to control the animate callback (at completion).
boolean done = false;
private void animateCameraToPosition(LatLng targetLatLng, float targetZoom) {
CameraPosition currPosition = gMap.getCameraPosition();
LatLng currLatLng = currPosition.target;
//meters_per_pixel = 156543.03392 * Math.cos(latLng.lat() * Math.PI / 180) / Math.pow(2, zoom)
int maxSteps = 500;
// number of steps between start and midpoint and midpoint and end
int stepsMid = maxSteps / 2;
// current zoom
float initz = currPosition.zoom;
//TODO maximum zoom (can be computed from overall distance) such that entire path
// is visible at midpoint.
float maxz = 4.0f;
float finalz = targetZoom;
CameraUpdateAnimator animator = new CameraUpdateAnimator(gMap, () -> {
if (!done) {
gMap.animateCamera(CameraUpdateFactory.
zoomTo(targetZoom), 5000, null);
}
done = true;
});
// loop from start to midpoint
for (int i = 0; i < stepsMid; i++) {
// compute interpolated zoom (current --> max) (linear)
float z = initz - ((initz - maxz) / stepsMid) * i;
// Compute fractional distance using an exponential function such that for the first
// half the fraction delta advances slowly and accelerates toward midpoint.
double ff = (i * (Math.pow(2,maxz) / Math.pow(2,z))) / maxSteps;
LatLng nextLatLng =
SphericalUtil.interpolate(currLatLng, targetLatLng, ff);
animator.add(CameraUpdateFactory.newLatLngZoom(
nextLatLng, z), false, 0);
}
// loop from midpoint to final
for (int i = 0; i < stepsMid; i++) {
// compute interpolated zoom (current --> max) (linear)
float z = maxz + ((finalz - maxz) / stepsMid) * i;
double ff = (maxSteps - ((i+stepsMid) * ( (Math.pow(2,maxz) / Math.pow(2,z)) ))) / (double)maxSteps;
LatLng nextLatLng =
SphericalUtil.interpolate(currLatLng, targetLatLng, ff);
animator.add(CameraUpdateFactory.newLatLngZoom(
nextLatLng, z), false, 0);
}
animator.add(CameraUpdateFactory.newLatLngZoom(
targetLatLng, targetZoom), true, 0);
//
animator.execute();
}
测试代码
gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40.68924, -74.04454), 13.0f));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
animateCameraToPosition(new LatLng(33.899832, -118.020450), 13.0f);
}
}, 5000);
CameraUpdateAnimator 模组
public void execute() {
mMap.setOnCameraIdleListener(this);
executeNext();
}
private void executeNext() {
if (cameraUpdates.isEmpty()) {
mMap.setOnCameraIdleListener(mOnCameraIdleListener);
mOnCameraIdleListener.onCameraIdle();
} else {
final Animation animation = cameraUpdates.remove(0);
// This optimization is likely unnecessary since I think the
// postDelayed does the same on a delay of 0 - execute immediately.
if (animation.mDelay > 0) {
new Handler().postDelayed(() -> {
if (animation.mAnimate) {
mMap.animateCamera(animation.mCameraUpdate);
} else {
mMap.moveCamera(animation.mCameraUpdate);
}
}, animation.mDelay);
} else {
if (animation.mAnimate) {
mMap.animateCamera(animation.mCameraUpdate);
} else {
mMap.moveCamera(animation.mCameraUpdate);
}
}
}
}
sample 前
// assume initial (40.68924, -74.04454) z=13.0f
gMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(33.899832,-118.020450), 13.0f), 30000, null);
UrlTileProvider
来提供洞察力。并记录请求。此实现获取谷歌图 block ,尽管它们的分辨率较低,通常是可见的。
// Turn off this base map and install diagnostic tile provider
gMap.setMapType(GoogleMap.MAP_TYPE_NONE);
gMap.addTileOverlay(new TileOverlayOptions().tileProvider(new MyTileProvider(256,256)).fadeIn(true));
并定义诊断文件提供者
public class MyTileProvider extends UrlTileProvider {
public MyTileProvider(int i, int i1) {
super(i, i1);
}
@Override
public URL getTileUrl(int x, int y, int zoom) {
Log.i("tiles","x="+x+" y="+y+" zoom="+zoom);
try {
return new URL("http://mt1.google.com/vt/lyrs=m&x="+x+"&y="+y+"&z="+zoom);
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
}
您会立即注意到切片图层始终以整数单位定义(
int
)。缩放中提供的分数缩放(例如
LatLngZoom
严格使用内存中的图像 - 很高兴知道。'
// initial zoom
x=2411 y=3080 zoom=13
x=2410 y=3080 zoom=13
x=2411 y=3081 zoom=13
x=2410 y=3081 zoom=13
x=2411 y=3079 zoom=13
x=2410 y=3079 zoom=13
并且最大:
x=9 y=12 zoom=5
x=8 y=12 zoom=5
x=9 y=11 zoom=5
x=8 y=11 zoom=5
x=8 y=13 zoom=5
x=9 y=13 zoom=5
x=7 y=12 zoom=5
x=7 y=11 zoom=5
x=7 y=13 zoom=5
x=8 y=10 zoom=5
x=9 y=10 zoom=5
x=7 y=10 zoom=5
这是每次调用 tiler(x 轴)时的缩放(y 轴)图表。每个缩放层的数量大致相同,这是 imo 所需要的。完全放大显示两倍长,因为这是中点重复。但是有一些异常需要解释(例如在 110 左右)。
关于java - Google Maps SDK for Android : Smoothly animating the camera to a new location, 沿途渲染所有图 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69318061/
我知道它们是匿名类型,但我不明白 Razor 语法。在一些文档中,我找到了这样的示例: @Html.Label("Hello", new { htmlAtributes = new { id = "h
关于:new Object(new Array()) 有一个相当基本的问题,我自己确实无法给出答案,我正在寻求建议: 在js中实例化对象时使用如下方法: var obj = new Object();
在eclipse中右击项目时,“新建文件夹”、“新建源文件夹”和“新建包”有什么区别?他们似乎都在做同样的事情,引用文献并没有说太多。 谢谢 最佳答案 新建文件夹 在项目中创建一个新文件夹。 新建源文
几天来我一直在测试 bolt-cms,我试图了解它是如何工作的。 我想知道新页面、新条目和新展示柜之间有什么区别。 我已阅读 this它并没有填补空白。 最佳答案 Pages、Entries 和 Sh
更新:感谢所有的回答。我发现的最干净的解决方案是这个: if ( k(Arrays.asList(new LinkedList<>())); 我有一个递归方法,可以从列表中生成所有“n 选 k”组合。
我现在想知道这些指令是如何分配内存的。 例如,如果我得到代码怎么办: x = new int[5]; y = new int[5]; 如果分配了这些,它在 RAM 中的实际情况如何?是为每个变量保留整
我希望将其写入output.txt而不清除它 - 只是附加到末尾。但是,当我使用以下两种方法时: public void addEmails(ArrayList emails){ for (i
我正在分配内存,稍后将用于构造具有放置 new 的对象。我应该使用 operator new(n),还是应该使用 new unsigned char[n]?为什么? 最佳答案 因素: new[] 必须
基本上,我的问题是以下代码是否有效。 void* mem = operator new(sizeof(T)); T* instance = new(mem) T; delete instance; 如
很抱歉,如果之前有人问过这个问题,但我想就以下两种用法之间的区别提供一个简明的答案。 VS 似乎将它们都接受为有效代码。 private static void doSomeWork() { /
请告诉我这段代码在做什么,它是否创建多维数组(我认为不是)? 代码片段.. var hanoi_peg = new Array( new Array( 5, 4, 3, 2, 1,
这个问题在这里已经有了答案: String intern() behaviour (4 个答案) When should we use intern method of String on Stri
许多人说您应该避免使用 new Object、new Array(),而是使用 {}。 [] 和真/假。 使用字面量构造来获取对象或数组的新实例而不是使用 new 有什么好处?我知道 Crockfor
我正在开发一个存在内存泄漏的开源库。该库是围绕 boost::asio 构建的数据流服务。服务器端使用堆内存管理系统,该系统提供内存以容纳有限数量的 samples,同时它们等待通过 tcp 连接被推
我从以下函数中得到内存泄漏: int ReadWrite(int socket, char *readfile) { FILE *rf = NULL; rf = fopen(readfile,
在考虑类似的事情时 auto x = new T; 标准是否强制要求内存必须来自operator new——类特定的还是全局的?也就是说,如果缺少特定于类的 operator new,则没有办法从除全
只是出于好奇:为什么 C++ 选择 a = new A 而不是 a = A.new 作为实例化对象的方式?后者不是更像是面向对象的吗? 最佳答案 Just out of curiosity: Why
考虑以下代码: typedef SomeType type_t[2]; SomeType * arr1 = new type_t; //new or new[] ??? type_t * arr2
这个问题在这里已经有了答案: Difference between 'new operator' and 'operator new'? (8 个答案) 关闭 8 年前。 面试题:"new"运算符和
我正在为一个应用程序设计界面,以在 TableLayout 中显示从数据库中提取的一些数据。现在,默认 View 是纵向的,它由一个下拉菜单和一个三列的表格组成。当用户切换到横向时,微调器及其选项可以
我是一名优秀的程序员,十分优秀!