How to set dynamic pixel offsets for infoboxes?

六月ゝ 毕业季﹏ 提交于 2019-12-25 06:59:33

问题


I have a map with multiple markers of basically 2 types. One is a larger, wide marker, and the other is a lot smaller, square marker. Both types need to have an infobox that appears when clicked. Due to the different shapes and sizes of the markers, I'd very much like the infobox windows to be anchored at different positions based on which marker is being clicked. Of course I found the pixelOffset property for the infobox options, but I seem unable to set this dynamically based on the marker my loop is passing over. Basically I loop over an array of markerdata, build the marker (via the 'new google.maps.marker()' thing), then proceed to add an event listener for clicks on the marker which calls the function to open an infobox.

So my question is, after looking at the below code, how can I set the pixelOffset of the infobox dynamically?
What I've tried below clearly doesn't do the trick! The alert I dumped in there does actually show the correct settings when I load the page!

<script type="text/javascript">
var LocationData = [
    [29.966270,-95.682491, "bhi", "Company Houston", "", "", "", "", "", "", "1"],
    [34.936190, -88.655899, "motors", "ConocoPhilips", "testfield #1", "rig #1", "HT102313MTR", "Eagle Ford", "v", "m", "0"],
    [32.133333, -102.3167, "type1", "Halliburton", "Test Field #2", "H&P #48", "HT070313RSS", "Bakken", "h", "m", "1"],
    [47.4667, -100.9333, "type2", "BP", "Test Field #3", "Ensco #318", "CC111512GWD", "Marcellus", "s", "", "2"],
    [41.5700, -117.7839, "type3", "Drake Directional", "Test Field #4", "H&P #143", "PE010214MWD", "Utica", "j", "f", "3"],
    [40.4667, -76.9333, "type4", "Shell", "testfield #5", "Ensco #23", "HT121213GYRO", "Barnett", "h", "m", "4"],

];

jQuery(document).ready(function(){
    initMap();  
});

var side_bar_html = '';
var gmarkers = [];
var htmls = [];

var myLatLong = new google.maps.LatLng(29.966270, -95.682491);
var mapOptions = {
    panControl: true,
    zoomControl: true,
    scaleControl: true
};

boxText = document.createElement("div");

function iconSizeFunction(usedIcon) {
    switch(usedIcon)
    {
    case 'bhi':
        var iconSizew_or = '68';
        var iconSizeh_or = '72';
        var iconSizew = '34';
        var iconSizeh = '36';
        var iconOriginw = '17';
        var iconOriginh = '28';
        var infoboxOffsetw = '200';
        var infoboxOffseth = '10';
        return [iconSizew_or, iconSizeh_or, iconSizew, iconSizeh, iconOriginw, iconOriginh, infoboxOffsetw, infoboxOffseth];
        break;
    default:
        var iconSizew_or = '264';
        var iconSizeh_or = '70';
        var iconSizew = '132';
        var iconSizeh = '35';
        var iconOriginw = '17';
        var iconOriginh = '-5';
        var infoboxOffsetw = '150';
        var infoboxOffseth = '200';
        return [iconSizew_or, iconSizeh_or, iconSizew, iconSizeh, iconOriginw, iconOriginh, infoboxOffsetw, infoboxOffseth];
        break;
    }
}

function initMap()
{
    var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
    var bounds = new google.maps.LatLngBounds();
    var infowindow = new google.maps.InfoWindow();
    var iconUsed;

    for (var i in LocationData)
    {
        var p = LocationData[i];
        var latlng = new google.maps.LatLng(p[0], p[1]);
        var iconUsed = p[2];
        var iconSizes = iconSizeFunction(p[2]);
        var infoBoxPosition = new google.maps.Size(iconSizes[6], iconSizes[7]);

        var jobStatus = p[10];

        switch(jobStatus)
        {
        case '0':
            jobStatus = 'off';
            break;
        case '1':
            jobStatus = 'on';
            break;
        case '2':
            jobStatus = 'up';
            break;
        case '3':
            jobStatus = 'unknown';
            break;
        case '4':
            jobStatus = 'new';
            break;
        }

        bounds.extend(latlng);

        var marker = new google.maps.Marker({
            position: latlng,
            map: map,
            icon: {
                url: '/images/mapicons/' + iconUsed + '_' + jobStatus + '.png',
                size: new google.maps.Size(iconSizes[0], iconSizes[1]),
                origin: new google.maps.Point(0,0),
                anchor: new google.maps.Point(iconSizes[4], iconSizes[5]),
                scaledSize: new google.maps.Size(iconSizes[2], iconSizes[3])
            },
            shape: {
                coord: [0, 0, iconSizes[2], iconSizes[3]],
                type: 'rect'
            },
            optimized: false,
            animation: google.maps.Animation.DROP,
            content: '<div class="boxOptionsHeader"><h2>' + p[3] + '</h2></div><div class="boxOptionsExtra">' + p[4] + '<br /><a href="http://maps.apple.com/maps?saddr=Current+Location&daddr=' + p[0] + ',' + p[1] + '">Directions to here</a></div>'
        });

        var i = gmarkers.length;
        gmarkers.push(marker);
        markerLength = gmarkers.length-1;
        side_bar_html += '- <a href="javascript:sidebarclick(' + markerLength + ')">' + p[3] + '<\/a><br \/>';


        alert(infoBoxPosition);
        var boxOptions = {
            content: boxText,
            disableAutoPan: false,
            alignBottom: true,
            maxWidth: 0,
            pixelOffset: infoBoxPosition,
            zIndex: null,
            boxStyle: {
                width: "240px"
            },
            closeBoxMargin: "0px 0px 0px -40px",
            closeBoxURL: "/images/mapicons/close_info.png",
            infoBoxClearance: new google.maps.Size(1, 1),
            visible: true,
            pane: "floatPane",
            enableEventPropagation: false,
            boxClass: 'boxOptions'
        };

        //console.log(marker.content);
        var ib = new InfoBox(boxOptions);
        google.maps.event.addListener(marker, 'click', function(e) {
            boxText.innerHTML = this.content;
            ib.open(map, this);
        });

        google.maps.event.addListener(map, 'click', function() {
            ib.close();
        });

        function setZoomWhenMarkerClicked() {
            var currentZoom = map.getZoom();
            if (currentZoom < 7) {
                map.setZoom(7);
            }
            return false;
        }
    }

    document.getElementById("side_bar").innerHTML = side_bar_html;
    map.fitBounds(bounds);
}

function sidebarclick(i) {
  google.maps.event.trigger(gmarkers[i], "click");
}

</script>

And here's the CSS for the box.

html { height: 100% }
body { height: 100%; margin: 0; padding: 0; background-color: #FFF; }
#map-canvas { height: 100%;}

.infobox-wrapper {
    display:none;
}

.boxOptions {
    position: relative;
    border: 2px solid #E1002B;
    margin-top: 0px;
    background: #FAFAFA;
    color:#5B6770;
    font-family:Arial, Helvetica, sans-serif;
    font-size: 14px;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 2px;
    text-shadow:0 -1px #FFF;
    z-index: 20;
}

.boxOptionsHeader {
    margin-top: -10px;
    padding: 0 1em;
}

.boxOptionsExtra {
    margin-top: -12px;
    padding: .5em 1em;
}

.boxOptions:after, .boxOptions:before {
    top: 100%;
    left: 15px;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
}

.boxOptions:after {
    border-color: rgba(136, 183, 213, 0);
    border-top-color: #FAFAFA;
    border-width: 8px;
    margin-left: -8px;
}

.boxOptions:before {
    border-color: rgba(194, 225, 245, 0);
    border-top-color: #E1002B;
    border-width: 11px;
    margin-left: -11px;
}

回答1:


The creation of the infoboxes inside the loop is redundant, all the markers will use the same infobox(the last one that will be created. Note that you overwrite the ib-variable on each iteration). Create a single InfoBox-instance outside of the loop with default-options.

How to apply the dynamic pixelOffset:

Store it as a property of the markers, e.g.:

ibOffset :new google.maps.Size(iconSizes[6], iconSizes[7])

in the click-listener set the pixelOffset-option of ib:

ib.setOptions({'pixelOffset':this.ibOffset}); 

But the most important thing:

google.maps.Size() expects the arguments to be of type Number, but you provide Strings.

Remove the quotes around the values of infoboxOffsetw and infoboxOffseth



来源:https://stackoverflow.com/questions/21262380/how-to-set-dynamic-pixel-offsets-for-infoboxes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!