关于BaiduMap自定义覆盖物

最近公司要求做一个类似“支付宝到位”功能,要求头像从网上获取,还要求有背景,点击有背景 会进行更换。
BaiduMap提供我们的覆盖物的API中,只可以替换icon或icons

MarkerOptions ooA = new MarkerOptions().position(new LatLng(new Double(info.getBo_lat()), new Double(info.getBo_lng())))
                    .icon(bitmapDescriptor).extraInfo(bundle)
                    .zIndex(9).draggable(true);

可以看出只是提供给我们替换bitmap的方法,没有提供一个addView或者replaceView的方法。

1、思路

用一个ImageView,设置背景,用Glide去加载网络图片,然后得到从ImageView得到bitmap,设置给mapView

2、踩到的坑

  • 使用infoWindow的形式,但是infoWindow只能显示一个,查了很多资料,在android这方面没有找找解决的方式
  • 使用canvas绘制的方式,先绘制背景bitmap,在绘制头像,但是在将bitmap剪裁成圆形的bitmap时出了问题,setXfermode不管使用哪种规则,都会有造成bitmap上显示不完整。
  • 既然bitmap剪裁成圆形的bitmap除了问题,我自己写了一个CircleImageView,核心方法如下

    float h = getMeasuredHeight()- 3.0f;
    float w = getMeasuredWidth()- 3.0f;
    if (path == null) {
    path = new Path();
    path.addCircle(
    w/2.0f
    , h/2.0f
    , (float) Math.min(w/2.0f, (h / 2.0))
    , Path.Direction.CCW);
    path.close();
    }
    cns.drawCircle(w/2.0f, h/2.0f, Math.min(w/2.0f, h / 2.0f) + 1.5f, paint);
    int saveCount = cns.getSaveCount();
    cns.save();
    cns.setDrawFilter(mPaintFlagsDrawFilter);
    cns.clipPath(path, Region.Op.REPLACE);
    cns.setDrawFilter(mPaintFlagsDrawFilter);
    cns.drawColor(Color.WHITE);
    super.onDraw(cns);
    cns.restoreToCount(saveCount);

    采用剪裁画布的方式得到圆形,可以取得圆形bitmap了,但是此时因为我数学不好,总是不能把他画到正确的位置上,只能暂时搁浅

  • 踩到了Glide加载网络图片显示慢的坑,bitmap经常性的不能得到正确的。
  • 使用

    imageView.setDrawingCacheEnabled(true);
    Bitmap bitmap = imageView.getDrawingCache();

    方式得到bitmap,但是总是为空,卡了很久,点进源码一看,有个判定

        ` if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
                return null;
           }`
    

    焕然大悟,未绘制的view只能得到空的bitmap,我的这个view不就没有显示吗!找到问题就好解决了,先想法让view显示,再取得bitmap,不就可以了

  • 最后一个坑,竟然是因为我自己写的CircleImageView,因为对画布进行了剪裁,无法正确的得到背景图片。

3、实现方式

//先用Glide加载图片,防止无法取得正确bitmap
    private void initBitmap(List<OrderList.DatasBean.OrderListBean> orderList) {

        for (OrderList.DatasBean.OrderListBean orderListBean : orderList) {
            View view = View.inflate(getActivity(), R.layout.map_icon, null);
            ImageView mapIcon = (ImageView) view.findViewById(R.id.iv_icon);
            Glide.with(getActivity())
                    .load(orderListBean.getMember_avatar())
                    .into(mapIcon);

            mDescriptors.add(view);
        }

    }
            View view = mDescriptors.get(i);
            InfoWindow infoWindow = new InfoWindow(view, new LatLng(new Double(info.getBo_lat()), new Double(info.getBo_lng())), 0);
            //显示InfoWindow
            mBaiduMap.showInfoWindow(infoWindow);
            //取得正确的bitmap
            ImageView imageView = (ImageView) view.findViewById(R.id.iv_icon);
            imageView.setDrawingCacheEnabled(true);
            Bitmap bitmap = imageView.getDrawingCache();
            BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap);

            MarkerOptions ooA = new MarkerOptions().position(new LatLng(new Double(info.getBo_lat()), new Double(info.getBo_lng())))
                    .icon(bitmapDescriptor).extraInfo(bundle)
                    .zIndex(9).draggable(true);
            // 掉下动画
            ooA.animateType(MarkerOptions.MarkerAnimateType.drop);
            mBaiduMap.addOverlay(ooA);
            //关闭InfoWindow
            if (i == mAllOrderList.size() - 1) {
                mBaiduMap.hideInfoWindow();
            }

ok,完美显示

4、感悟

遇到问题总是想着百度,不自己沉入代码中研究,总是与在百度中有无法解决的问题,有时候深入代码中学习,才能得到很好的解决方式。

附效果如图,第一次上传,不会压缩

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Vue中实现复杂自定义覆盖物可以使用百度地图API中提供的Overlay类和自定义覆盖物自定义覆盖物是指在地图上添加自己的DOM元素,可以通过DOM元素来实现自己的样式和交互效果。 下面是在Vue中实现复杂自定义覆盖物的步骤: 1. 安装vue-baidu-map 在终端中运行以下命令来安装vue-baidu-map: ``` npm install vue-baidu-map --save ``` 2. 注册vue-baidu-map组件 在Vue组件中注册vue-baidu-map组件: ``` import BaiduMap from 'vue-baidu-map' export default { components: { BaiduMap } } ``` 3. 在模板中添加地图 在模板中添加vue-baidu-map标签,并设置地图的中心点和缩放级别: ``` <template> <div> <BaiduMap :center="center" :zoom="zoom"></BaiduMap> </div> </template> <script> export default { data() { return { center: {lng: 116.404, lat: 39.915}, zoom: 15 } } } </script> ``` 4. 创建自定义覆盖物 在Vue组件的mounted()生命周期函数中,创建自定义覆盖物: ``` mounted() { const map = this.$refs.baiduMap.getBMap() const BMap = window.BMap const CustomOverlay = function(point, options) { this._point = point this._options = options } CustomOverlay.prototype = new BMap.Overlay() CustomOverlay.prototype.initialize = function(map) { this._map = map const div = document.createElement('div') div.style.position = 'absolute' div.style.width = '100px' div.style.height = '100px' div.style.background = '#fff' div.style.borderRadius = '50%' div.style.boxShadow = '0 0 15px rgba(0, 0, 0, 0.3)' div.style.cursor = 'pointer' div.innerHTML = '<span>自定义覆盖物</span>' div.addEventListener('click', () => { console.log('自定义覆盖物被点击了') }) map.getPanes().labelPane.appendChild(div) this._div = div return div } CustomOverlay.prototype.draw = function() { const pixel = this._map.pointToOverlayPixel(this._point) this._div.style.left = pixel.x - 50 + 'px' this._div.style.top = pixel.y - 50 + 'px' } const point = new BMap.Point(116.404, 39.915) const myOverlay = new CustomOverlay(point) map.addOverlay(myOverlay) } ``` 在上面的代码中,我们创建了一个CustomOverlay类,它继承了BMap.Overlay类,用于创建自定义覆盖物。在CustomOverlay类的initialize方法中,我们创建了一个DIV元素,并设置了DIV元素的样式和内容。我们将DIV元素添加到地图的labelPane层中,这样它就可以显示在其他标注之上了。在CustomOverlay类的draw方法中,我们将DIV元素的位置设置自定义覆盖物的位置。 5. 添加CSS样式 最后,我们需要添加CSS样式来定义自定义覆盖物的样式: ``` <style> .custom-overlay { position: absolute; width: 100px; height: 100px; background: #fff; border-radius: 50%; box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); cursor: pointer; } </style> ``` 在上面的代码中,我们定义了".custom-overlay"类来设置自定义覆盖物的样式。 这样就可以在Vue中实现复杂自定义覆盖物了。可以根据需要修改CustomOverlay类的实现,来实现更复杂的自定义覆盖物
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值