按配置数据绘制配置型地图marker的icon,自定义marker

3 篇文章 0 订阅

一、需求

需要自定义配置数据的marker,其中图片内容要灵活可配置自动生成。此处项目用的百度地图。

效果图:

二、思路

用背景图+canvas绘制数字的方式生成icon的图片资源。

再将icon生成对应地图marker。

三、代码

canvasImg.js
<!--
* @description canvasImg.js 背景图+绘制内容生成图片资源
* @author xw
!-->

export function addFontWithBgImg(file, params, callback) {
    var ready = new FileReader()
    /* 开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
    ready.readAsDataURL(file) // 调用reader.readAsDataURL()方法,把图片转成base64
    ready.onload = function () {
        var re = this.result
        canvasDataURL(re, params, callback)
    }
}

/**
 * path 背景图资源路径
 * params:{ bgImgStyle: 'no-repeat', bgWidth: 35, bgHeight: 48, fontText: 1, fontWidth: 35, fontHeight: 35, font: 'bold 20px PingFangSC', bgc: '#0081FF', fontColor: '#fff' }
 * callback
 *      bgImgStyle = [
            "no-repeat", // 不平铺
            "repeat-x", // 横向平铺
            "repeat-y", // 纵向平铺
            "repeat" // 全画布平铺
        ];
 * */
export function canvasDataURL(path, params, callback) {
    const defaultOptions = {
        bgImgStyle: 'no-repeat',
        bgWidth: 45,
        bgHeight: 48,
        bgc: '#0081FF',
        fontText: 1, // 图片正中 大数字
        font: 'bold 20px PingFangSC',
        fontWidth: 34,
        fontHeight: 39,
        fontColor: '#0081FF',
        fontTwoText: 1, // 右上角 小数字
        fontTwo: 'bold 10px PingFangSC',
        fontTwoColor: '#fff',
        fontTwoPositionX: 35,
        fontTwoPositionY: 10,
    }
    const options = Object.assign(defaultOptions, params)
    const { bgImgStyle, bgWidth, bgHeight, fontText, fontWidth, fontHeight, font, bgc, fontColor, fontTwoText, fontTwo, fontTwoColor, fontTwoPositionX, fontTwoPositionY } = options
    // console.log('createNumberImg()-options', options)
    const img = new Image()
    img.src = path
    img.onload = function () {
        const canvas = document.createElement('canvas');
        // document.body.appendChild(canvas); //将画布添加到页面上
        // 设置画布大小
        canvas.width = bgWidth;
        canvas.height = bgHeight;
        // context 获取2D上下文
        const ctx = canvas.getContext('2d');
        // 清空画布内容
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        // ctx.fillStyle = ctx.createPattern(img, bgImgStyle);
        // ctx.fillRect(0, 0, canvas.width, canvas.height);
        // ctx.fill();
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height)  //绘制背景图片

        // 背景色 部分,会覆盖背景图, 背景色做背景 和 背景图做背景 二选一
        // ctx.fillStyle = bgc
        // 背景画布设置完后,绘制第2层内容, 覆盖在背景上的 内容---ctxTwo--fillText
        // const ctxTwo = canvas.getContext('2d');
        ctx.font = font
        ctx.fillStyle = fontColor
        ctx.textAlign = 'center' // 水平居中 left center right ,positionX = fontWidth / 2
        const positionX = fontWidth / 2
        ctx.textBaseline = 'middle' // 垂直居中 top  middle bottom,  positionY = fontHeight / 2
        const positionY = fontHeight / 2
        ctx.fillText(String(fontText), positionX, positionY)

        ctx.font = fontTwo
        ctx.fillStyle = fontTwoColor
        ctx.fillText(String(fontTwoText), fontTwoPositionX, fontTwoPositionY)
        // 导出为图片数据URL
        const imageDataUrl = canvas.toDataURL('image/png', 1); // canvas.toDataURL('image/png', 1)
        // console.log("生成的图像资源链接:", imageDataUrl);
        callback(imageDataUrl)
    }

}


/**
 * 将以base64的图片url数据转换为Blob
 * @param urlData
 * 用url方式表示的base64图片数据
 */
export function convertBase64UrlToBlob(urlData) {
    const arr = urlData.split(',')
    const mime = arr[0].match(/:(.*?);/)[1]
    const bstr = atob(arr[1])
    let n = bstr.length
    const u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
    }
    return new Blob([u8arr], { type: mime })
}
具体使用
createIconImg() {
                // 图片资源 自己找几个bg 在项目里本地引用
                const iconNormal = require('@/assets/image/bg/normal.png');
                const iconDanger = require('@/assets/image/bg/danger.png'); 
                const iconInfo = require('@/assets/image/bg/info.png'); 
                const userImgMap = {
                    '0': iconInfo,
                    '1': iconNormal,
                    '2': iconNormal,
                    '3': iconDanger,
                }
                const fontColorMap = {
                    '0': '#666',
                    '1': '#0081FF',
                    '2': '#0081FF',
                    '3': 'red',
                }
const pointList = [
                    { lng: '113.939435', lat: '22.522226', completeStatus: '0', frequency: 1 },
                    { lng: '113.947254', lat: '22.524549', completeStatus: '1', frequency: 3 },
                    { lng: '113.945889',  lat: '22.520798', completeStatus: '2',  frequency: 4 },
                ]
                // 设置地图 marker ---此处用的百度地图--BMap--使用 canvasDataURL方法
                const markers = []
                if (BMap && pointList && pointList.length > 0) {
                    const mapRef = this.$refs.map
                    mapRef?.clearOverlays()
                    // 生成的icon图片bgWidth背景宽高 要和 canvas画布宽高保持一致
                    const bgWidth = 45
                    const bgHeight = 48
                    const iconSize = new BMap.Size(bgWidth, bgHeight)
                    const iconOptions = { offset: new BMap.Size(25, 50) }
                    pointList.forEach((em, idx) => {
                        const userImg = userImgMap[String(em.completeStatus) || '0']
                        const fontColor = fontColorMap[String(em.completeStatus) || '0']
                        const params = { bgWidth, bgHeight, fontText: String(idx+1), fontColor, fontTwoText: String(em.frequency)} 
                        // 生成图片资源
                        canvasDataURL(userImg, params, function (imgUrl) {
                            const siteMarker = this.createMarker(mapRef, imgUrl, iconSize, iconOptions, item, index)
                            markers.push(siteMarker)
                        })
                    })
                    setTimeout(() => { 
                        const centerPoint = new BMap.Point(Number(selectRow.pointList[0]?.lng), Number(selectRow.pointList[0]?.lat));
                        mapRef.centerAndZoom(centerPoint, 15)
                    }, 300)
                }
            },
            createMarker(mapRef, iconImg, item, index) {
                const siteIcon = new BMap.Icon(
                    iconImg,
                    iconSize,
                    iconOptions,
                )
                const sitePoint = new BMap.Point(Number(item.lng), Number(item.lat));
                const siteMarker = new BMap.Marker(sitePoint, {
                    icon: siteIcon
                })
                // siteMarker.lisaSiteInfo = item // lisaSiteInfo自定义字段 主要装item信息,在InfoWindow的innerHtml时使用
                // const newHtml = '<div class="">我是innerHtml</div>'
                // console.log('newHtml', newHtml)
                // const infoWindow = new BMap.InfoWindow({
                //     content: newHtml,
                //     InfoWindowOptions: {
                //         width: 400,
                //         height: 300,
                //         enableAutoPan: true,
                //     }
                // })
                siteMarker.on('click', function () {
                    alert("carText模拟触发了地图click事件!");
                    // console.log('mapRef', mapRef)
                    // mapRef.openInfoWindow(infoWindow, sitePoint); //开启信息窗口
                })
                mapRef.addOverlay(siteMarker)
                return siteMarker
            },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值