【问题标题】:Select marker located below a rectangle selection drawn by user over google maps选择位于用户在谷歌地图上绘制的矩形选择下方的标记
【发布时间】:2016-09-13 08:47:17
【问题描述】:

下面的代码包含适当的 cmets 以便正确理解。如果问题不清楚,请告诉我

我的要求是获取用户在地图上所做的矩形选择下的所有标记的信息。 (使用控制键+鼠标按下+鼠标移动事件)

我有一个要在谷歌地图中绘制的标记列表。为了稍后对其进行操作,我使用了 API 提供的自定义叠加层。它工作正常。

现在我需要允许用户通过按下 Control 键 + 鼠标来绘制一个矩形选择。当鼠标移动时,会在地图上绘制一个矩形,并检查是否有任何标记位于绘制的矩形下方。这也很好用。

但是,如果我使用鼠标滚动地图,则会错误地计算值并且没有得到结果。即矩形没有正确绘制。

我的分析是鼠标移动事件的PageX和PageY的使用有问题。最初我使用了 clientX 和 clientY,但为了帐户滚动,我使用了 PageX 和 PageY。

这里可能有什么问题?请告诉我。

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Proto 1 displaying a list of cameras with custom markers.</title>
    <style>
        html,
        body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
        #map {
            height: 100%;
        }
        #rectangle {
            position: absolute;
            border: 1px solid #c1e0ff;
            z-index: 100000;
            visibility: hidden;
            background-color: #c1e0ff;
            opacity: 0.5
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBY_Jb6UGbhR1g9cM3uPGStdevUputZh5s"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script>
        var map;
        /* Need to listen for control key + mouse down + mouse move to draw a rectangle over google map and check for markers below the selection*/
        document.addEventListener('keydown', multipleCameraSelection);

        function multipleCameraSelection(e) {
            if (e.ctrlKey) {
                map.setOptions({
                    draggable: false
                });

                document.onmousedown = function(event) {

                    /*get div having ID of rectangle.This is created and added to the overlay image pane of map in the draw() function*/
                    var rectangleDiv = document.getElementById('rectangle');

                    /*get the co ordinates where mouse is clicked*/
                    var initialX = event.pageX;
                    var initialY = event.pageY;

                    rectangleDiv.style.left = initialX + 'px';
                    rectangleDiv.style.top = initialY + 'px';

                    document.onmousemove = function(event) {

                        /*on mouse move width and height of rectangle is calculated and set*/
                        var wid = Math.abs(event.pageX - initialX);
                        var hei = Math.abs(event.pageY - initialY);

                        rectangleDiv.style.width = wid + 'px';
                        rectangleDiv.style.height = hei + 'px';

                        rectangleDiv.style.visibility = 'visible';

                        if (event.pageX < initialX && event.pageY >= initialY) {
                            rectangleDiv.style.left = event.pageX + 'px';
                        } else if (event.pageY <= initialY && event.pageX >= initialX) {

                            rectangleDiv.style.top = event.pageY + 'px';
                        } else if (event.pageY < initialY && event.pageX < initialX) {

                            rectangleDiv.style.left = event.pageX + 'px';
                            rectangleDiv.style.top = event.pageY + 'px';
                        }

                    }

                    document.onmouseup = function(event) {
                        document.onmousedown = null;
                        document.onmousemove = null;
                        document.onmouseup = null;
                        rectangleDiv.style.visibility = 'hidden';

                        /*get the current left , top value of element*/
                        var rectPos = getOffsetValues(rectangleDiv);


                        /*all markers have a name starting with cameraDiv. checking whether they lies between the rectangle drawn*/
                        $("div[id^='cameraDiv']").each(function(index, value) {

                            var elemToFind = value;

                            var elemToFindpos = getOffsetValues(elemToFind);

                            if ((((rectPos.topValue + rectangleDiv.offsetHeight) > elemToFindpos.topValue) && (rectPos.topValue < elemToFindpos.topValue || rectPos.topValue <= (elemToFindpos.topValue + elemToFind.offsetHeight))) &&
                                (((rectPos.leftValue + rectangleDiv.offsetWidth) > elemToFindpos.leftValue) && (rectPos.leftValue < elemToFindpos.leftValue || rectPos.leftValue <= (elemToFindpos.leftValue + elemToFind.offsetWidth)))) {

                                console.log(value);
                            }

                        })

                        map.setOptions({
                            draggable: true
                        });
                    }
                }
            }
        }

        function getOffsetValues(elem) {
            var left = 0,
                top = 0;

            while (elem) {
                left += elem.offsetLeft;
                top += elem.offsetTop;
                elem = elem.offsetParent;
            }
            return {
                leftValue: left,
                topValue: top
            };

        }

        function initMap() {
            map = new google.maps.Map(document.getElementById('map'), {
                zoom: 12,
                center: {
                    lat: 8.5241,
                    lng: 76.9366
                }
            });

            overlay = new CameraLayer(map);
            //setMarkers(map);
        }

        var overlay;
        CameraLayer.prototype = new google.maps.OverlayView();

        function CameraLayer(map) {
            this.map_ = map;
            this.div_ = null;
            this.setMap(map);
            //window.alert('constructor called');
        }

        CameraLayer.prototype.onAdd = function() {
            var panes = this.getPanes();
            var div = document.createElement('div');
            div.style.position = 'absolute';
            div.id = 'myCustomdiv';
            this.div_ = div;

            panes.overlayImage.appendChild(this.div_);

        }

        CameraLayer.prototype.draw = function() {

            /*when a scroll happens replot the markers in correct pixel coordinates using methods exposed by map api*/
            while (this.div_.firstChild)
                this.div_.removeChild(this.div_.firstChild);

            var msgContainer = document.createDocumentFragment();

            for (i = 0; i < camerasToPlace.length; i++) {

                var lat = camerasToPlace[i];
                var lat1 = lat[1];
                var lng1 = lat[2];

                var latLng = new google.maps.LatLng({
                    lat: lat1,
                    lng: lng1
                });

                var pixelPosition = this.getProjection().fromLatLngToDivPixel(latLng);

                //msgContainer.appendChild()

                var div1 = document.createElement('div');
                div1.id = 'cameraDiv' + i;
                div1.style.position = 'absolute';

                var img = document.createElement('img');
                img.src = 'camera.png';
                img.style.position = 'absolute';
                //img.style.width = '100%';
                //img.style.height = '100%';



                div1.style.left = pixelPosition.x + 'px';
                div1.style.top = pixelPosition.y + 'px';
                //
                div1.style.width = '32px';
                div1.style.height = '32px';

                div1.appendChild(img);

                msgContainer.appendChild(div1)


            }

            /*creating and appending a div to the overlay image , width and height calculated when the mouse move event happens , style applied above*/
            var rectDiv = document.createElement('div');
            rectDiv.id = 'rectangle';
            rectDiv.style.position = 'absolute';
            this.div_.appendChild(rectDiv);

            /*container holding marker data to plot in map with left and top values*/
            this.div_.appendChild(msgContainer);

        }


        /* a list holding the latitude and longitude values to be used in draw function to plot in map*/
        var camerasToPlace = [
            ['Camera1 located at TVM', 8.545394, 76.883503],
            ['Camera2 located at TVM', 8.7379, 76.7163],
            ['Camera3 located at TVM', 8.8932, 76.6141],
            ['Camera4 located at TVM', 8.7707, 76.8836],
            ['Camera5 located at TVM', 8.936906, 76.871831],
            ['Camera6 located at TVM', 8.485295, 76.916806]
        ];

        google.maps.event.addDomListener(window, 'load', initMap);
    </script>
</body>

</html>

【问题讨论】:

  • 看起来您正在使用网页选择;为了实现您的目标,我会在地图内使用点击事件。那你就不用担心pageX,pageY(这可能会很棘手)
  • @EmmanuelDelay 你的建议奏效了。谢谢

标签: javascript google-maps google-maps-api-3


【解决方案1】:

根据 Emmanuel Delay 的建议,使用地图事件及其工作方式对此进行了重新设计 如果对任何人有帮助,这是代码。请注意,我们必须通过控制 + 鼠标按下 + 鼠标移动来绘制选择。持有标记的 div 元素还附加了一个预定义的名称,以便以后识别它

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Proto 1 displaying a list of cameras with custom markers.</title>
    <style>
        html,
        body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
        #map {
            height: 100%;
        }
        #rectangle {
            position: absolute;
            border: 1px solid #c1e0ff;
            z-index: 100000;
            visibility: hidden;
            background-color: #c1e0ff;
            opacity: 0.5
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBY_Jb6UGbhR1g9cM3uPGStdevUputZh5s"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script>
        var map;
        var mapMouseMoveHandler;
        var mapMouseDownHandler;
        var mapMouseUpHandler;

        document.addEventListener('keydown', controlKeyDown);
        document.addEventListener('keyup', controlKeyUp);

        function controlKeyDown(e) {

            if (e.ctrlKey) {
                mapMouseDownHandler = google.maps.event.addListener(map, 'mousedown', cameraSelectionOnMouseDown);
            }
        }


        function controlKeyUp(e) {
            if (e.key == 'Control') {
                google.maps.event.removeListener(mapMouseDownHandler);
            }
        }

        function getElementOffsetValues(elem) {
            var left = 0,
                top = 0;

            while (elem) {
                left += elem.offsetLeft;
                top += elem.offsetTop;
                elem = elem.offsetParent;
            }
            return {
                leftValue: left,
                topValue: top
            };

        }

        function initMap() {
            map = new google.maps.Map(document.getElementById('map'), {
                zoom: 12,
                center: {
                    lat: 8.5241,
                    lng: 76.9366
                }
            });

            overlay = new CameraLayer(map);
            //setMarkers(map);
        }

        function cameraSelectionOnMouseDown(e) {

            map.setOptions({
                draggable: false
            });

            var rectangleDiv = document.getElementById('rectangle');
            var pixelPosition = overlay.getProjection().fromLatLngToDivPixel(e.latLng);
            var initialX = pixelPosition.x;
            var initialY = pixelPosition.y;

            rectangleDiv.style.left = initialX + 'px';
            rectangleDiv.style.top = initialY + 'px';

            mapMouseMoveHandler = google.maps.event.addListener(map, 'mousemove', function(e) {

                var newXY = overlay.getProjection().fromLatLngToDivPixel(e.latLng);
                var wid = Math.abs(newXY.x - initialX);
                var hei = Math.abs(newXY.y - initialY);

                rectangleDiv.style.width = wid + 'px';
                rectangleDiv.style.height = hei + 'px';
                rectangleDiv.style.visibility = 'visible';

                if (newXY.x < initialX && newXY.y >= initialY) {
                    rectangleDiv.style.left = newXY.x + 'px';
                } else if (newXY.y <= initialY && newXY.x >= initialX) {

                    rectangleDiv.style.top = newXY.y + 'px';
                } else if (newXY.y < initialY && newXY.x < initialX) {

                    rectangleDiv.style.left = newXY.x + 'px';
                    rectangleDiv.style.top = newXY.y + 'px';
                }
            })

            mapMouseUpHandler = google.maps.event.addListener(map, 'mouseup', function(e) {

                google.maps.event.removeListener(mapMouseMoveHandler);
                google.maps.event.removeListener(mapMouseUpHandler);

                var rectPosition = getElementOffsetValues(rectangleDiv);

                $("div[id^='cameraDiv']").each(function(index, value) {

                    var elemToFind = value;

                    var elemToFindposition = getElementOffsetValues(elemToFind);

                    if ((((rectPosition.topValue + rectangleDiv.offsetHeight) > elemToFindposition.topValue) && (rectPosition.topValue < elemToFindposition.topValue || rectPosition.topValue <= (elemToFindposition.topValue + elemToFind.offsetHeight))) &&
                        (((rectPosition.leftValue + rectangleDiv.offsetWidth) > elemToFindposition.leftValue) && (rectPosition.leftValue < elemToFindposition.leftValue || rectPosition.leftValue <= (elemToFindposition.leftValue + elemToFind.offsetWidth)))) {

                        console.log(value);
                    }

                })

                rectangleDiv.style.visibility = 'hidden';
                map.setOptions({
                    draggable: true
                });
            });

        }

        var overlay;
        CameraLayer.prototype = new google.maps.OverlayView();

        function CameraLayer(map) {
            this.map_ = map;
            this.div_ = null;
            this.setMap(map);
        }

        CameraLayer.prototype.onAdd = function() {
            var panes = this.getPanes();
            var div = document.createElement('div');
            div.style.position = 'absolute';
            div.id = 'myCustomdiv';
            this.div_ = div;

            panes.overlayImage.appendChild(this.div_);

        }

        CameraLayer.prototype.draw = function() {

            while (this.div_.firstChild)
                this.div_.removeChild(this.div_.firstChild);

            var msgContainer = document.createDocumentFragment();

            for (i = 0; i < camerasToPlace.length; i++) {

                var lat = camerasToPlace[i];
                var lat1 = lat[1];
                var lng1 = lat[2];

                var latLng = new google.maps.LatLng({
                    lat: lat1,
                    lng: lng1
                });

                var pixelPosition = this.getProjection().fromLatLngToDivPixel(latLng);


                var div1 = document.createElement('div');
                div1.id = 'cameraDiv' + i;
                div1.style.position = 'absolute';

                var img = document.createElement('img');
                img.src = 'camera.png';
                img.style.position = 'absolute';
                //img.style.width = '100%';
                //img.style.height = '100%';



                div1.style.left = pixelPosition.x + 'px';
                div1.style.top = pixelPosition.y + 'px';
                //
                div1.style.width = '32px';
                div1.style.height = '32px';

                div1.appendChild(img);

                msgContainer.appendChild(div1)


            }

            var rectDiv = document.createElement('div');
            rectDiv.id = 'rectangle';
            rectDiv.style.position = 'absolute';
            this.div_.appendChild(rectDiv);

            this.div_.appendChild(msgContainer);

        }

        var camerasToPlace = [
            ['Camera1 located at TVM', 8.545394, 76.883503],
            ['Camera2 located at TVM', 8.7379, 76.7163],
            ['Camera3 located at TVM', 8.8932, 76.6141],
            ['Camera4 located at TVM', 8.7707, 76.8836],
            ['Camera5 located at TVM', 8.936906, 76.871831],
            ['Camera6 located at TVM', 8.485295, 76.916806]
        ];

        google.maps.event.addDomListener(window, 'load', initMap);
    </script>
</body>

</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 2018-04-16
    • 2023-03-23
    相关资源
    最近更新 更多