Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用GroundOverlay的脉冲动画_Android_Google Maps_Animation_Gmsgroundoverlay - Fatal编程技术网

Android 使用GroundOverlay的脉冲动画

Android 使用GroundOverlay的脉冲动画,android,google-maps,animation,gmsgroundoverlay,Android,Google Maps,Animation,Gmsgroundoverlay,我需要通过脉冲动画显示位置A和位置B。我能够实现这一点,使用下面的代码。但我面临的问题是,当缩放级别发生变化时,GroundOverlay会改变其大小。如果位置A和B彼此接近(即地图放大级别高),则脉冲半径太大。当我缩小时,它会变得太小 如何在不考虑地图缩放级别的情况下保持覆盖的大小不变 以下代码在此引用: [这是我在两个位置相距较远时得到的结果][] 对于第一个图像,如果我放大,那么我会看到脉冲动画 有没有一种方法可以在不考虑缩放级别的情况下保持脉冲半径不变?因此,假设您希望覆盖圆半径为固

我需要通过脉冲动画显示位置A和位置B。我能够实现这一点,使用下面的代码。但我面临的问题是,当缩放级别发生变化时,GroundOverlay会改变其大小。如果位置A和B彼此接近(即地图放大级别高),则脉冲半径太大。当我缩小时,它会变得太小

如何在不考虑地图缩放级别的情况下保持覆盖的大小不变

以下代码在此引用:

[这是我在两个位置相距较远时得到的结果][]

对于第一个图像,如果我放大,那么我会看到脉冲动画


有没有一种方法可以在不考虑缩放级别的情况下保持脉冲半径不变?

因此,假设您希望覆盖圆半径为固定尺寸(相对于 屏幕像素),例如屏幕宽度的1/10(在当前缩放时)

本例使用宽度作为缩放轴,但也可以使用高度或对角线(通过使用投影的不同点)

“远”的用法可以替换为“近”——它用来解释倾斜,所以你必须进行实验

所以现在你的资源值是一个比例因子,而不是一个绝对半径值-所以在这个例子中,你可以将资源值设置为0.10F,并使用上面的硬编码

如果希望脉冲(和叠加)在缩放后/缩放过程中工作,则需要使用“onCameraIdle”事件更新叠加圆的宽度(circle.setWidth(scaledRadius))-使用与上述scaledRadius相同的计算,例如:

public void onCameraIdle() {
    if (circle != null) {
       // compute scaled radius as in above code...

       // The 1-argument version is specifically width
       circle.setDimensions(scaledRadius);
    }
}

这是因为
GroundOverlay
与谷歌地图一起缩放。为了避免这种情况,您应该为每个缩放级别重新创建覆盖,并为该缩放级别和纬度(示例源代码中为米到像素)校正半径。为了避免
GroundOverlay
娱乐,您应该存储创建的
GroundOverlay
对象,并在创建新对象之前将其删除。为此,您需要对
showRipples()
方法进行一些更改-它应该返回创建的覆盖。完整源代码(例如,带有一个标记):

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private static final String TAG = MainActivity.class.getSimpleName();

    private final LatLng RED_MARKER = new LatLng(-37.884312, 145.000623);

    private GoogleMap mGoogleMap;
    private MapFragment mMapFragment;

    private GroundOverlay mRedPoint = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mMapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;

        mGoogleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
            @Override
            public void onCameraIdle() {
                // if overlay already exists - remove it
                if (mRedPoint != null) {
                    mRedPoint.remove();
                }
                mRedPoint = showRipples(RED_MARKER, Color.RED);
            }
        });
        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(RED_MARKER, 16));
    }

    private GroundOverlay showRipples(LatLng latLng, int color) {
        GradientDrawable d = new GradientDrawable();
        d.setShape(GradientDrawable.OVAL);
        d.setSize(500, 500);
        d.setColor(color);
        d.setStroke(0, Color.TRANSPARENT);

        final Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth()
                , d.getIntrinsicHeight()
                , Bitmap.Config.ARGB_8888);

        // Convert the drawable to bitmap
        final Canvas canvas = new Canvas(bitmap);
        d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        d.draw(canvas);

        // Radius of the circle for current zoom level and latitude (because Earth is sphere at first approach)
        double meters_to_pixels = (Math.cos(mGoogleMap.getCameraPosition().target.latitude * Math.PI /180) * 2 * Math.PI * 6378137) / (256 * Math.pow(2, mGoogleMap.getCameraPosition().zoom));
        final int radius = (int)(meters_to_pixels * getResources().getDimensionPixelSize(R.dimen.ripple_radius));

        // Add the circle to the map
        final GroundOverlay circle = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
                .position(latLng, 2 * radius).image(BitmapDescriptorFactory.fromBitmap(bitmap)));

        // Prep the animator
        PropertyValuesHolder radiusHolder = PropertyValuesHolder.ofFloat("radius", 1, radius);
        PropertyValuesHolder transparencyHolder = PropertyValuesHolder.ofFloat("transparency", 0, 1);

        ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        valueAnimator.setValues(radiusHolder, transparencyHolder);
        valueAnimator.setDuration(1000);
        valueAnimator.setEvaluator(new FloatEvaluator());
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float animatedRadius = (float) valueAnimator.getAnimatedValue("radius");
                float animatedAlpha = (float) valueAnimator.getAnimatedValue("transparency");
                circle.setDimensions(animatedRadius * 2);
                circle.setTransparency(animatedAlpha);

            }
        });

        // start the animation
        valueAnimator.start();

        return circle;
    }

}

计算“半径”作为屏幕投影大小的函数(请参见map.getProjection()。
public void onCameraIdle() {
    if (circle != null) {
       // compute scaled radius as in above code...

       // The 1-argument version is specifically width
       circle.setDimensions(scaledRadius);
    }
}
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private static final String TAG = MainActivity.class.getSimpleName();

    private final LatLng RED_MARKER = new LatLng(-37.884312, 145.000623);

    private GoogleMap mGoogleMap;
    private MapFragment mMapFragment;

    private GroundOverlay mRedPoint = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mMapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;

        mGoogleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
            @Override
            public void onCameraIdle() {
                // if overlay already exists - remove it
                if (mRedPoint != null) {
                    mRedPoint.remove();
                }
                mRedPoint = showRipples(RED_MARKER, Color.RED);
            }
        });
        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(RED_MARKER, 16));
    }

    private GroundOverlay showRipples(LatLng latLng, int color) {
        GradientDrawable d = new GradientDrawable();
        d.setShape(GradientDrawable.OVAL);
        d.setSize(500, 500);
        d.setColor(color);
        d.setStroke(0, Color.TRANSPARENT);

        final Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth()
                , d.getIntrinsicHeight()
                , Bitmap.Config.ARGB_8888);

        // Convert the drawable to bitmap
        final Canvas canvas = new Canvas(bitmap);
        d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        d.draw(canvas);

        // Radius of the circle for current zoom level and latitude (because Earth is sphere at first approach)
        double meters_to_pixels = (Math.cos(mGoogleMap.getCameraPosition().target.latitude * Math.PI /180) * 2 * Math.PI * 6378137) / (256 * Math.pow(2, mGoogleMap.getCameraPosition().zoom));
        final int radius = (int)(meters_to_pixels * getResources().getDimensionPixelSize(R.dimen.ripple_radius));

        // Add the circle to the map
        final GroundOverlay circle = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
                .position(latLng, 2 * radius).image(BitmapDescriptorFactory.fromBitmap(bitmap)));

        // Prep the animator
        PropertyValuesHolder radiusHolder = PropertyValuesHolder.ofFloat("radius", 1, radius);
        PropertyValuesHolder transparencyHolder = PropertyValuesHolder.ofFloat("transparency", 0, 1);

        ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        valueAnimator.setValues(radiusHolder, transparencyHolder);
        valueAnimator.setDuration(1000);
        valueAnimator.setEvaluator(new FloatEvaluator());
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float animatedRadius = (float) valueAnimator.getAnimatedValue("radius");
                float animatedAlpha = (float) valueAnimator.getAnimatedValue("transparency");
                circle.setDimensions(animatedRadius * 2);
                circle.setTransparency(animatedAlpha);

            }
        });

        // start the animation
        valueAnimator.start();

        return circle;
    }

}