当前位置: 首页 > 知识库问答 >
问题:

如何在Google地图上绘制静态目标圆?

章乐逸
2023-03-14

我一直在研究在谷歌地图上绘制一个静态半径的圆,我遇到的所有答案都描述了绘制标记和与纬度坐标相关的圆。

我需要的是:

这个圆圈和标记漂浮在Google Maps片段上方,即:当您平移和缩放时,它保持静止。这里有一个棘手的部分:我希望能够得到地图中的覆盖区域进行处理(例如:lat、中心标记的长度和圆的半径,取决于地图上的缩放级别)。

我怎样才能做到这一点?提前谢谢。

共有1个答案

阙新觉
2023-03-14

可以创建自定义视图来绘制圆。我的示例基于绘制外部填充的透明圆

在这里,您可以找到有关如何创建自定义视图的教程。

在我的示例中,我创建了一个自定义RadarOverlayView,其中包含一个半径参数,用于计算面积。

我的自定义视图代码:

public class RadarOverlayView extends LinearLayout {
    private Bitmap windowFrame;
    private float radius = 0f;
    private int centerX = 0;
    private int centerY = 0;

    public RadarOverlayView(Context context) {
        super(context);
    }

    public RadarOverlayView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs, R.styleable.RadarOverlayView, 0, 0);

        try {
            radius = a.getDimension(R.styleable.RadarOverlayView_radius, 0f);
        } finally {
            a.recycle();
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);

        if (windowFrame == null) {
            createWindowFrame();
        }
        canvas.drawBitmap(windowFrame, 0, 0, null);
    }

    @Override
    public boolean isEnabled() {
        return false;
    }

    @Override
    public boolean isClickable() {
        return false;
    }

    protected void createWindowFrame() {
        windowFrame = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas osCanvas = new Canvas(windowFrame);

        centerX = getWidth() / 2;
        centerY = getHeight() / 2;

        if (radius > 0) {
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

            // Draw the circunference
            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(Color.RED);
            paint.setAlpha(200);
            paint.setStrokeWidth(5);
            osCanvas.drawCircle(centerX, centerY, radius, paint);

            // Draw the circle
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.RED);
            paint.setAlpha(100);
            osCanvas.drawCircle(centerX, centerY, radius, paint);

            // Draw the center icon
            paint.setAlpha(255);
            Bitmap centerBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
            osCanvas.drawBitmap(centerBitmap, centerX - centerBitmap.getWidth() / 2,
                    centerY - centerBitmap.getHeight() / 2,
                    paint);
        }
    }

    @Override
    public boolean isInEditMode() {
        return true;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        windowFrame = null;
    }

    public float getRadius() {
        return radius;
    }

    public int getCenterX() {
        return centerX;
    }

    public int getCenterY() {
        return centerY;
    }
}

我的attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RadarOverlayView">
        <attr name="radius" format="dimension" />
    </declare-styleable>
</resources>

我的activity\u映射。xml布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
    <fragment
        android:id="@+id/map"
        android:name="myPackage.MySupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MapsActivity"/>
    <myPackage.RadarOverlayView
        android:id="@+id/radar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        app:radius="150dp" />
</RelativeLayout>

我的活动:

public class MapsActivity extends FragmentActivity implements GoogleMap.OnCameraChangeListener {
    private GoogleMap mMap;
    private RadarOverlayView radarView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        radarView = (RadarOverlayView) findViewById(R.id.radar);
        setUpMapIfNeeded();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {
        if (mMap == null) {
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                    .getMap();
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void setUpMap() {
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        mMap.getUiSettings().setAllGesturesEnabled(true);
        mMap.getUiSettings().setZoomControlsEnabled(true);

        mMap.setOnCameraChangeListener(this);
    }

    @Override
    public void onCameraChange(final CameraPosition cameraPosition) {
        // Compute the area of the circle each time the camera changes

        LatLng center = mMap.getProjection().fromScreenLocation(
                new Point(radarView.getCenterX(), radarView.getCenterY()));
        LatLng right = mMap.getProjection().fromScreenLocation(
                new Point(radarView.getCenterX() + Math.round(radarView.getRadius()),
                        radarView.getCenterY()));

        Location locationCenter = new Location("center");
        locationCenter.setLatitude(center.latitude);
        locationCenter.setLongitude(center.longitude);

        Location locationRight = new Location("right");
        locationRight.setLatitude(right.latitude);
        locationRight.setLongitude(right.longitude);

        double geoRadius = locationCenter.distanceTo(locationRight);
        double geoArea = Math.PI * Math.pow(geoRadius, 2);

        // Uncomment to inspect the difference between
        // RadarOverlayView circle and geographic circle:
        // mMap.clear();
        // Circle circle = mMap.addCircle(new CircleOptions()
        //        .center(cameraPosition.target)
        //        .radius(geoRadius)
        //        .strokeColor(Color.GREEN)
        //        .fillColor(Color.BLUE));

        Toast.makeText(this, "Area: " + geoArea, Toast.LENGTH_SHORT).show();
    }
}

结果如下所示,并在每次更换相机时显示一个由圆圈覆盖的区域:

限制:

示例是在视图中绘制一个完美的圆,但根据缩放级别,不能保证该圆在地理上的准确性。

您可以看到,在高缩放级别下,如果您取消注释mMap.addCircle代码,则自定义视图绘制的圆与地理上精确的圆(基于相机目标和半径)之间存在巨大差异。

这种差异是由地图投影(WGS84)造成的,在高缩放级别时差异很大,在低缩放级别时会减小:

 类似资料:
  • 我有一个从Google maps下载静态图像的应用程序,将标记放置在我想要的位置(通过将参数传入Google static maps URL来放置)。但是,我也需要能够点击标记。我想我可以将x和y坐标转换为lon/lat,然后用这种方法计算出哪个标记被点击了,但我发现这并不容易。 我知道地图的尺寸(以像素为单位),缩放级别,以及地图的中心点(以像素和lon/lat为单位),所以我跟踪了这篇博文。不

  • 问题内容: 我试过了 但它产生错误: 任何的想法? 问题答案: 好吧,错误消息很清楚:不是实体。如果要映射基本元素的集合,请使用批注(来自Hibernate)或批注(来自JPA 2.0)。 因此,假设您使用的是Hibernate Annotations 3.4,请尝试以下操作: 或者,使用泛型时: 如果您使用的是Hibernate Annotations 3.5+,则更喜欢JPA 2.0注释: 或

  • 最新代码-http://jsfidle.net/ysqdh/88/- 这个版本使用gDouglasPeuker从绘制的版本中创建一个rudamentary多边形形状-http://jsfiddle.net/ysqdh/94/ ^这将禁用用于绘制的映射,并在创建形状后再次启用该映射。 我正在开发一个谷歌地图应用程序。而不是多边形点击练习。我想要能够画一个形状-然后转换成一个多边形。 下面是我的最新应

  • 嗨,我正在学习如何在shiny上使用传单地图,我用了这个例子: 我想通过将函数替换为来将圈替换为标记。 实际的函数是:(server.r的第98行) 我把它换成了:

  • 我该怎么做才能在我自己的视图上使用freehanf手指画?

  • 我遵循这个例子:https://docs.mapbox.com/android/maps/examples/symbol-layer-info-window/ 也在这里: https://github.com/mapbox/mapbox-android-demo/blob/master/MapboxAndroidDemo/src/main/java/com/mapbox/mapboxandroid