高德绘图工具研发

高德绘图工具缺点

  • 没有友好鼠标跟随文字提示功能
  • 不支持撤销,回退功能
  • 触发的事件只有draw事件,不能精确到每个节点的事件
  • 绘制完的图形保存方式太单一,只能加入到自己的覆盖物组,没有封装

研发的高德工具

基于高德提供的地图事件和键盘事件,来满足更为复杂的业务需求,精确到对每一个节点操作进行监听,参考代码在下面,目前只支持绘制点,线,矩形,多边形,圆目前还没有需求,所以还没开始做,但基于这个代码扩展起来很方便,以下是相对于高德绘图工具的优点:(源码在下面)

  • 绘制不同类型图形,鼠标不同的友好文字提示
  • 支持撤销,回退功能
  • 触发的事件支持更多,绘制完成事件,右键事件,绘制一个点事件,移动事件,开始事件
  • 绘制完图形保存方式支持,不保存,只保存当前,保存所有
  • 绘图次数支持绘制一次,和绘制多次

注意 :

  • AMap._rightMenu这个属性,因为不仅封装了绘图工具,同时封装了右键菜单工具,所以单击鼠标右键的时候会有冲突,所以启用绘图工具的时候会禁用右键菜单,完成释放右键菜单,封装的右键菜单包含地图放大,缩小,复位,移动,点击查询,后面有时间会给大家讲封装的右键菜单
  • 依赖于AMapTool文件,这个文件是生成默认的overlay,也可以自己编写生成overlay,那样就不依赖于其他文件。
  • 下面是绘图工具部分截图
    绘制多条线段
    绘制多条线段
    绘制多个矩形
    绘制多个矩形
    绘制单个点
    绘制单个点
    绘制单个矩形
    绘制单个多边形
define([
    'product/webgisPanda/AMapTool/AMapTool',
], function (AMapTool) {

    class AMapDrawTool {
        static geometrySymbol = {
            CircleMarker: {

            },
            Polyline: {
                strokeColor: '#80d8ff',
                bubble : true
            },
            Polygon: {
                fillColor: '#00b0ff',
                strokeColor: '#80d8ff'
            },
            Rectangle: {
                fillColor: '#00b0ff',
                strokeColor: '#80d8ff',
                fillOpacity: .7
            },
            Circle: {
                fillColor: '#00b0ff',
                strokeColor: '#80d8ff'
            }
        }
        static defaultTooltips = {
            CircleMarker: "单击鼠标左键选取,右键取消",
            Polyline: "单击鼠标左键开始绘制,ESC撤销,右键取消",
            Polygon: "单击鼠标左键开始绘制,ESC撤销,右键取消",
            Rectangle: "按下鼠标左键拖动开始绘制,右键取消",
            StepByStep: "单击鼠标左键开始绘制",
            Circle: "鼠标单击选取圆心,右键取消",
            Circleing: "再次点击鼠标左键确认圆,右键取消",
        }
        constructor(options) {
            this.type = options.type || 'CircleMarker'
            this.map = options.map
            this.geometrySymbol = options.geometrySymbol || AMapDrawTool.geometrySymbol[this.type]
            this.drawHandles = []
            this.toolTip = options.toolTip || AMapDrawTool.defaultTooltips[this.type]
            this.cursor = this.defaultCursor || 'default'
            this.drawMethod = options.drawMethod || 'once'  //绘图次数, 1次或者多次  value : once or repeat
            this.saveOverlayStatus = options.saveOverlayStatus || 'saveNot'  //绘制的图形是否保存 自动清除 : saveNot , 保持1次 : saveOnce , 保持无限次 : saveMore 
            this.rightMenuHandleOverlays = options.rightMenuHandleOverlays || 'clear' // 默认右键菜单是清除,也可以保存 value =>clear save
            this.addToolTip()
            this.addOverlayGroup()
        }
        addToolTip() {
            let $container = $(this.map.getContainer())
            if ($container.find('#AMap-toolTip').length < 1) $container.append(`<div id="AMap-toolTip" style="position: absolute;left: -9999px;background-color: #fff;color: #333;padding: 2px;font-size: 12px;border: 1px solid red;border-radius: 3px;pointer-events: none;">${this.toolTip}</div>`)
            this.$tipContainer = $container.find('#AMap-toolTip')
            return this.$tipContainer
        }
        addOverlayGroup() {
            this.overlayGroup = new AMap.OverlayGroup()
            this.overlayGroup.setMap(this.map)
        }
        destoryOverlayGroup() {
            if(this.overlayGroup){
                this.overlayGroup.setMap(null)
                this.overlayGroup = null
            }
        }
        destory() {
            this.destoryTip()
            this.destoryEvents()
            this.destoryOverlayGroup()
            this.relaseMapDrag()
        }
        destoryEvents(){
            this.drawHandles.map(function (drawHandle) {
                AMap.event.removeListener(drawHandle)
            })
            this.drawHandles = []
        }
        destoryTip(){
            if(this.$tipContainer){
                this.$tipContainer.remove()
                this.$tipContainer = null
            }
        }
        hideTip(){
            if(this.$tipContainer)  this.$tipContainer.hide()
        }
        showTip(){
            if(this.$tipContainer)  this.$tipContainer.show()
        }
        pause(){
            this.relaseMapDbClick()
            this.relaseMapDrag()
            this.$tipContainer.hide()
            this.isDrawing = false
        }
        resume(){
            this.$tipContainer.show()
            this.isDrawing = true
            this.stopMapDbClick()
            this.stopMapDrag()
        }
        cancelDraw(clearOverlay) {
            this.hideTip()
            this.destoryEvents()
            this.relaseMapDrag()
            this.relaseMapDbClick()
            if(clearOverlay) this.overlayGroup.clearOverlays()
        }
        drawBeforeEvent() {
            this.addToolTip().show()
            this.relaseMapDrag()
            this.overlayGroup.clearOverlays()
            this.destoryEvents()
            this.isDrawing = true
            if(AMap._rightMenu) AMap._rightMenu.enable = false
        }
        drawAfterEvent(){
            setTimeout(function(){
                if(AMap._rightMenu) AMap._rightMenu.enable = true
            }.bind(this), 20)
            this.relaseMapDrag()
        }
        draw(options) {
            let drawEnd = options.drawEnd || function () {} 
            let rightClick = options.rightClick || function () {}
            let drawPoint = options.drawPoint || function () {}  
            let drawing = options.drawing || function() {}
            let drawStart = options.drawStart || function () {}
            this.drawBeforeEvent()
            switch (this.type) {
                case "CircleMarker":
                    this.drawHandles.push(AMap.event.addListener(this.map, 'click', this.pointMouseDrawEndHandler.bind(this, drawEnd), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'mousemove', this.pointMouseMoveHandler, this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'rightclick', this.pointMouseRightClickHandler.bind(this, rightClick), this))
                    break
                case "Polyline":
                    this.repaintDrawpolyline = true
                    this.drawHandles.push(AMap.event.addListener(this.map, 'dblclick', this.polylineMouseDbClickHandler.bind(this, drawEnd), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'mousemove', this.polylineMouseMoveHandler.bind(this, drawing), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'click', this.polylineMouseClickHandler.bind(this, drawPoint, drawStart), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'rightclick', this.polylineMouseRightClickHandler.bind(this, rightClick), this))
                    this.drawHandles.push(AMap.event.addDomListener($('body').get(0), 'keyup',this.polylineKeyupHandler.bind(this),this))
                    break
                case "Rectangle":
                    this.drawHandles.push(AMap.event.addListener(this.map, 'mousedown', this.rectangleMouseDownHandler.bind(this,drawStart), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'mousemove', this.rectangleMouseMoveHandler.bind(this, drawing), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'mouseup', this.rectangleMouseUpHandler.bind(this, drawEnd), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'rightclick', this.rectangleMouseRightClickHandler.bind(this, rightClick), this))
                    break
                case "Polygon" :
                    this.repaintDrawpolygon = true
                    this.drawHandles.push(AMap.event.addListener(this.map, 'dblclick', this.polygonMouseDbClickHandler.bind(this, drawEnd), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'mousemove', this.polygonMouseMoveHandler.bind(this, drawing), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'click', this.polygonMouseClickHandler.bind(this, drawPoint, drawStart), this))
                    this.drawHandles.push(AMap.event.addListener(this.map, 'rightclick', this.polygonMouseRightClickHandler.bind(this, rightClick), this))
                    this.drawHandles.push(AMap.event.addDomListener($('body').get(0), 'keyup',this.polygonKeyupHandler.bind(this),this))
                default:
                    break
            }
            this.map.setDefaultCursor(this.cursor)
        }
        /*****绘制点 ********/
        pointMouseMoveHandler(e){
            if(this.mouseEventStopAction()) return 
            this.mouseMoveTipHandler(e)
        }
        pointMouseRightClickHandler(rightClick, e){
            if(this.mouseEventStopAction()) return 
            this.rightClickCommon(rightClick)
        }
        pointMouseDrawEndHandler(drawEnd, e){
            if(this.mouseEventStopAction()) return 
            if(this.drawMethod == 'once'){
                if(this.saveOverlayStatus != 'saveNot'){
                    this.addOverlay({
                        type : 'CircleMarker',
                        coordinate : [e.lnglat.lng, e.lnglat.lat],
                        settings : this.geometrySymbol
                    })
                }
                this.cancelDraw()
                this.drawAfterEvent()
            }else if(this.drawMethod == 'repeat'){
                switch(this.saveOverlayStatus){
                    case "saveNot" :
                        break
                    case "saveOnce" :
                        this.overlayGroup.clearOverlays()
                        this.addOverlay({
                            coordinate : [e.lnglat.lng, e.lnglat.lat],
                            settings : this.geometrySymbol
                        })
                        break
                    case "saveMore" :
                        this.addOverlay({
                            coordinate : [e.lnglat.lng, e.lnglat.lat],
                            settings : this.geometrySymbol
                        })
                        break
                    default :
                        break
                } 
            }
            drawEnd(e)
        }

        /*****绘制点 ********/

        /*****绘制线 ********/
        polylineMouseClickHandler(drawPoint, drawStart, e){
            if(this.mouseEventStopAction()) return 
            this.commonMouseClickHander(this.repaintDrawpolyline, e)
            let polylines = this.overlayGroup.getOverlays()
            if(this.repaintDrawpolyline){
                this.repaintDrawpolyline = false
                let path = [
                    [e.lnglat.lng, e.lnglat.lat],
                    [e.lnglat.lng, e.lnglat.lat],
                ]
                let settings = _.extend(this.geometrySymbol, {
                    path,
                    extData : {
                        lng : e.lnglat.lng,
                        lat : e.lnglat.lat,
                    },
                    bubble : true
                })
                let polyline = this.addOverlay({
                    coordinate : [[e.lnglat.lng, e.lnglat.lat]],
                    settings
                })
                drawStart(polyline, polylines.length + 1)
                drawPoint(polyline)
            }else{
                let polyline = polylines[polylines.length - 1] 
                let path = polyline.getPath()
                path.push(e.lnglat)
                polyline.setPath(path)
                drawPoint(polyline)
            }
        }
        polylineMouseMoveHandler(drawing, e){
            if(this.mouseEventStopAction()) return 
            this.mouseMoveTipHandler(e)
            let polylines = this.overlayGroup.getOverlays()
            if(polylines && polylines[polylines.length - 1] && !this.repaintDrawpolyline){
                let polyline = polylines[polylines.length - 1] 
                let path = polyline.getPath()
                path.pop()
                path.push(e.lnglat)
                polyline.setPath(path)
                drawing(polyline)
            }
        }
        polylineMouseDbClickHandler(drawEnd, e){
            if(this.mouseEventStopAction()) return 
            this.relaseMapDrag()
            let polylines = this.overlayGroup.getOverlays()
            let polyline = polylines[polylines.length - 1]
            this.handleRepeatPath(polyline)
            if(this.drawMethod == 'once'){
                if(this.saveOverlayStatus == 'saveNot'){
                    this.overlayGroup.clearOverlays()
                }
                this.cancelDraw()
                this.drawAfterEvent()
            }else if(this.drawMethod == 'repeat'){
                switch(this.saveOverlayStatus){
                    case "saveNot" :
                        this.overlayGroup.clearOverlays()
                        break
                    case "saveOnce" :
                        break
                    case "saveMore" :
                        break
                    default :
                        break
                }
                this.repaintDrawpolyline = true
            }
            drawEnd(polyline)
        }
        handleRepeatPath(polyline){
            if(this.mouseEventStopAction()) return 
            let path = polyline.getPath()
            let flag = true
            while(flag && path.length > 2){
                let pathlast = path[path.length - 1]
                let pathLastSecond = path[path.length - 2]
                if(pathlast.lng == pathLastSecond.lng && pathlast.lat == pathLastSecond.lat){
                    path.pop()
                }else{
                    flag = false
                }
            }
            polyline.setPath(path)
        }
        polylineMouseRightClickHandler(rightClick){
            if(this.mouseEventStopAction()) return 
            this.rightClickCommon(rightClick)
        }
        polylineKeyupHandler(e){
            if(this.mouseEventStopAction()) return 
            if(e.key == 'Escape' || e.keyCode == 27){
                let polylines = this.overlayGroup.getOverlays()
                if(polylines.length == 0) return
                this.repaintDrawpolyline = false
                let polyline = polylines[polylines.length - 1] 
                let path = polyline.getPath()
                if(path.length == 0 && polylines.length >= 2) return this.overlayGroup.removeOverlay(polyline)
                if(path.length >= 3){
                    let pathLast = path[path.length - 1]
                    let pathTwo = path[path.length - 2]
                    if(pathLast.lng == pathTwo.lng && pathLast.lat == pathTwo.lat) path.pop()
                }
                path.pop()
                if(path.length == 1 && this.drawMethod == 'repeat'){
                    if(polylines.length > 1) {
                        this.overlayGroup.removeOverlay(polyline)
                        polyline = []
                    }
                    return
                }
                polyline.setPath(path)
            }
        }
        /*****绘制线 ********/

        /*****绘制矩形 ********/
        rectangleMouseDownHandler(drawStart, e){
            if(this.mouseEventStopAction()) return 
            if(e.originEvent.button != 0) return
            this.stopMapDrag()
            this.mouseMoveTipHandler(e)
            if(this.drawMethod == 'repeat') {
                switch(this.saveOverlayStatus){
                    case "saveNot" :
                        break
                    case "saveOnce" :
                        this.overlayGroup.clearOverlays()
                        break
                    case "saveMore" :
                        break
                    default :
                        break
                } 
            }
            let bounds = new AMap.Bounds(new AMap.LngLat(e.lnglat.lng, e.lnglat.lat), new AMap.LngLat(e.lnglat.lng, e.lnglat.lat))
            let settings = _.extend(this.geometrySymbol, {
                bounds,
                extData : {
                    lng : e.lnglat.lng,
                    lat : e.lnglat.lat,
                },
                bubble : true
            })
            let overlay = this.addOverlay({
                type : 'Rectangle',
                coordinate : [e.lnglat.lng, e.lnglat.lat,e.lnglat.lng, e.lnglat.lat],
                settings
            })
            drawStart(overlay)
        }
        rectangleMouseMoveHandler(drawing, e){
            if(this.mouseEventStopAction()) return 
            this.mouseMoveTipHandler(e)
            let rectangles = this.overlayGroup.getOverlays()
            if(rectangles && rectangles[rectangles.length - 1] && !this.getMapDragStatus()){
                let rectangle = rectangles[rectangles.length - 1]
                let bounds = rectangle.getBounds()
                let origin = rectangle.getExtData()
                bounds = new AMap.Bounds(new AMap.LngLat(origin.lng, origin.lat), new AMap.LngLat(e.lnglat.R, e.lnglat.Q))
                rectangle.setBounds(bounds)
                drawing(rectangle)
            }
        }
        rectangleMouseUpHandler(drawEnd, e){
            if(this.mouseEventStopAction()) return 
            if(e.originEvent.button != 0) return
            this.relaseMapDrag()
            let overlays = this.overlayGroup.getOverlays()
            let overlay = overlays[overlays.length - 1]
            if(this.drawMethod == 'once'){
                if(this.saveOverlayStatus == 'saveNot'){
                    this.overlayGroup.clearOverlays()
                }
                this.cancelDraw()
                this.drawAfterEvent()
            }else if(this.drawMethod == 'repeat') {
                switch(this.saveOverlayStatus){
                    case "saveNot" :
                        this.overlayGroup.clearOverlays()
                        break
                    case "saveOnce" :
                        break
                    case "saveMore" :
                        break
                    default :
                        break
                } 
            }
            drawEnd(overlay)
        }
        rectangleMouseRightClickHandler(rightClick){
            if(this.mouseEventStopAction()) return 
            this.rightClickCommon(rightClick)
        }
        /*****绘制矩形 ********/

        /*****绘制矩多边形 ********/
        polygonMouseClickHandler(drawPoint, drawStart, e){
            if(this.mouseEventStopAction()) return 
            this.commonMouseClickHander(this.repaintDrawpolygon, e)
            let polygons = this.overlayGroup.getOverlays()
            if(this.repaintDrawpolygon){
                this.repaintDrawpolygon = false
                let path = [
                    [e.lnglat.lng, e.lnglat.lat],
                    [e.lnglat.lng, e.lnglat.lat],
                ]
                let settings = _.extend(this.geometrySymbol, {
                    path,
                    extData : {
                        lng : e.lnglat.lng,
                        lat : e.lnglat.lat,
                    },
                    bubble : true
                })
                let polygon = this.addOverlay({
                    coordinate : path,
                    settings
                })
                drawStart(polygon,polygons.length+1)
                drawPoint(polygon)
            }else{
                let polygon = polygons[polygons.length - 1] 
                let path = polygon.getPath()
                path.push(e.lnglat)
                polygon.setPath(path)
                drawPoint(polygon)
            }
        }
        polygonMouseMoveHandler(drawing, e){
            if(this.mouseEventStopAction()) return 
            this.mouseMoveTipHandler(e)
            let polygons = this.overlayGroup.getOverlays()
            if(polygons && polygons[polygons.length - 1] && !this.repaintDrawpolygon){
                let polygon = polygons[polygons.length - 1] 
                let path = polygon.getPath()
                path.pop()
                path.push(e.lnglat)
                polygon.setPath(path)
                drawing(polygon)
            }
        }
        polygonMouseDbClickHandler(drawEnd, e){
            if(this.mouseEventStopAction()) return 
            this.relaseMapDrag()
            let polygons = this.overlayGroup.getOverlays()
            let polygon = polygons[polygons.length - 1]
            this.handleRepeatPath(polygon)
            if(this.drawMethod == 'once'){
                if(this.saveOverlayStatus == 'saveNot'){
                    this.overlayGroup.clearOverlays()
                }
                this.cancelDraw()
                this.drawAfterEvent()
            }else if(this.drawMethod == 'repeat'){
                switch(this.saveOverlayStatus){
                    case "saveNot" :
                        this.overlayGroup.clearOverlays()
                        break
                    case "saveOnce" :
                        break
                    case "saveMore" :
                        break
                    default :
                        break
                }
                this.repaintDrawpolygon = true
            }
            drawEnd(polygon)
        }
        polygonMouseRightClickHandler(rightClick){
            if(this.mouseEventStopAction()) return 
            this.rightClickCommon(rightClick)
        }
        polygonKeyupHandler(e){
            if(this.mouseEventStopAction()) return 
            if(e.key == 'Escape' || e.keyCode == 27){
                let polygons = this.overlayGroup.getOverlays()
                if(polygons.length == 0) return
                this.repaintDrawpolygon = false
                let polygon = polygons[polygons.length - 1] 
                let path = polygon.getPath()
                if(path.length == 0 && polygons.length >= 2) return this.overlayGroup.removeOverlay(polygon)
                if(path.length >= 3){
                    let pathLast = path[path.length - 1]
                    let pathTwo = path[path.length - 2]
                    if(pathLast.lng == pathTwo.lng && pathLast.lat == pathTwo.lat) path.pop()
                }
                path.pop()
                if(path.length == 1 && this.drawMethod == 'repeat'){
                    if(polygons.length > 1) {
                        this.overlayGroup.removeOverlay(polygon)
                        polygon = []
                    }
                    return
                }
                polygon.setPath(path)
            }
        }
        /*****绘制多边形 ********/

        /*****绘制圆 ********/

        /*****绘制圆 ********/

        /*****公共模块 ********/
        mouseEventStopAction(){
            if(!this.getIsDrawing()) return true
            return false
        }
        getIsDrawing(){
            return !!this.isDrawing
        }
        mouseMoveTipHandler(e){
            let x = e.pixel.x + 8
            let y = e.pixel.y - 8
            this.$tipContainer.css({
                left: x + 'px',
                top: y + 'px'
            })
        }
        stopMapDrag() {
            this.map.setStatus({
                dragEnable: false
            })
        }
        relaseMapDrag() {
            this.map.setStatus({
                dragEnable: true
            })
        }
        getMapDragStatus(){
            return this.map.getStatus()['dragEnable']
        }
        addOverlay({type , coordinate, settings}){
            let overlay = AMapTool.getDefaultOverlay({
                type : type || this.type,
                coordinate : coordinate,
                settings : settings
            })['overlay']
            this.overlayGroup.addOverlay(overlay)
            return overlay
        }
        rightClickCommon(rightClick){
            this.drawAfterEvent()
            if(this.rightMenuHandleOverlays == 'clear'){
                this.cancelDraw(true)
            }else {
                this.cancelDraw()
            }
            rightClick()
        }
        stopMapDbClick(){
            this.map.setStatus({
                doubleClickZoom : false
            })
        }
        relaseMapDbClick(){
            this.map.setStatus({
                doubleClickZoom : true
            })
        }
        commonMouseClickHander(repeatDraw, e){
            this.stopMapDrag()
            this.stopMapDbClick()
            this.mouseMoveTipHandler(e)
            if(this.drawMethod == 'repeat') {
                switch(this.saveOverlayStatus){
                    case "saveNot" :
                        break
                    case "saveOnce" :
                        if(repeatDraw){
                            this.overlayGroup.clearOverlays()
                        }
                        break
                    case "saveMore" :
                        break
                    default :
                        break
                } 
            }
        }
        /*****公共模块 ********/
    }

    return AMapDrawTool
});
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值