自研地图控件/投入大半年研发/没有的时候好多人问/搞出来了又没人要/哎心好累

张开发
2026/4/11 22:53:15 15 分钟阅读

分享文章

自研地图控件/投入大半年研发/没有的时候好多人问/搞出来了又没人要/哎心好累
一、前言说明这个地图组件开发了大半年全身心的投入不断解决一个个难题终极对标产品是奥维地图他的那个地图组件确实做到了极致也是qt开发的至于是不是用到了其他qtlocation模块不知道他发布的是一个单文件。至于为什么要用纯qwidget绘制去实现这个组件前面也有提到过主要就是性能方面的考虑无论web怎么吹上天大量图形的绘制还是比不过本地CS架构的程序有些客户是很古老的电脑配置甚至一些国产机器匹配的是Qt4.8这种古老的版本再或者需要编译成wasm或者移动端运行纯qwidget的方案不要太好兼容性最强大唯一的缺点就是没有一些动画效果需要自己用代码实现而如果是qml则内置了这些效果直接几行代码就能搞定整体地图移动动画效果还一个就是qml大部分走的GPU绘制占用CPU这块相对来说低一些而纯qpainter绘制地图由于是一个小的瓦片地图组成的所以在每收到一个小瓦片的时候就需要填充绘制一次导致频繁瞬间不断的拖动地图在不断的下载和加载地图会占用一定的CPU个人实测在7%左右这个是瞬间造成的不是一直这个占用而且有内存缓存图片策略在下次加载到这个区域的瓦片时候如果内存存在该瓦片则先从内存取出来速度极快可能就一个中断。这个组件之前很多人问过有没有比如需要在很差的配置的电脑上运行不能用web浏览器方案有些需要在手机移动端运行甚至有个人还要在wasm网页上运行当初问的时候也没有备注登记现在搞出来了人又找不到了也不知道是谁哎事情往往就是这样全靠兴趣支撑哎心好累。二、效果图三、代码使用将core_mapwidget目录拷贝到你的项目目录并在pro中填写引入代码加入到你的项目中。$$PWD/…/表示上级目录。include($$PWD/../core_mapwidget/core_mapwidget.pri)引入头文件编写代码。#includemapwidget.h//创建地图控件MapWidget w;//设置瓦片源头w.setTileSource(TileSource_Tian);//设置瓦片类型w.setTileType(TileType_Satellite);//加载地图w.load();更详细的接口参考mapwidget.h头文件。#ifndefMAPWIDGET_H#defineMAPWIDGET_H#includetilehelper.h#includelayeroverlay.hclassMapWidget:publicQWidget{Q_OBJECTpublic:explicitMapWidget(QWidget*parent0);//设置唯一标识voidsetFlag(constQStringflag);protected:voidresizeEvent(QResizeEvent*);private://瓦片数据源TileSource tileSource;//瓦片类型TileType tileType;//是否离线booloffline;//离线目录QString offlinePath;//地图控件MapControl*mapControl;//图层锁QReadWriteLock layerMutex;//图形图层LayerOverlay*overlayLayer;privateslots://地图相关事件voidmouseEvent(intmouse_type,QMouseEvent*mouse_event,PointWorldCoord press_coord,PointWorldCoord current_coord);publicslots://加载地图voidload();//地图放大voidzoomIn();//地图缩小voidzoomOut();//重新绘制voidrequestRedraw();public://获取和设置缩放intgetZoom()const;voidsetZoom(intzoom);//获取和设置中心QPointFgetCenter()const;voidsetCenter(constQPointFpoint);//获取和设置区域QRectFgetRect()const;voidsetRect(constQRectFrect);//获取和设置绘图类型OverlayTypegetDrawType()const;voidsetDrawType(constOverlayTypedrawType);//获取地图控件MapControl*getMapControl();//设置绘图尺寸voidsetViewportSize(constQSizesize);//获取图形图层LayerOverlay*getOverlayLayer();//显示和隐藏图层voidsetLayerVisible(boolvisible);//获取图形集合QListOverlayBase*getOverlays();//获取指定图形OverlayBase*getOverlay(constQStringflag);//添加单个图形voidaddOverlay(OverlayBase*overlay,boolredraw);//删除单个图形voiddeleteOverlay(OverlayBase*overlay,boolredraw);//清空所有图形voidclearOverlay(boolredrawtrue);//显示比例尺voidenableScalebar(boolvisible);//显示十字线voidenableCrosshairs(boolvisible);//显示缩放控件voidenableZoomControls(boolvisible,AlignType alignAlignType_TopLeft);//启用布局鼠标事件voidenableLayerMouseEvents(boolenable);//启用地图拖曳voidenableDrag(boolenable);//启用键盘操作voidenableKeyboard(boolenable);//启用右键移动voidenableRightMove(boolenable);//启用滚轮缩放voidenableScrollWheelZoom(boolenable);//启用双击放大voidenableDoubleClickZoom(boolenable);//启用鼠标移动voidenableMouseTracking(boolenable);//设置瓦片源头voidsetTileSource(TileSource tileSource);//设置瓦片类型voidsetTileType(TileType tileType);//设置是否离线/离线目录voidsetOffline(booloffline);voidsetOfflinePath(constQStringofflinePath);//设置缓存目录voidsetCachePath(constQStringcachePath);//设置风格样式voidsetStyle(constQColorcolor);//保存当前瓦片整体地图图片voidsavePixmap(constQStringfileName,boolfullfalse,constQVectorQPointFpointsQVectorQPointF());//自动调整视图voidsetAutoView(constQRectFrect);voidsetAutoView(constQStringpoints);voidsetAutoView(constQVectorQPointFpoints);//添加和更新坐标点OverlayBase*addShape(constQStringflag,constQPointFpoint,constQColorcolor,intwidth);voidupdateShape(constQStringflag,constQPointFpointQPointF(),constQColorcolorQColor(),intwidth0);QPointFgetShapeCoord(constQStringflag);//添加和更新文本OverlayBase*addLabel(constQStringflag,constQPointFpoint,constQColorcolor,constQStringtext,intalign2,intsize15,introtate0);voidupdateLabel(constQStringflag,constQPointFpointQPointF(),constQColorcolorQColor(),constQStringtextQString(),intalign-1,intsize0,introtate-1);QPointFgetLabelPara(constQStringflag,QString*textNULL,int*rotateNULL);//添加和更新标注点OverlayBase*addMarker(constQStringflag,constQPointFpoint,constQStringimageQString(),constQPixmappixmapQPixmap(),introtate0,intalign5);voidupdateMarker(constQStringflag,constQPointFpointQPointF(),constQStringimageQString(),constQPixmappixmapQPixmap(),introtate-1,intalign-1);QPointFgetMarkerPara(constQStringflag,QPixmap*imageNULL,int*rotateNULL,int*alignNULL);//添加和更新折线OverlayBase*addPolyline(constQStringflag,constQStringListpoints,constQColorcolor,intwidth);OverlayBase*addPolyline(constQStringflag,constQVectorQPointFpoints,constQColorcolor,intwidth);voidupdatePolyline(constQStringflag,constQStringListpointsQStringList(),constQColorcolorQColor(),intwidth0);voidupdatePolyline(constQStringflag,constQVectorQPointFpointsQVectorQPointF(),constQColorcolorQColor(),intwidth0);QVectorQPointFgetPolylinePoints(constQStringflag);//添加和设置折线数据voidaddPolylineData(constQStringflag,constQPointFpoint);voidsetPolylineData(constQStringflag,constQVectorQPointFpoints);//添加和更新多边形OverlayBase*addPolygon(constQStringflag,constQStringListpoints,constQColorcolor,intwidth,constQColorbgColor);voidaddPolygon(constQStringflag,constQVectorQPointFpoints,constQColorcolor,intwidth,constQColorbgColor);voidupdatePolygon(constQStringflag,constQStringListpointsQStringList(),constQColorcolorQColor(),intwidth0,constQColorbgColorQColor());voidupdatePolygon(constQStringflag,constQVectorQPointFpointsQVectorQPointF(),constQColorcolorQColor(),intwidth0,constQColorbgColorQColor());QVectorQPointFgetPolygonPoints(constQStringflag);//添加和设置多边形数据voidaddPolygonData(constQStringflag,constQPointFpoint);voidsetPolygonData(constQStringflag,constQVectorQPointFpoints);//添加行政区划voidaddBoundary(constQStringflag,constQStringpoints,constQColorcolor,intwidth,constQColorbgColor);//添加和更新矩形OverlayBase*addRectangle(constQStringflag,constQPointFtopLeft,constQPointFbottomRight,constQColorcolor,intwidth,constQColorbgColor);voidupdateRectangle(constQStringflag,constQPointFtopLeftQPointF(),constQPointFbottomRightQPointF(),constQColorcolorQColor(),intwidth0,constQColorbgColorQColor());QRectFgetRectangleRect(constQStringflag);//添加和更新圆形OverlayBase*addCircle(constQStringflag,constQPointFpoint,qreal radius,constQColorcolor,intwidth,constQColorbgColor);voidupdateCircle(constQStringflag,constQPointFpointQPointF(),qreal radius0,constQColorcolorQColor(),intwidth0,constQColorbgColorQColor());QRectFgetCirclePara(constQStringflag,qreal*lngNULL,qreal*latNULL,qreal*radiusNULL);//添加和获取窗体voidaddWidget(constQStringflag,constQPointFpoint,QWidget*form);voidupdateWidget(constQStringflag,constQPointFpoint);QWidget*getWidget(constQStringflag);//删除单个图形voiddeleteOverlay(constQStringflag);//删除分组图形voiddeleteGroup(constQStringgroup);//设置图形顺序voidsetOverlayZIndex(constQStringflag,intzindex);//设置图形可见voidsetOverlayVisible(constQStringflag,boolvisible);//设置图形编辑voidsetOverlayEdit(constQStringflag,booledit);signals://图形相关事件voidoverlayEvent(inttype,OverlayBase*overlay);//地图相关事件voidmapEvent(inttype,boolright,constQPointFpoint);};#endif四、相关地址国内站点https://gitee.com/feiyangqingyun国际站点https://github.com/feiyangqingyun个人作品https://blog.csdn.net/feiyangqingyun/article/details/97565652文件地址https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码o05q 文件名bin_mapwidget.zip五、功能特点支持各种地图源包括天地图、高德地图、腾讯地图、谷歌地图、微软地图等。标准WGS-84地球坐标系采用默卡托投影可以拓展其他坐标系和投影规则。支持在线和离线两种场景需求可以自定义在线瓦片地址格式和离线瓦片地址格式。多线程下载和加载瓦片图片文件多线程绘制自动缓存瓦片文件。在线模式下可以开启是否缓存文件指定缓存路径将下载的瓦片文件存放到本地默认优先从缓存文件查找如果存在缓存文件则加载缓存文件不存在则联网下载。可以拖动地图鼠标滚轮放大和缩小地图以鼠标所在位置作为缩放中心点提供缩放控件手动单击进行操作。多图层机制支持多个瓦片叠加图层和图形绘制图层全部采用双缓冲技术所有的图形和瓦片全部绘制到一个图片文件上最终再将图片文件绘制到地图控件。不可见区域的图层包括覆盖物不会触发绘制降低CPU占用。预加载机制默认绘制的图层大小以当前区域往四周放大两倍这样在鼠标拖动和缩放的时候不会看到明显的加载过程体验更佳。内置了多种图形覆盖物包括坐标点、文本、标注点、折线、多边形、矩形、圆形等可以设置边框颜色粗细、填充颜色和透明度等参数。标注点支持旋转角度和提示文本其中提示文本可以设置在标注点的相对位置标注点图片支持gif动图可以动态切换静态图和动图。标注点和提示文本可以设置相对位置位置包括左侧、右侧、上侧、下侧、中间、左上角、右上角、左下角、右下角。标注点默认按照底部居中对齐一般圆形图标可以设置中心点对齐。标注点提示文本可设置背景颜色透明度、颜色边框和粗细支持换行和多行文字。所有的图形可以动态更新前景色、颜色粗细、背景颜色、颜色透明度等。支持删除单个图形、删除一种类型的图形、删除所有图形、隐藏单个或者所有图形等。支持动态绘制各种图形开启后直接在地图上鼠标按下绘制鼠标右键结束绘制非常方便快捷。在对应图形区域鼠标按下发出图形单击信号精准识别单击区域比如折线以鼠标在折线条上作为判断依据多边形区域以鼠标在整个多边形区域内为准而不是以矩形区域包括圆形也是以圆形内部为准。可以动态启动禁用比例尺、十字线、缩放控件、地图拖曳、键盘操作、滚轮缩放、双击放大、鼠标追踪等特性。可以任意指定经纬度区域进行瓦片拼接保存成图片文件也可以直接对整个可视区域或者缓存区域的地图图片文件保存。支持任意多边形轮廓保存成图片比如某个行政区的瓦片保存。图形可以动态设置zindex层叠顺序值越大越显示在前面内部维护着一个zindex表默认按照添加的先后顺序增加后面添加的显示在前面主动设置后按照设置的zindex来绘制。支持将QWidget对象作为覆盖物添加到地图控件中跟随地图移动位置极大提高灵活性比如可以将自定义控件直接作为地图控件的子对象加入进去。内置MarkerMove轨迹移动类支持历史轨迹数据回放和实时轨迹移动可设置图标、轨迹线的颜色和粗细、移动速度、移动间隔、平滑移动等支持多条轨迹线条同时移动。内置MarkerLine航迹规划类支持动态添加航迹点显示对应箭头可以动态拖曳调整航迹点的位置选中点高亮显示。大量使用按需绘制机制包括内部提供合理的默认值来触发绘制也可以手动传入参数指定是否需要立即绘制比如删除了某个覆盖物有些频繁的操作可以不指定立即绘制等操作完成后再统一一起绘制效率更高。默认开启缓存瓦片机制所有加载过的瓦片文件都存储在内存中下次再次绘制直接从内存取出来绘制既不需要从联网获取也不需要从缓存文件获取直接内存取出来绘制响应迅速效率最高体验最佳。支持批量添加覆盖物比如几万个标注点和圆形都是瞬间完成绘制相比web网页的方式性能提升百倍以上。支持街道图、卫星图、混合图、路网图等各种图层可以任意叠加N个图层甚至杂交不同地图厂家的瓦片文件。纯QWidget绘制非qml也非web不依赖qml或者浏览器控件支持极低性能的嵌入式环境。原创轻量级5000行代码架构漂亮注释详细拓展方便容易学习适合各种初学者和进阶者方便二次开发。支持任意Qt版本、任意系统、任意编译器包括嵌入式linux和各种国产电脑环境。古法编程不含任何AI代码品质保证。

更多文章