骚操作!解决百度地图marker太多卡顿问题

用过百度地图的小伙伴应该都知道,百度地图的marker太多的时候会造成地图加载卡顿。这个问题其实可以通过海量点来解决,但是海量点的图标实在太丑了,我们家UI不干,所以只能另辟蹊径啦

原理

其实原理很简单,使用的是百度地图的CanvasLayer,直接在地图上画一层canvas。

 demo代码:

 var mp = new BMap.Map("container");
    mp.centerAndZoom(new BMap.Point(116.3964,39.9093), 10);
    mp.enableScrollWheelZoom();

    var canvasLayer = new BMap.CanvasLayer({
        update: update
    });

    function update() {
        var ctx = this.canvas.getContext("2d");

        if (!ctx) {
            return;
        }

        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

        var temp = {};
        ctx.fillStyle = "rgba(50, 50, 255, 0.7)";
        ctx.beginPath();
        var data = [
            new BMap.Point(116.297047,39.979542),
            new BMap.Point(116.321768,39.88748),
            new BMap.Point(116.494243,39.956539)
        ];

        for (var i = 0, len = data.length; i < len; i++) {
            var pixel = mp.pointToPixel(data[i]);
            ctx.fillRect(pixel.x, pixel.y, 30, 30);
        }
    }
    mp.addOverlay(canvasLayer);

在update方法里,this.canvas代表的是当前的canvas对象,其余的代码和写canvas没有什么区别,但是写原生的canvas太费脑子了,所以可以使用canvas库来简化一下代码。

代码实现

canvas库我使用了zrender,zrender不能说是最好用,但是我用顺手了习惯了。

<template>
    <div class="map-board">
        <div id="mapBoard" style="width:100%;height:100%;"></div>
        <div class="tool-tip-wrapper" ref="tooltip">
            <div class="tool-tip-container" v-if="curPoint">
                <span>测点名称{{curPoint.name}}</span>
            </div>
        </div>
    </div>
</template>

<script>
    import * as zrender from 'zrender'  //引入zrender库

    export default {
        data(){
          return {
              zr:null, 
              curPoint:null,
              canvasWidth:0,
              canvasHeight:0,
              pointArr:[
                  {name:'测点1',position:new BMap.Point(116.297047,39.979542)},
                  {name:'测点2',position:new BMap.Point(116.321768,39.88748)},
                  {name:'测点3',position:new BMap.Point(116.494243,39.956539)}
              ]
          }
        },
        mounted() {
            var mp = new BMap.Map("mapBoard");
            mp.centerAndZoom(new BMap.Point(116.3964,39.9093), 10);
            mp.enableScrollWheelZoom();

            let that = this

            var canvasLayer = new BMap.CanvasLayer({
                update: update
            });

            function update() {
                if(!this.zr) {
                    that.zr = zrender.init(this.canvas); //初始化zrender
                    that.canvasWidth = that.zr.getWidth();
                    that.canvasHeight = that.zr.getHeight();
                }else{
                    that.zr.clear() //先清空之前的
                }

                for (var i = 0, len = that.pointArr.length; i < len; i++) {
                    var pixel = mp.pointToPixel(that.pointArr[i].position);
                    var circle = new zrender.Image({
                        style: {
                            image:"/static/2dicon/zd0.png", //这张是我自己本地的一张图片
                            x: pixel.x - 15,
                            y: pixel.y - 36,
                            width:30,
                            height:36
                        },
                        data:that.pointArr[i]
                    });
                    //点击事件
                    circle.on('click',(e) => {
                        console.log(e)
                    })
                    //鼠标移入
                    circle.on('mousemove',(ev)=>{
                        that.showDetailWindow(ev)
                    })
                    //鼠标移出
                    circle.on('mouseout',(e)=>{
                        that.hideDetailWindow(e)
                    })
                    that.zr.add(circle);
                }
            }
            mp.addOverlay(canvasLayer);
            
            //根据点的位置自动设置地图的视口
            mp.setViewport(this.pointArr.map(item => item.position))
        },
        methods:{
            /*
      * 显示浮层位置,并且设置数据
      * */
            showDetailWindow(e){
                this.$refs.tooltip.style.display = 'block'

                //计算一下浮层的位置
                let top = 0;
                let left = 0;

                if (e.offsetX + 270 > this.canvasWidth) {
                    left = e.offsetX - 270
                } else {
                    left = e.offsetX
                }

                if(e.event.pageY + this.$refs.tooltip.clientHeight + 10 > window.innerHeight){
                    top = e.offsetY - this.$refs.tooltip.clientHeight - 10
                }else{
                    top = e.offsetY
                }

                //设置一下浮层的位置
                this.$refs.tooltip.style.top = (top + 10) + 'px'
                this.$refs.tooltip.style.left = (left + 10) + 'px'
                this.curPoint = e.target.data
            },
            /*
            * 隐藏浮层
            * */
            hideDetailWindow(e){
                this.$refs.tooltip.style.display = 'none'
                this.curPoint = null
                if(this.infoid) {
                    document.getElementById(this.infoid).style.display = 'none'
                }
            },
        }
    }
</script>

<style lang="scss" scoped>
    .map-board{
        height:100%;
        position: relative;
        .tool-tip-wrapper{
            position:absolute;
            display: none;
            border-radius: 10px;
            width:250px;
            padding:10px;
            background: rgba(0,0,0,0.5);
            color:#fff;
            line-height: 25px;
        }
    }
</style>

好啦。。来看下效果

放上6000个点也不卡哦:

好啦~问题解决啦~

后记

有很多朋友会遇到缩放后点偏位的问题,这个问题只需要加上一行就行啦,这是由于缩放之后zrender的画布像素尺寸没有变化导致的。

that.zr.resize()
  • 15
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 26
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值