<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
當Mapbox升級到V10(我直接到當前的最新V10.3)版本後,就可以就此實現自己想要實現的功能。
官方檔案 (docs.mapbox.com/android/map…)上的一些case就不在重複了
UISettings:
PreV10 通過MapView 拿到UISettings, 然後控制相關屬性,V10 UISettings已經被移除了,不再統一管理,比較分散。
參見相關屬性的控制:
mMapView.compass.visibility = false mMapView.logo.enabled = false mMapView.attribution.enabled = false mMapView.gestures.updateSettings { null }//控制無法觸控
PreV10 與 V10 的Camera 相關的animation (涉及到用到的Point,PreV10 之前有LatLn, Point 兩個類,當時還覺得為啥弄兩個,比較冗餘,V10裡面拿掉了LatLn保留Point,注意的是Point構造時 longitude為第一個prarams. )
fun moveCamera( mapView: MapView, originalList: List<Point>, paddingStart: Double, paddingTop: Double, paddingEnd: Double, paddingBottom: Double ) { if (originalList.isEmpty()) { return } val mapboxMap = mapView.getMapboxMap() val camera = mapboxMap.cameraForCoordinates(originalList, EdgeInsets(paddingTop, paddingStart, paddingBottom, paddingEnd)) mapView.camera.flyTo(camera) // mapboxMap.setCamera(camera) }
camera動畫之後,animationEnd 後的回撥 需求時,傳入animationOptions給 easeTo(),如下實現:
fun easeCamera(mapView:MapView, originalList: List<Point>, margin: Double, duration: Long, actionAfter: (() -> Unit)? = null){ if (originalList.isEmpty()) { return } val animationOptions = MapAnimationOptions.mapAnimationOptions { duration(duration) // owner(MapAnimationOwnerRegistry.GESTURES) animatorListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator?) { actionAfter?.invoke() } }) } val mapboxMap = mapView.getMapboxMap() val camera = mapboxMap.cameraForCoordinates(originalList, EdgeInsets(margin, margin, margin, margin)) mapView.camera.easeTo(camera, animationOptions) }
LatlngBounds:
Pre10 之前的類,並且可以通過 List 建立一個 LatlngBounds, 然後 getCenter(), V10中直接拿掉了 LatLngBounds, 也就沒有獲取List 對應的 getCenter()了,沒有仔細地去找API是否有相對應的替代,直接自己用擴充套件實現了一下:
@JvmStatic fun getCenter(originalList: List<Point>): Point? { if (originalList.isEmpty()) { return null } if (originalList.size < 2) { return originalList[0] } val multiPoint = MultiPoint.fromLngLats(originalList) val boundingBox = multiPoint.createBoundingBoxFromPoints() return boundingBox?.getCenter() }
涉及到兩個類 BoundingBox 及 MultiPoint, 在兩個類上新增擴充套件方法:
/** ** 通過 southwest、northeast 兩個點構建 BoundingBox 物件 **/ fun MultiPoint.createBoundingBoxFromPoints(): BoundingBox?{ val coordinates = coordinates() if (coordinates.size > 1){ var minLat: Double = MAX_LATITUDE var minLon: Double = MAX_LONGITUDE var maxLat: Double = MIN_LATITUDE var maxLon: Double = MIN_LONGITUDE for (gp in coordinates) { val latitude: Double = gp.latitude() val longitude: Double = gp.longitude() minLat = Math.min(minLat, latitude) minLon = Math.min(minLon, longitude) maxLat = Math.max(maxLat, latitude) maxLon = Math.max(maxLon, longitude) } val southwest = Point.fromLngLat(minLon, minLat) val northeast = Point.fromLngLat(maxLon, maxLat) return BoundingBox.fromPoints(southwest, northeast) } return null } /** ** 擴充套件BoundingBox getCenter()方法。 **/ fun BoundingBox.getCenter(): Point { val centerLon = (southwest().longitude() + northeast().longitude())/2.0 val centerLat = (southwest().latitude() + northeast().latitude())/2.0 return Point.fromLngLat(centerLon, centerLat) }
V10 新增了DSL build 新增 source、layer,相對而言source、layer都比較集中在builder{}的 block裡,實際應用中通常source、layer 的新增都是分離的,動態的,通過sourceID, layerId 找到對應的 source、layer然後修改裡面的內容, 發現 addLayerBelow(layer, layId) 該方法不好使,Crash了,暫且不用它了。 SymbolLayer 相比之前的api介面,少了一個 style.addImages(imagesMap), 不再支援一次性新增多個Image,新增一個簡單的擴充套件函數即可。
fun Style.addImages(imageMap: Map<String, Bitmap>) { imageMap.forEach { (t, u) -> addImage(t, u) } }
建立SymbolLayer 及 Source (Feature)的case
private fun createSymbolLayer( layerId: String, sourceId: String, isChangeStyle: Boolean, offsetY: Float ): SymbolLayer { return symbolLayer(layerId, sourceId){ iconImage(PROPERTY_ICON_NAME_PATTERN) iconAllowOverlap(true) iconSize(if (isChangeStyle) 1.0 else 0.0) iconIgnorePlacement(true) iconOffset(listOf(0.0, offsetY.toDouble())) } } // 控制iconSize 大小是方便做動畫。 private fun createSymbolBitmap(latLng: Point, markerStr: String, markerParams: MarkerParams?) { val feature = Feature.fromGeometry(Point.fromLngLat(latLng.longitude(), latLng.latitude())) val bitmap = createMarkerBitmap(mContext, markerParams!!) feature.addStringProperty(PROPERTY_ICON_NAME, markerStr) imagesMap[markerStr] = bitmap markerCoordinates.add(feature) }
新增對應的 source, Layer
style.addSource( geoJsonSource(END_SOURCE_ID){ featureCollection(FeatureCollection.fromFeatures(markerCoordinates)) } ) style.addLayer(endSymbolLayer)
同樣新增Layer前需要新增 source, List 構建 FeatureCollection, 如下:
mMapView.getMapboxMap().getStyle()?.addSource( geoJsonSource(sourceId){ featureCollection( FeatureCollection.fromFeatures( arrayOf( Feature.fromGeometry( LineString.fromLngLats(points) ) ) ) ) lineMetrics(true) // 注意這裡,繪製LineGradient 需要新增這行程式碼。 } )
新增單色的 LineLayer
mMapView.getMapboxMap().getStyle()?.addLayer( lineLayer(layerId, sourceId){ lineDasharray(listOf(0.01, 2.0)) lineCap(LineCap.ROUND) lineJoin(LineJoin.ROUND) lineWidth(TRACE_WIDTH.toDouble()) lineColor(pathColor) } )
繪製LineGradient, 先聊 Pre10的方案
/** * Defines a gradient with which to color a line feature. Can only be used with GeoJSON sources that specify `"lineMetrics": true`. * * @param expression an expression statement * @return property wrapper around an expression statement */ public static PropertyValue<Expression> lineGradient(Expression expression) { return new PaintPropertyValue<>("line-gradient", expression); } /** Produces continuous, smooth results by interpolating between pairs of input and output values ("stops"). The `input` may be any numeric expression (e.g., `["get", "population"]`). Stop inputs must be numeric literals in strictly ascending order. The output type must be `number`, `array<number>`, or `color`. Example usage: FillLayer fillLayer = new FillLayer("layer-id", "source-id"); fillLayer.setProperties( fillColor( interpolate( exponential(0.5f), zoom(), stop(1.0f, color(Color.RED)), stop(5.0f, color(Color.BLUE)), stop(10.0f, color(Color.GREEN)) ) ) ); Params: interpolation – type of interpolation number – the input expression stops – pair of input and output values Returns: expression See Also: Style specification */ public static Expression interpolate(@NonNull Interpolator interpolation, @NonNull Expression number, Stop... stops) { return interpolate(interpolation, number, Stop.toExpressionArray(stops)); }
以上只需建立 Expression.Stop[] stops, 根據List 中每個Point 的配速對應的色值,傳入即可,繪製LineGradient。
V10 中不再有 Expression 下 的Stop類,所以無從談起建立Stop[] 了,從官方的demo裡看 , 最後跟了不定的 stop{}, 可以看見是一個可變引數,所以打算構建一個 stop{} 的資料。
private fun createHeatmapLayer(): HeatmapLayer { return heatmapLayer( HEATMAP_LAYER_ID, EARTHQUAKE_SOURCE_ID ) { maxZoom(9.0) sourceLayer(HEATMAP_LAYER_SOURCE) // Begin color ramp at 0-stop with a 0-transparancy color // to create a blur-like effect. heatmapColor( interpolate { linear() heatmapDensity() stop { literal(0) rgba(33.0, 102.0, 172.0, 0.0) } stop { literal(0.2) rgb(103.0, 169.0, 207.0) } stop { literal(0.4) rgb(209.0, 229.0, 240.0) } stop { literal(0.6) rgb(253.0, 219.0, 240.0) } stop { literal(0.8) rgb(239.0, 138.0, 98.0) } stop { literal(1) rgb(178.0, 24.0, 43.0) } } ) ... ... } }
其實 stop{} 的原始碼如下, 所以需要提供一個高階函數的陣列
fun stop(block: ExpressionBuilder.() -> Unit) { this@ExpressionBuilder.apply(block) } //給Expression.InterpolatorBuilder 新增一個 stops()的擴充套件方法即可 fun Expression.InterpolatorBuilder.stops(stopList:Array<(Expression.ExpressionBuilder.() -> Unit)?>){ stopList.forEach { stop -> stop?.let { apply(it) } } } //將以上的擴充套件方法作為引數傳入 構建 Expression的最後一個引數, var colorExpression = Expression.interpolate{ linear() lineProgress() stops(colorStops) } //最後將 colorExpression 應用到構建lineLayer的 lineGradient(colorExpression) 作為引數即可,大功告成 mMapView.getMapboxMap().getStyle()?.addLayer( lineLayer(layerId, sourceId){ lineCap(LineCap.ROUND) lineJoin(LineJoin.ROUND) lineWidth(5.0) lineGradient(colorExpression) } )
到此這篇關於Android基於Mapbox V10 繪製LineGradient軌跡的文章就介紹到這了,更多相關Android Mapbox 繪製 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45