在mapview中绘制透明度的圆圈

时间:2012-01-30 14:42:13

标签: android google-maps overlay android-mapview geometry

我遇到mapview和Overlay问题。

每次改变GPS位置时,我必须在地图上画一个圆圈。 我在我的覆盖类中使用了方法draw来扩展叠加层。 问题是我必须用透明度绘制这些圆圈,但是当圆圈在交点处相互重叠时,颜色会有所不同,因为有一个alpha的总和。

我该如何解决?

这是我的叠加类:

public class ImpactOverlay extends Overlay {

private static int CIRCLERADIUS = 0;
private GeoPoint geopoint;
private int myCircleRadius;
Point point = new Point();
Paint circle = new Paint(Paint.ANTI_ALIAS_FLAG);
private long systemTime= -1 ;



public ImpactOverlay(GeoPoint point, int myRadius) {

    geopoint = point;
    CIRCLERADIUS = myRadius; // assegna raggio del cerchio
}

@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {

     // Transfrom geoposition to Point on canvas
     Projection projection = mapView.getProjection();
     projection.toPixels(geopoint, point);

     // the circle to mark the spot
     circle.setColor(Color.parseColor("#88ff0000"));
     circle.setAlpha(122); // trasparenza

     myCircleRadius = metersToRadius(CIRCLERADIUS, mapView,
     (double) geopoint.getLatitudeE6() / 1000000);

     canvas.drawCircle(point.x, point.y, myCircleRadius, circle);       

}



public static int metersToRadius(float meters, MapView map, double latitude) {
    return (int) (map.getProjection().metersToEquatorPixels(meters) * (1 / Math
            .cos(Math.toRadians(latitude))));
}

@Override
/* Implementa il doppio tap per eseguire zoom sulla mappa */
public boolean onTouchEvent(MotionEvent event, MapView mapView) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        if ((System.currentTimeMillis() - systemTime) < 250) {
            mapView.getController().zoomIn();
        }
        systemTime = System.currentTimeMillis();
        break;
    }

    return false;
}
}

4 个答案:

答案 0 :(得分:0)

有一种可能性就是将那个与第二个圆相交的区域剪掉,伪代码:

canvas.clipPath(circle2.toPath())
canvas.draw(circle1)
canvas.removeClip()
canvas.draw(circle2)

答案 1 :(得分:0)

剪辑时需要考虑交叉点,如下所示:

@Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
                long when) {
    Paint paint = new Paint();
    paint.setColor(Color.parseColor("#88ff0000"));
    paint.setAlpha(16); // quite transparent
    Point point = new Point();
    Point point2 = new Point();
    float radius = 50.0f;

    Projection projection = mapView.getProjection();
    projection.toPixels(mGpt, point);   // 1st GeoPoint
    projection.toPixels(mGpt2, point2); // 2nd GeoPoint

    Path path1 = new Path();
    Path path2 = new Path();

    path1.addCircle(point.x, point.y, radius, Direction.CW);   // 1st circle
    path2.addCircle(point2.x, point2.y, radius, Direction.CW); // 2nd circle
    canvas.save(); // save canvas without the clip region
    canvas.clipPath(path2, Region.Op.DIFFERENCE); // clip the region
    // to the whole view less where circle2 will be when it's drawn
    canvas.drawPath(path1, paint); // draw 1st circle minus where it overlaps
    canvas.restore();              // clear the clip region
    canvas.drawPath(path2, paint); // draw 2nd circle (unclipped)
    return false;
}

应该有效

答案 2 :(得分:0)

您不需要事先知道有多少形状。如果使用单独的叠加层,则可以轻松绘制每个叠加层并将相应的区域添加到剪切区域。

完整代码如下:

import java.util.List;

import android.graphics.*;
import android.graphics.Path.Direction;
import android.graphics.Region.Op;
import android.os.Bundle;
import android.view.MotionEvent;

import com.google.android.maps.*;

public class CircleTest extends MapActivity {
    private MapView m_map;

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

        m_map = (MapView) findViewById(R.id.mapview);
        m_map.displayZoomControls(true);
        m_map.setBuiltInZoomControls(true);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // m_map.getOverlays().add(new ); // some other overlays
        m_map.getOverlays().add(new ImpactGeneratorOverlay());
        // the impact areas are being inserted between these two, see ImpactGeneratorOverlay
        m_map.getOverlays().add(new ImpactClipRestoreOverlay());
    }

    /**
     * Restore clipping area to the saved one.
     */
    public static class ImpactClipRestoreOverlay extends Overlay {
        @Override
        public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
            super.draw(canvas, mapView, shadow);
            canvas.restore();
        }
    }

    /**
     * Handles events, on touch down it adds a new Impact area to the map,
     * just before the ClipRestore overlay (assume it's the last, if not store position, and insert before).
     */
    public static class ImpactGeneratorOverlay extends Overlay {
        @Override
        public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
            super.draw(canvas, mapView, shadow);
            canvas.save();
        }

        @Override
        public boolean onTouchEvent(final MotionEvent e, final MapView mapView) {
            switch (e.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
                    GeoPoint point = mapView.getProjection().fromPixels((int) e.getX(), (int) e.getY());
                    List<Overlay> overlays = mapView.getOverlays();
                    overlays.add(overlays.size() - 1, new ImpactOverlay(point, 1000));
                    break;
            }
            return super.onTouchEvent(e, mapView);
        }
    }

    /**
     * Draw impact and remove the current shape path from the drawable area.
     */
    public static class ImpactOverlay extends Overlay {
        // shape parameters
        private final GeoPoint  circleCenter;
        private final int       circleRadius;

        // drawing cache
        private final Point     circleDrawCenter    = new Point();
        private final Paint     circlePaint         = new Paint();

        public ImpactOverlay(final GeoPoint circleCenter, final int circleRadius) {
            this.circleCenter = circleCenter;
            this.circleRadius = circleRadius;

            circlePaint.setAntiAlias(true);
            circlePaint.setColor(Color.argb(64, 255, 0, 0));
        }

        @Override
        public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
            // Transfrom geoposition to Point on canvas
            Projection projection = mapView.getProjection();
            projection.toPixels(circleCenter, circleDrawCenter);

            // the circle to mark the spot
            float circleDrawRadius = ImpactOverlay.metersToRadius(mapView, circleRadius, circleCenter.getLatitudeE6() / 1e6f);

            // create circle from path
            Path path = new Path();
            path.addCircle(circleDrawCenter.x, circleDrawCenter.y, circleDrawRadius, Direction.CW);

            // draw circle
            canvas.drawPath(path, circlePaint);

            // remove circle from further posibble drawing areas
            canvas.clipPath(path, Op.DIFFERENCE);
        }

        public static float metersToRadius(final MapView map, final float meters, final float latitude) {
            return (float) (map.getProjection().metersToEquatorPixels(meters) * (1 / Math.cos(Math.toRadians(latitude))));
        }
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
}

这包含用于剪切不需要的图层的修复,比如说第一个,但如果您只是将所有圆圈聚集在一个叠加层中并使用一种绘制方法绘制它们,则可以避免这种情况。

关键是绘制和设置剪裁(即使它们存在于不同的叠加层中,不建议!):

canvas.save();
canvas.drawPath(path1, paint);
canvas.clipPath(path1, Op.DIFFERENCE);
canvas.drawPath(path2, paint); // do not draw over path1
canvas.clipPath(path2, Op.DIFFERENCE);
canvas.drawPath(path3, paint); // do not draw over path1 + path2
canvas.clipPath(path3, Op.DIFFERENCE);
// do not draw over path1 + path2 + path3
canvas.restore();
canvas.drawPath(path4, paint); // draw over anything

答案 3 :(得分:0)

        CircleOptions circle = new CircleOptions();
        circle.center(new LatLng(latitude, longitude))
        .radius(1500)//in meters
        .strokeColor(Color.BLUE)//border color
        .strokeWidth(3.0f)//border width
        .fillColor(0x200000ff);//inside circle
        googleMap.addCircle(circle);//GoogleMap googleMap(initialize accordingly)