網(wǎng)站首頁 編程語言 正文
前言
當Mapbox升級到V10(我直接到當前的最新V10.3)版本后,就可以就此實現(xiàn)自己想要實現(xiàn)的功能。
官方文檔 (docs.mapbox.com/android/map…)上的一些case就不在重復了
UISettings:
PreV10 通過MapView 拿到UISettings, 然后控制相關屬性,V10 UISettings已經(jīng)被移除了,不再統(tǒng)一管理,比較分散。
參見相關屬性的控制:
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. )
普通的 camera
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 后的回調(diào) 需求時,傳入animationOptions給 easeTo(),如下實現(xiàn):
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 創(chuàng)建一個 LatlngBounds, 然后 getCenter(), V10中直接拿掉了 LatLngBounds, 也就沒有獲取List 對應的 getCenter()了,沒有仔細地去找API是否有相對應的替代,直接自己用擴展實現(xiàn)了一下:
@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)
}
Style設定Layer
V10 添加了DSL build 添加 source、layer,相對而言source、layer都比較集中在builder{}的 block里,實際應用中通常source、layer 的添加都是分離的,動態(tài)的,通過sourceID, layerId 找到對應的 source、layer然后修改里面的內(nèi)容, 發(fā)現(xiàn) addLayerBelow(layer, layId) 該方法不好使,Crash了,暫且不用它了。 SymbolLayer 相比之前的api接口,少了一個 style.addImages(imagesMap), 不再支持一次性添加多個Image,添加一個簡單的擴展函數(shù)即可。
fun Style.addImages(imageMap: Map<String, Bitmap>) {
? ?imageMap.forEach { (t, u) ->
? ? ? ?addImage(t, u)
? }
}
創(chuàng)建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)
繪制軌跡LineLayer
同樣添加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));
}
以上只需創(chuàng)建 Expression.Stop[] stops, 根據(jù)List 中每個Point 的配速對應的色值,傳入即可,繪制LineGradient。
V10 中不再有 Expression 下 的Stop類,所以無從談起創(chuàng)建Stop[] 了,從官方的demo里看 , 最后跟了不定的 stop{}, 可以看見是一個可變參數(shù),所以打算構建一個 stop{} 的數(shù)據(jù)。
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{} 的源碼如下, 所以需要提供一個高階函數(shù)的數(shù)組
? ?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)
? ? ? }
? }
}
?
//將以上的擴展方法作為參數(shù)傳入 構建 Expression的最后一個參數(shù),
var colorExpression = Expression.interpolate{
? ? ? ? ? ? ? ?linear()
? ? ? ? ? ? ? ?lineProgress()
? ? ? ? ? ? ? ?stops(colorStops)
? ? ? ? ? }
?
//最后將 colorExpression 應用到構建lineLayer的 lineGradient(colorExpression) 作為參數(shù)即可,大功告成
mMapView.getMapboxMap().getStyle()?.addLayer(
? ? ? ? ? ? ? ?lineLayer(layerId, sourceId){
? ? ? ? ? ? ? ? ? ?lineCap(LineCap.ROUND)
? ? ? ? ? ? ? ? ? ?lineJoin(LineJoin.ROUND)
? ? ? ? ? ? ? ? ? ?lineWidth(5.0)
? ? ? ? ? ? ? ? ?lineGradient(colorExpression)
? ? ? ? ? ? ? }
? ? ? ? ? )
原文鏈接:https://juejin.cn/post/7076033476700405768
相關推薦
- 2022-11-09 Python數(shù)據(jù)庫sqlite3圖文實例詳解_python
- 2023-04-24 Tensor?和?NumPy?相互轉(zhuǎn)換的實現(xiàn)_python
- 2022-07-03 C++超詳細講解隱藏私有屬性和方法的兩種實現(xiàn)方式_C 語言
- 2022-02-02 bat命令刪除文件夾
- 2023-11-21 什么是交叉編譯、交叉編譯有什么用,為什么需要交叉編譯
- 2022-06-16 HTTP服務壓力測試工具及相關術語講解_Golang
- 2023-04-04 python中class(object)的含義是什么以及用法_python
- 2023-03-22 一文帶你學會Python?Flask框架設置響應頭_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支