Osmdroid覆盖物添加API功能介绍2----点线面覆盖物

Osmdroid覆盖物添加API功能介绍2----点线面覆盖物

http://osmdroid.github.io/osmdroid/

前言

Osmdroid 和百度高德一样可以加载一些点线面图形到地图上面
当多个覆盖物在通一个点显示并被点击时,是根据覆盖物的点击事件是否返回true来判断是否消费该事件

1,点-ItemizedOverlay

这是一个可以显示多个点集合的覆盖物,它有两个实现类ItemizedIconOverlay,ItemizedOverlayWithFocus

  • 方法getDisplayedItems();可以获取当前界面上显示的数据点
  • OverlayItem可以通过setMarker设置不同的显示图标
1.1 ItemizedIconOverlay

使用方式:

 			final ArrayList<OverlayItem> items = new ArrayList<>();
			items.add(new OverlayItem("Hannover", "SampleDescription", new GeoPoint(52.370816, 9.735936)));
			items.add(new OverlayItem("Berlin", "SampleDescription", new GeoPoint(52.518333, 13.408333)));
			items.add(new OverlayItem("Washington", "SampleDescription", new GeoPoint(38.895000, -77.036667)));
			
			/* OnTapListener for the Markers, shows a simple Toast. */
			this.mMyLocationOverlay = new ItemizedIconOverlay<>(items,
					new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
						@Override
						public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
							Toast.makeText(
									SampleWithMinimapItemizedoverlay.this,
									"Item '" + item.getTitle() + "' (index=" + index
											+ ") got single tapped up", Toast.LENGTH_LONG).show();
							return true; // We 'handled' this event.返回true就表示这个点击事件被消费掉了
						}

						@Override
						public boolean onItemLongPress(final int index, final OverlayItem item) {
							Toast.makeText(
									SampleWithMinimapItemizedoverlay.this,
									"Item '" + item.getTitle() + "' (index=" + index
											+ ") got long pressed", Toast.LENGTH_LONG).show();
							return false;//false表示这个事件可以继续向下传递
						}
					}, getApplicationContext());
			this.mMapView.getOverlays().add(this.mMyLocationOverlay);

实现效果
ItemizedIconOverlay实现效果

1.1 ItemizedOverlayWithFocus

ItemizedIconOverlay不同的是这个覆盖物可以设置是否获取焦点,并且在获取焦点的时候显示一个文本框。并且可以自定义这个文本框的样式
使用代码:

/* Create a static ItemizedOverlay showing some Markers on various cities. */
			final ArrayList<OverlayItem> items = new ArrayList<>();
			items.add(new OverlayItem("Hannover", "Tiny SampleDescription", new GeoPoint(52.370816,
					9.735936))); // Hannover
			items.add(new OverlayItem("Berlin", "This is a relatively short SampleDescription.",
					new GeoPoint(52.518333, 13.408333))); // Berlin
			items.add(new OverlayItem(
					"Washington",
					"This SampleDescription is a pretty long one. Almost as long as a the great wall in china.",
					new GeoPoint(38.895, -77.036667))); // Washington
			items.add(new OverlayItem("San Francisco", "SampleDescription", new GeoPoint(37.7793,
					-122.4192))); // San Francisco

			/* OnTapListener for the Markers, shows a simple Toast. */
			mMyLocationOverlay = new ItemizedOverlayWithFocus<>(items,
					new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
						@Override
						public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
							Toast.makeText(
									context,
									"Item '" + item.getTitle() + "' (index=" + index
											+ ") got single tapped up", Toast.LENGTH_LONG).show();
							return true;
						}

						@Override
						public boolean onItemLongPress(final int index, final OverlayItem item) {
							Toast.makeText(
									context,
									"Item '" + item.getTitle() + "' (index=" + index
											+ ") got long pressed", Toast.LENGTH_LONG).show();
							return false;
						}
					}, context);
			mMyLocationOverlay.setFocusItemsOnTap(true);
			mMyLocationOverlay.setFocusedItem(0);
			//https://github.com/osmdroid/osmdroid/issues/317
			//you can override the drawing characteristics with this
			mMyLocationOverlay.setMarkerBackgroundColor(Color.BLUE);
			mMyLocationOverlay.setMarkerTitleForegroundColor(Color.WHITE);
			mMyLocationOverlay.setMarkerDescriptionForegroundColor(Color.WHITE);
			mMyLocationOverlay.setDescriptionBoxPadding(15);

			mMapView.getOverlays().add(mMyLocationOverlay);

效果图:
在这里插入图片描述

2,Mark覆盖物

在地图上添加一个标记图片。
使用方式

 	    GeoPoint startPoint = new GeoPoint(38.8977, -77.0365);  //white house
        points.add(startPoint);
        Marker startMarker = new Marker(mMapView);
        startMarker.setPosition(startPoint);
        startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
        startMarker.setIcon(drawable);
        startMarker.setTitle("White House");
        startMarker.setSnippet("The White House is the official residence and principal workplace of the President of the United States.");
        startMarker.setSubDescription("1600 Pennsylvania Ave NW, Washington, DC 20500");
        startMarker.setOnMarkerClickListener(new Marker.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker, MapView mapView) {
                marker.showInfoWindow();
                return true;
            }
        });
        mMapView.getOverlays().add(startMarker);

实现效果
在这里插入图片描述

3,线Polyline

实现方式

        //mOsmPathOverlay = new OsmPathOverlay(context);
		//mMapView.getOverlayManager().add(mOsmPathOverlay);
		Polyline line = new Polyline(mMapView);
		line.setTitle("Central Park, NYC");
		line.setSubDescription(Polyline.class.getCanonicalName());
		line.setWidth(20f);
		List<GeoPoint> pts = new ArrayList<>();
		//here, we create a polygon, note that you need 5 points in order to make a closed polygon (rectangle)

		pts.add(new GeoPoint(40.796788, -73.949232));
		pts.add(new GeoPoint(40.796788, -73.981762));
		pts.add(new GeoPoint(40.768094, -73.981762));
		pts.add(new GeoPoint(40.768094, -73.949232));
		pts.add(new GeoPoint(40.796788, -73.949232));
		line.setPoints(pts);
		line.setGeodesic(true);
		line.setInfoWindow(new BasicInfoWindow(R.layout.bonuspack_bubble, mMapView));
		//Note, the info window will not show if you set the onclick listener
		//line can also attach click listeners to the line
		/*
		line.setOnClickListener(new Polyline.OnClickListener() {
			@Override
			public boolean onClick(Polyline polyline, MapView mapView, GeoPoint eventPos) {
				Toast.makeText(context, "Hello world!", Toast.LENGTH_LONG).show();
				return false;
			}
		});*/
		mMapView.getOverlayManager().add(line);

实现效果
在这里插入图片描述

4,面Polygon

使用方式

       //here, we create a polygon using polygon class, note that you need 4 points in order to make a rectangle
		Polygon polygon = new Polygon(mMapView);
		polygon.setTitle("This is a polygon");
		polygon.setSubDescription(Polygon.class.getCanonicalName());
		polygon.setFillColor(Color.RED);
		polygon.setVisible(true);
		polygon.setStrokeColor(Color.BLACK);
		polygon.setInfoWindow(new BasicInfoWindow(R.layout.bonuspack_bubble, mMapView));


		pts = new ArrayList<>();
		pts.add(new GeoPoint(40.886788, -73.959232));
		pts.add(new GeoPoint(40.886788, -73.971762));
		pts.add(new GeoPoint(40.878094, -73.971762));
		pts.add(new GeoPoint(40.878094, -73.959232));
		polygon.setPoints(pts);
		mMapView.getOverlays().add(polygon);

实现效果
在这里插入图片描述

Polygon可以构建复杂的面图形结构

setHoles(List<? extends List<GeoPoint>> holes)

效果:
在这里插入图片描述

5,路径演示功能

功能实现效果如下图所示

在这里插入图片描述

实现代码:

1,创建一个Polyline对象
 	    final Polyline line = new Polyline(mMapView);
        line.setColor(COLOR_POLYLINE_STATIC);
        line.setWidth(LINE_WIDTH_BIG);
        line.setPoints(mGeoPoints);
        line.getPaint().setStrokeCap(Paint.Cap.ROUND);
        mMapView.getOverlayManager().add(line);
2,创建是ValueAnimator 执行动画效果
//路径切片
 final MilestoneMeterDistanceSliceLister slicerForPath = new MilestoneMeterDistanceSliceLister();
 //图片切片
final MilestoneMeterDistanceSliceLister slicerForIcon = new MilestoneMeterDistanceSliceLister();
 final ValueAnimator percentageCompletion = ValueAnimator.ofFloat(0, 10000); // 10 kilometers
            percentageCompletion.setDuration(5000); // 5 seconds
            percentageCompletion.setStartDelay(1000); // 1 second
            percentageCompletion.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                //当前的位置
                    mAnimatedMetersSoFar = (float)animation.getAnimatedValue();
                    //路径
                    slicerForPath.setMeterDistanceSlice(0, mAnimatedMetersSoFar);
                    //图片当前的位置
                    slicerForIcon.setMeterDistanceSlice(mAnimatedMetersSoFar, mAnimatedMetersSoFar);
                    mMapView.invalidate();
                }
            });
            percentageCompletion.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mAnimationEnded = true;
                }
            });
            percentageCompletion.start();
3,创建绘制千米符号的MilestoneManager
        final float backgroundRadius = 20;
        final Paint backgroundPaint1 = getFillPaint(COLOR_BACKGROUND);
        final Paint backgroundPaint2 = getFillPaint(COLOR_POLYLINE_ANIMATED);
        final Paint textPaint1 = getTextPaint(COLOR_POLYLINE_STATIC);
        final Paint textPaint2 = getTextPaint(COLOR_BACKGROUND);
        final Paint borderPaint = getStrokePaint(COLOR_BACKGROUND, 2);
        return new MilestoneManager(
        	   //每一千米一个监听回调
                new MilestoneMeterDistanceLister(1000),
                new MilestoneDisplayer(0, false) {
                    @Override
                    protected void draw(final Canvas pCanvas, final Object pParameter) {
                        final double meters = (double)pParameter;
                        final int kilometers = (int)Math.round(meters / 1000);
                        //根据动画的执行过程绘制不同的符号
                        final boolean checked = meters < mAnimatedMetersSoFar || (kilometers == 10 && mAnimationEnded);
                        final Paint textPaint = checked ? textPaint2 : textPaint1;
                        final Paint backgroundPaint = checked ? backgroundPaint2 : backgroundPaint1;
                        final String text = "" + kilometers + "K";
                        final Rect rect = new Rect();
                        textPaint1.getTextBounds(text, 0, text.length(), rect);
                        pCanvas.drawCircle(0, 0, backgroundRadius, backgroundPaint);
                        pCanvas.drawText(text, -rect.left - rect.width() / 2, rect.height() / 2 - rect.bottom, textPaint);
                        pCanvas.drawCircle(0, 0, backgroundRadius + 1, borderPaint);
                    }
                }
        );
4,方向箭头
final Path arrowPath = new Path(); // a simple arrow towards the right
        arrowPath.moveTo(-5, -5);
        arrowPath.lineTo(5, 0);
        arrowPath.lineTo(-5, 5);
        arrowPath.close();
        final Paint backgroundPaint = getFillPaint(COLOR_BACKGROUND);
        return new MilestoneManager( // display an arrow at 500m every 1km
                new MilestoneMeterDistanceLister(500),
                new MilestonePathDisplayer(0, true, arrowPath, backgroundPaint) {
                    @Override
                    protected void draw(final Canvas pCanvas, final Object pParameter) {
                        final int halfKilometers = (int)Math.round(((double)pParameter / 500));
                        if (halfKilometers % 2 == 0) {
                            return;
                        }
                        super.draw(pCanvas, pParameter);
                    }
                }
        );
5,开始图标
/**
     * Starting point
     * @since 6.0.2
     */
    private MilestoneManager getStartManager(final Bitmap pBitmap) {
        return new MilestoneManager(
                new MilestoneVertexLister(),
                new MilestoneBitmapDisplayer(0, true,
                        pBitmap, pBitmap.getWidth() / 2, pBitmap.getHeight() / 2) {
                    @Override
                    protected void draw(final Canvas pCanvas, final Object pParameter) {
                        if (0 != (int)pParameter) { // we only draw the start
                            return;
                        }
                        super.draw(pCanvas, pParameter);
                    }
                }
        );
    }
6,路径动画效果
    final MilestoneMeterDistanceSliceLister slicerForPath = new MilestoneMeterDistanceSliceLister();
    MilestoneManager  pathManager =  getAnimatedPathManager(slicerForPath)
    /**
     * Animated path
     * @since 6.0.2
     */
    private MilestoneManager getAnimatedPathManager(final MilestoneLister pMilestoneLister) {
        final Paint slicePaint = getStrokePaint(COLOR_POLYLINE_ANIMATED, LINE_WIDTH_BIG);
        return new MilestoneManager(pMilestoneLister, new MilestoneLineDisplayer(slicePaint));
    }
7,图片动画效果
        final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), org.osmdroid.library.R.drawable.next);
        final MilestoneMeterDistanceSliceLister slicerForIcon = new MilestoneMeterDistanceSliceLister();
        MilestoneManager  pathIconManager = getAnimatedIconManager(slicerForIcon, bitmap)
          /**
     * Animated icon
     * @since 6.0.2
     */
    private MilestoneManager getAnimatedIconManager(final MilestoneLister pMilestoneLister,
                                                    final Bitmap pBitmap) {
        return new MilestoneManager(
                pMilestoneLister,
                new MilestoneBitmapDisplayer(0, true, pBitmap,
                        pBitmap.getWidth() / 2, pBitmap.getHeight() / 2)
        );
    }
8,添加到Polyline
        final List<MilestoneManager> managers = new ArrayList<>();
        managers.add(getAnimatedPathManager(slicerForPath));
        managers.add(getAnimatedIconManager(slicerForIcon, bitmap));
        managers.add(getHalfKilometerManager());
        managers.add(getKilometerManager());
        managers.add(getStartManager(bitmap));
        line.setMilestoneManagers(managers);
9,整体代码
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;

import org.osmdroid.samplefragments.BaseSampleFragment;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.milestones.MilestoneBitmapDisplayer;
import org.osmdroid.views.overlay.milestones.MilestoneDisplayer;
import org.osmdroid.views.overlay.milestones.MilestoneLister;
import org.osmdroid.views.overlay.milestones.MilestoneManager;
import org.osmdroid.views.overlay.milestones.MilestoneMeterDistanceLister;
import org.osmdroid.views.overlay.milestones.MilestoneMeterDistanceSliceLister;
import org.osmdroid.views.overlay.milestones.MilestonePathDisplayer;
import org.osmdroid.views.overlay.milestones.MilestoneLineDisplayer;
import org.osmdroid.views.overlay.milestones.MilestoneVertexLister;
import org.osmdroid.views.overlay.Polyline;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Fabrice on 28/12/2017.
 * @since 6.0.0
 */

public class SampleRace extends BaseSampleFragment {

    public static final String TITLE = "10K race in Paris";

    private static final float LINE_WIDTH_BIG = 12;
    private static final float TEXT_SIZE = 20;
    private static final int COLOR_POLYLINE_STATIC = Color.BLUE;
    private static final int COLOR_POLYLINE_ANIMATED = Color.GREEN;
    private static final int COLOR_BACKGROUND = Color.WHITE;

    private double mAnimatedMetersSoFar;
    private boolean mAnimationEnded;

    /**
     * @since 6.0.3
     */
    private final List<GeoPoint> mGeoPoints = getGeoPoints();

    @Override
    public String getSampleTitle() {
        return TITLE;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        mMapView.post(new Runnable() {
            @Override
            public void run() {
                final BoundingBox boundingBox = BoundingBox.fromGeoPoints(mGeoPoints);
                mMapView.zoomToBoundingBox(boundingBox, false, 30);
            }
        });

        super.onActivityCreated(savedInstanceState);
    }

    @Override
    protected void addOverlays() {
        super.addOverlays();

        final Polyline line = new Polyline(mMapView);
        line.setColor(COLOR_POLYLINE_STATIC);
        line.setWidth(LINE_WIDTH_BIG);
        line.setPoints(mGeoPoints);
        line.getPaint().setStrokeCap(Paint.Cap.ROUND);
        final List<MilestoneManager> managers = new ArrayList<>();
        final MilestoneMeterDistanceSliceLister slicerForPath = new MilestoneMeterDistanceSliceLister();
        final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), org.osmdroid.library.R.drawable.next);
        final MilestoneMeterDistanceSliceLister slicerForIcon = new MilestoneMeterDistanceSliceLister();
        managers.add(getAnimatedPathManager(slicerForPath));
        managers.add(getAnimatedIconManager(slicerForIcon, bitmap));
        managers.add(getHalfKilometerManager());
        managers.add(getKilometerManager());
        managers.add(getStartManager(bitmap));
        line.setMilestoneManagers(managers);
        mMapView.getOverlayManager().add(line);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            final ValueAnimator percentageCompletion = ValueAnimator.ofFloat(0, 10000); // 10 kilometers
            percentageCompletion.setDuration(5000); // 5 seconds
            percentageCompletion.setStartDelay(1000); // 1 second
            percentageCompletion.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mAnimatedMetersSoFar = (float)animation.getAnimatedValue();
                    slicerForPath.setMeterDistanceSlice(0, mAnimatedMetersSoFar);
                    slicerForIcon.setMeterDistanceSlice(mAnimatedMetersSoFar, mAnimatedMetersSoFar);
                    mMapView.invalidate();
                }
            });
            percentageCompletion.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mAnimationEnded = true;
                }
            });
            percentageCompletion.start();
        }
    }

    /**
     * @since 6.0.2
     */
    private Paint getFillPaint(final int pColor) {
        final Paint paint = new Paint();
        paint.setColor(pColor);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        return paint;
    }

    /**
     * @since 6.0.2
     */
    private Paint getStrokePaint(final int pColor, final float pWidth) {
        final Paint paint = new Paint();
        paint.setStrokeWidth(pWidth);
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setColor(pColor);
        paint.setStrokeCap(Paint.Cap.ROUND);
        return paint;
    }

    /**
     * @since 6.0.2
     */
    private Paint getTextPaint(final int pColor) {
        final Paint paint = new Paint();
        paint.setColor(pColor);
        paint.setTextSize(TEXT_SIZE);
        paint.setAntiAlias(true);
        return paint;
    }

    /**
     * Kilometer milestones
     * @since 6.0.2
     */
    private MilestoneManager getKilometerManager() {
        final float backgroundRadius = 20;
        final Paint backgroundPaint1 = getFillPaint(COLOR_BACKGROUND);
        final Paint backgroundPaint2 = getFillPaint(COLOR_POLYLINE_ANIMATED);
        final Paint textPaint1 = getTextPaint(COLOR_POLYLINE_STATIC);
        final Paint textPaint2 = getTextPaint(COLOR_BACKGROUND);
        final Paint borderPaint = getStrokePaint(COLOR_BACKGROUND, 2);
        return new MilestoneManager(
                new MilestoneMeterDistanceLister(1000),
                new MilestoneDisplayer(0, false) {
                    @Override
                    protected void draw(final Canvas pCanvas, final Object pParameter) {
                        final double meters = (double)pParameter;
                        final int kilometers = (int)Math.round(meters / 1000);
                        final boolean checked = meters < mAnimatedMetersSoFar || (kilometers == 10 && mAnimationEnded);
                        final Paint textPaint = checked ? textPaint2 : textPaint1;
                        final Paint backgroundPaint = checked ? backgroundPaint2 : backgroundPaint1;
                        final String text = "" + kilometers + "K";
                        final Rect rect = new Rect();
                        textPaint1.getTextBounds(text, 0, text.length(), rect);
                        pCanvas.drawCircle(0, 0, backgroundRadius, backgroundPaint);
                        pCanvas.drawText(text, -rect.left - rect.width() / 2, rect.height() / 2 - rect.bottom, textPaint);
                        pCanvas.drawCircle(0, 0, backgroundRadius + 1, borderPaint);
                    }
                }
        );
    }

    /**
     * Half-kilometer milestones
     * @since 6.0.2
     */
    private MilestoneManager getHalfKilometerManager() {
        final Path arrowPath = new Path(); // a simple arrow towards the right
        arrowPath.moveTo(-5, -5);
        arrowPath.lineTo(5, 0);
        arrowPath.lineTo(-5, 5);
        arrowPath.close();
        final Paint backgroundPaint = getFillPaint(COLOR_BACKGROUND);
        return new MilestoneManager( // display an arrow at 500m every 1km
                new MilestoneMeterDistanceLister(500),
                new MilestonePathDisplayer(0, true, arrowPath, backgroundPaint) {
                    @Override
                    protected void draw(final Canvas pCanvas, final Object pParameter) {
                        final int halfKilometers = (int)Math.round(((double)pParameter / 500));
                        if (halfKilometers % 2 == 0) {
                            return;
                        }
                        super.draw(pCanvas, pParameter);
                    }
                }
        );
    }

    /**
     * Animated path
     * @since 6.0.2
     */
    private MilestoneManager getAnimatedPathManager(final MilestoneLister pMilestoneLister) {
        final Paint slicePaint = getStrokePaint(COLOR_POLYLINE_ANIMATED, LINE_WIDTH_BIG);
        return new MilestoneManager(pMilestoneLister, new MilestoneLineDisplayer(slicePaint));
    }

    /**
     * Animated icon
     * @since 6.0.2
     */
    private MilestoneManager getAnimatedIconManager(final MilestoneLister pMilestoneLister,
                                                    final Bitmap pBitmap) {
        return new MilestoneManager(
                pMilestoneLister,
                new MilestoneBitmapDisplayer(0, true, pBitmap,
                        pBitmap.getWidth() / 2, pBitmap.getHeight() / 2)
        );
    }

    /**
     * Starting point
     * @since 6.0.2
     */
    private MilestoneManager getStartManager(final Bitmap pBitmap) {
        return new MilestoneManager(
                new MilestoneVertexLister(),
                new MilestoneBitmapDisplayer(0, true,
                        pBitmap, pBitmap.getWidth() / 2, pBitmap.getHeight() / 2) {
                    @Override
                    protected void draw(final Canvas pCanvas, final Object pParameter) {
                        if (0 != (int)pParameter) { // we only draw the start
                            return;
                        }
                        super.draw(pCanvas, pParameter);
                    }
                }
        );
    }

    /**
     * @since 6.0.2
     * TODO get a real list of geo points instead of this lousy manual list
     */
    private List<GeoPoint> getGeoPoints() {
        final List<GeoPoint> pts = new ArrayList<>();
        pts.add(new GeoPoint(48.85546563875735,2.359844067173981)); // saint paul
        pts.add(new GeoPoint(48.85737826660179,2.351524365470226)); // hôtel de ville
        pts.add(new GeoPoint(48.86253652215784,2.3354870181106264)); // louvre 1
        pts.add(new GeoPoint(48.86292409137066,2.3356209116511195)); // louvre 2
        pts.add(new GeoPoint(48.86989982398147,2.332474413449688)); // opéra loop 1
        pts.add(new GeoPoint(48.87019045840439,2.3327154218225985)); // opéra loop 2
        pts.add(new GeoPoint(48.87100070303335,2.332420856033508)); // opéra loop 3
        pts.add(new GeoPoint(48.871987070089496,2.3330367663197364)); // opéra loop 4
        pts.add(new GeoPoint(48.87285012531207,2.3319923967039813)); // opéra loop 5
        pts.add(new GeoPoint(48.87270041271832,2.33134970770962)); // opéra loop 6
        pts.add(new GeoPoint(48.87166121883793,2.330720408069368)); // opéra loop 7
        pts.add(new GeoPoint(48.87096547527885,2.331885281871564)); // opéra loop 8
        pts.add(new GeoPoint(48.87003193074662,2.3321932370146783)); // opéra loop 9
        pts.add(new GeoPoint(48.86989982398147,2.332474413449688)); // opéra loop 10
        pts.add(new GeoPoint(48.864306984328245,2.3350719481351234)); // rue de l'échelle 1
        pts.add(new GeoPoint(48.86316191644713,2.3338401275626666)); // rue de l'échelle 2
        pts.add(new GeoPoint(48.866209500723855,2.3235169355912433)); // rivoli
        pts.add(new GeoPoint(48.866729156977776,2.3223118937268623)); // concorde
        pts.add(new GeoPoint(48.86901910330005,2.3239721736289027)); // madeleine loop 1
        pts.add(new GeoPoint(48.8691952486765,2.3249897645366104)); // madeleine loop 2
        pts.add(new GeoPoint(48.87022568670458,2.325927019319977)); // madeleine loop 3
        pts.add(new GeoPoint(48.870489898165346,2.32583329384164)); // madeleine loop 4
        pts.add(new GeoPoint(48.87073649426996,2.3250165432446863)); // madeleine loop 5
        pts.add(new GeoPoint(48.87075410823092,2.3247085881016005)); // madeleine loop 6
        pts.add(new GeoPoint(48.86957395913612,2.323570493007452)); // madeleine loop 7
        pts.add(new GeoPoint(48.86901910330005,2.3239721736289027)); // madeleine loop 8
        pts.add(new GeoPoint(48.86664988772853,2.3224457872673554)); // concorde 1
        pts.add(new GeoPoint(48.866183077380335,2.3231420336778967)); // concorde 2
        pts.add(new GeoPoint(48.865610568177935,2.3231688123859726)); // concorde 3
        pts.add(new GeoPoint(48.86398108306007,2.321307692173235)); // concorde 4
        pts.add(new GeoPoint(48.863531864319754,2.3216022579623257)); // concorde 5
        pts.add(new GeoPoint(48.86047157217769,2.3306186871927252)); // pont césaire
        pts.add(new GeoPoint(48.859105908108276,2.336824405441064)); // mitterrand 1
        pts.add(new GeoPoint(48.858679130445125,2.3402407938844476)); // mitterrand 2
        pts.add(new GeoPoint(48.85792514768071,2.342640914879439)); // pont neuf
        pts.add(new GeoPoint(48.8563361600739,2.3489338967683864)); // pont notre dame
        pts.add(new GeoPoint(48.85582206974299,2.3509713700276507)); // pont d'arcole
        pts.add(new GeoPoint(48.85403498622509,2.3547049339593116)); // pont louis philippe
        pts.add(new GeoPoint(48.85303073607055,2.3575358780393856)); // pont marie
        pts.add(new GeoPoint(48.852894107137885,2.358500835434853)); // quai des célestins 1
        pts.add(new GeoPoint(48.85275705072659,2.3589590819111095)); // quai des célestins 2
        pts.add(new GeoPoint(48.852639573503986,2.3594411333991445)); // quai des célestins 3
        pts.add(new GeoPoint(48.85244769344759,2.3598755748636506)); // quai des célestins 4
        pts.add(new GeoPoint(48.85215399805951,2.360375480110463)); // quai des célestins 5
        return pts;
    }
}
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据提供的引用内容,u-navbar 组件中似乎没有提及有关白线的信息。因此,无法确定 u-navbar 组件是否具有一条白线。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [react-responsive-animate-navbar:React js 库 - 响应式动画导航栏](https://download.csdn.net/download/weixin_42131316/20716157)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [u-navbar组件在真机运行时undefined](https://blog.csdn.net/qq_49490164/article/details/123710656)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [u-navbar自定义标题背景随着页面滑动渐变](https://blog.csdn.net/oneya1/article/details/126303038)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值