【问题标题】:How to create a polyline on google map like the line showing in the image如何在谷歌地图上创建一条折线,如图像中显示的线
【发布时间】:2017-08-12 08:43:59
【问题描述】:

我需要创建一条同时具有阴影和高程的折线。我还需要为线路提供多种颜色。请建议。

【问题讨论】:

  • 欢迎来到 StackOverflow。不幸的是,这既不是教程网站,也不是网络搜索替代品。我们可以帮助解决certain on-topic problems,但首先的工作是put some efforts 在这个主题上,包括基本的(re)search,尤其是知道绝大多数新手的问题,通常是基本的问题已经回答了很多次了。
  • @Marcin:谢谢你的建议,但我做了一些研究,也使用了基本搜索,但我找不到与此相关的任何链接。

标签: android google-maps google-maps-android-api-2 google-polyline


【解决方案1】:

目前 Google Maps Android API 的折线不支持多种颜色。正如我在对先前答案的评论中提到的那样,Google 问题跟踪器中有一个功能请求,以在 Maps Android API 中实现渐变折线。

作为一种解决方法,您可以在地图顶部实现自己的 GroundOverlay,以绘制不同颜色的线条。查看 StackOverflow 上的类似问题,我发现有些人已经实现了此功能。例如,你可以看看这个实现渐变折线和多边形的 Github 项目:

https://github.com/antoniocarlon/richmaps

我从这个项目中复制了类并创建了一个示例 Google 地图活动,该活动显示了一条类似于您正在寻找的折线。我活动的代码 sn-p 如下

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnCameraIdleListener {

    private GoogleMap mMap;
    private RichLayer richLayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

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

        mMap.getUiSettings().setZoomControlsEnabled(true);

        LatLng ny1 = new LatLng(40.711322,-74.007844);
        LatLng ny2 = new LatLng(40.782493,-73.965424);

        LatLng ny3 = new LatLng(40.75675,-73.98571);

        mMap.setOnCameraIdleListener(this);

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(ny3, 12f));

        richLayer = new RichLayer.Builder(findViewById(R.id.map), mMap).zIndex(100).build();

        this.showPolylineAndShade(ny1, ny2);
    }

    @Override
    public void onCameraIdle() {
        // Refresh the RichLayer each time the camera changes
        richLayer.refresh();
    }

    private void showPolylineAndShade(LatLng p1, LatLng p2) {
        this.showCurvedLine(p1, p2, 0.1, Color.argb(30, 220,220,220), Color.argb(30, 192,192,192), Color.argb(30, 105,105,105),15);
        this.showCurvedLine(p1, p2, 0.3, Color.argb(255, 0,191,255), Color.argb(255, 26,188,156), Color.argb(255, 40,123,177),6);
    }

    private void showCurvedLine (LatLng p1, LatLng p2, double k, int basecolor, int color1, int color2,  int w) {
        //Calculate distance and heading between two points
        double d = SphericalUtil.computeDistanceBetween(p1,p2);
        double h = SphericalUtil.computeHeading(p1, p2);

        //Midpoint position
        LatLng p = SphericalUtil.computeOffset(p1, d*0.5, h);

        //Apply some mathematics to calculate position of the circle center
        double x = (1-k*k)*d*0.5/(2*k);
        double r = (1+k*k)*d*0.5/(2*k);

        LatLng c = SphericalUtil.computeOffset(p, x, h + 90.0);

        //Calculate heading between circle center and two points
        double h1 = SphericalUtil.computeHeading(c, p1);
        double h2 = SphericalUtil.computeHeading(c, p2);

        //Calculate positions of points on circle border and add them to polyline options
        int numpoints = 1000;
        double step = (h2 -h1) / numpoints;

        RichPolylineOptions polylineOpts = new RichPolylineOptions(null)
                .zIndex(100) // zIndex represents the position of the polyline on the RichLayer
                .strokeWidth(w)
                .strokeColor(basecolor)
                .linearGradient(false);

        Point fromScreenPoint = null;
        Point toScreenPoint = null;
        int[] colors = new int[]{color1, color2};
        Projection projection = mMap.getProjection();

        for (int i=0; i < numpoints; i++) {
            LatLng pi = SphericalUtil.computeOffset(c, r, h1 + i * step);
            RichPoint rp = new RichPoint(pi);
            polylineOpts.add(rp);
            if (i == 0) {
                fromScreenPoint = projection.toScreenLocation(rp.getPosition());
            }
            if (i == numpoints -1) {
                toScreenPoint = projection.toScreenLocation(rp.getPosition());
            }
        }

        if (fromScreenPoint!=null && toScreenPoint!=null) {
            int fromX = fromScreenPoint.x ;
            int fromY = fromScreenPoint.y;
            int toX = toScreenPoint.x;
            int toY = toScreenPoint.y;

            polylineOpts.strokeShader(new LinearGradient(fromX, fromY, toX, toY,
                    colors, null, Shader.TileMode.CLAMP));
        }

        RichPolyline polyline = polylineOpts.build();
        richLayer.addShape(polyline);
    }
}

此代码将创建一条折线,如以下屏幕截图所示

您可以在 Github 上找到并下载示例项目

https://github.com/xomena-so/so45648311

我希望这会有所帮助!

【讨论】:

    【解决方案2】:

    在 Android Google Maps API 中似乎没有“标准”方法可以执行此操作,但您始终可以使用放置在地图片段上的自定义视图手动执行此操作。类似的东西:

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <fragment
            android:id="@+id/map_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            class="com.google.android.gms.maps.MapFragment"
        />
    
        <your.custom.component.Name
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
        />
    
    </RelativeLayout>
    

    您可以从地图中获取曲线坐标并将其绘制在您的自定义视图画布上,并具有透明度。

    【讨论】:

    • 我只能在 Google 问题跟踪器中添加,您可以在 Google Maps Android API 中找到添加渐变折线的功能请求:issuetracker.google.com/issues/35828754。您可以对此功能请求加注星标以添加您的投票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多