一、需求
需要自定义配置数据的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()方法,把图片转成base64ready.onload = function () {var re = this.resultcanvasDataURL(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 = pathimg.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 = fontctx.fillStyle = fontColorctx.textAlign = 'center' // 水平居中 left center right ,positionX = fontWidth / 2const positionX = fontWidth / 2ctx.textBaseline = 'middle' // 垂直居中 top middle bottom, positionY = fontHeight / 2const positionY = fontHeight / 2ctx.fillText(String(fontText), positionX, positionY)ctx.font = fontTwoctx.fillStyle = fontTwoColorctx.fillText(String(fontTwoText), fontTwoPositionX, fontTwoPositionY)// 导出为图片数据URLconst 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.lengthconst 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.mapmapRef?.clearOverlays()// 生成的icon图片bgWidth背景宽高 要和 canvas画布宽高保持一致const bgWidth = 45const bgHeight = 48const 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},