百度地图新业务需求视频模块与附近的功能:
提示:这次版本换了angular写
- 记录开发附近功能遇到的坑
视频模块:
视频模块
视频模块还是跟原来的一样定位加详情,不过这次版本新增了附近的功能和随机切换视频,随机切换到的定位还要高亮
下面来说说怎么实现了:
提示:虽然换了angular但是总体思路不变
功能点:
- 1.随机切换视频
- 2.附近的功能
- 3.video实现hls流播放
video实现hls流播放:
首先安装依赖 npm install --save-dev video.js
然后就是在angular.json下写入需要编译的包路径architect下面:
"node_modules/ng-devui/devui-layout.min.css",
"node_modules/video.js/dist/video-js.min.css",
然后在shared里面封装了video.component.ts组件
// videojs 整合angular https://videojs.com/guides/angular/
import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'
import videojs from 'video.js'
@Component({
selector: 'app-vjs-player',
template: ` <video #target class="video-js" controls muted playsinline preload="none"></video> `,
styleUrls: ['./video.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class VideoComponent implements OnInit, OnDestroy {
@ViewChild('target', { static: true }) target!: ElementRef
@Input()
options!: {
fluid?: boolean
aspectRatio?: string
autoplay?: boolean
sources?: {
src?: string
type?: string
}[]
}
player: any
constructor(private elementRef: ElementRef) {}
// Instantiate a Video.js player OnInit
ngOnInit() {
this.player = videojs(this.target.nativeElement, this.options, () => {})
this.player.errorDisplay.close()
}
// Dispose the player OnDestroy
ngOnDestroy() {
if (this.player) {
this.player.dispose()
}
}
}
然后在你需要的组件里面引入:
<app-vjs-player class="vehicle-video" *ngIf="show" [options]="options3"></app-vjs-player>
注意:angular和vue组件名不一样
然后你把src传入options里面就行了,下面说说切换播放时候的坑:
有切换视频业务 的同学你是不是发现直接修改options里面的src 没用啊?
*ngIf=“show” 就解决了这个问题,更新了dom 每次点击的时候改变show 状态就可以了
随机切换视频
随机切换视频原理很简单
ngOnInit(): void {
// this.cut(this.src)
this.cut()
this.videoRightSetInterval = setInterval(() => {
this.cut()
}, 30000)
}
定时任务就可以了
但是产品加了随机到的视频要高亮 还要切换视角过去,下面说说怎么实现的
随机视频是每次取3个,然后返回的视频URL是带有坐标的
//先创建一个随机高亮layer
this.randomLabelLayer = BMapGLLayerHelper.LabelLayer({
textAlign: 'center',
textColor: '#fff',
borderColor: 'rgba(179, 231, 248, 0.01)',
backgroundColor: 'rgba(37, 115, 255, 1)',
padding: [0, 0],
borderRadius: 12,
offset: [0, 0],
fontSize: 12,
// height: '30px',
lineHeight: 1,
collides: false, // 是否开启碰撞检测, 数量较多时建议打开
enablePicked: true,
})
//再把随机视频坐标塞进来就实现了
public randomVideoUrl(data?: any) {
BMapGLLayerHelper.setData(this.randomLabelLayer, data)
}
//至于视角切换什么的,早就封装了工具类 交给工具类去干吧
const mapOptions = {
center: { lng: res[0].geometry.coordinates[0], lat: res[0].geometry.coordinates[1] },
/** 地图缩放级别 */
zoom: 17,
}
this.layoutService.updateMap(mapOptions)
// 更新地图
public updateMap(options: BMapGLOptions) {
BMapGLHelper.update(this.map, options)
}
public static update(map: any, options: BMapGLOptions): void {
let tilt = Reflect.has(options, 'tilt') ? options.tilt : map.getTilt()
if (Reflect.has(options, 'center') && Reflect.has(options, 'zoom')) {
const zoom = options.zoom || 0
const center = new BMapGL.Point(options?.center?.lng, options?.center?.lat)
const currentZoom = map.getZoom()
if (currentZoom > zoom) {
// 先缩小后移动
map.setZoom(zoom, {
callback: () => {
map.setCenter(center, {
callback: () => {
map.setTilt(tilt)
},
})
},
})
} else if (currentZoom < zoom) {
// 先移动后
map.setCenter(center, {
callback: () => {
map.setZoom(zoom, {
callback: () => {
map.setTilt(tilt)
},
})
},
})
} else {
// 只移动
map.setCenter(center, {
callback: () => {
map.setTilt(tilt)
},
})
}
} else {
if (Reflect.has(options, 'zoom')) {
map.setZoom(options.zoom, {
callback: () => {
map.setTilt(tilt)
},
})
}
if (Reflect.has(options, 'center')) {
const center = new BMapGL.Point(options?.center?.lng, options?.center?.lat)
map.setCenter(center, {
callback: () => {
map.setTilt(tilt)
},
})
}
}
if (Reflect.has(options, 'tilt') && !(Reflect.has(options, 'center') || Reflect.has(options, 'zoom'))) {
map.setTilt(options.tilt)
}
if (Reflect.has(options, 'mapStyleV2')) {
map.setMapStyleV2({ styleJson: options.mapStyleV2 })
}
}
附近的服务----------------------------
附近的服务很简单:就是调了地图的画圆Api 然后渲染图标
介于我多个模块都需要用到附近的功能,所以我就封装了一个附近的服务 让其他服务去调用
// 创建一个nearbyservices.service.ts服务
export class NearbyserviceService {
private labelLayer?: any
private personnelIconLayer?: any
private VideoIconLayer?: any
private vehicleIconLayer?: any
private devicesIconLayer?: any
private view?: any
private queryParams?: any = {
name: '',
}
public NearbyEvent: EventEmitter<NearbyEvent> = new EventEmitter<NearbyEvent>()
public personalList?: any[]
}
// 申请注册图标我就不说了 附近的服务我是单独创建了图标的
// 接下来就是附近的功能了
public addPersonnelData(personnelData: any[], vehicleList?: any, devicesList?: any, videoList?: any): void {
this.initLayers(this.view)
BMapGLLayerHelper.setData(this.personnelIconLayer, personnelData)
BMapGLLayerHelper.setData(this.vehicleIconLayer, vehicleList)
BMapGLLayerHelper.setData(this.VideoIconLayer, videoList)
BMapGLLayerHelper.setData(this.devicesIconLayer, devicesList)
BMapGLViewHelper.showLayer(
this.view,
this.labelLayer,
this.personnelIconLayer,
this.VideoIconLayer,
this.vehicleIconLayer,
this.devicesIconLayer
)
}
// 然后通过点击附近的图标路由传参
if (e.dataItem.properties.type == 1) {
this.router.navigate(['/vehicle'], { queryParams: { item: JSON.stringify(e) } })
}
if (e.dataItem.properties.type == 2) {
this.router.navigate(['personnel'], { queryParams: { item: JSON.stringify(e) } })
}
if (e.dataItem.properties.type == 3) {
this.router.navigate(['videos'], { queryParams: { item: JSON.stringify(e) } })
}
if (e.dataItem.properties.type == 4) {
this.router.navigateByUrl('/devices')
this.layoutService.goBackEventEmitter.emit({
item: e,
})
}
this.layoutService.removeOverlay()
//画圆我放在了各个模块下面,下面我随便找一个示例
onClick(e: any): void {
console.log(e, 'eeee')
this.layoutService.removeOverlay()
const point = BMapGLLayerHelper.Point(e.dataItem.geometry.coordinates[0], e.dataItem.geometry.coordinates[1])
const circle = BMapGLOverlayHelper.Circle(point, 200, {
strokeColor: 'rgba(26, 211, 213, 1)',
fillColor: 'rgba(26,211,213,0.1)',
fillOpacity: 0.1,
strokeWeight: 2,
strokeOpacity: 0.5,
strokeStyle: 'dashed',
})
//封装的删除画园layer服务
this.layoutService.addOverlay(circle)
}