Как создать легенду для тепловой карты Google?

Я нарисовал тепловую карту, используя Google Maps API v3 с приложением БД на бэкэнде.

Круто, я вижу зеленое.->.желтое.->.красное сияние над моей картой. Выглядит хорошо!

Но как я могу получить значения для этих цветов?

Какова средняя масса светло-зеленого и темно-красного цветов?

Могу ли я реализовать такую ​​«легенду» с помощью goolge API или мне нужно написать какую-то пользовательскую функциональность JS?


person Capacytron    schedule 15.10.2013    source источник


Ответы (1)


На сегодняшний день, похоже, нет официального способа получить легенду тепловой карты через API, что означает, что вы здесь сами по себе. Чтобы построить легенду, вам понадобятся следующие два ингредиента.

  1. Определение цветов градиента тепловой карты
  2. Максимальная плотность — это верхняя граница легенды (нижняя граница всегда равна 0)

Предпосылки

В следующих фрагментах кода предполагается, что ваш HTML содержит контейнеры для легенды и градиента легенды, а также что вы создали действительную карту и тепловую карту.

<div id="map"></div>
<div id="legend">
    <div id="legendGradient"></div>
</div>
<script type="text/javascript">
    function initialize() {
        map = new google.maps.Map(document.getElementById('map'), {
            ...
        });

        heatmap = new google.maps.visualization.HeatmapLayer({
            data: ...
        });

        heatmap.setMap(map);
    }

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

Градиент

Тепловая карта на самом деле содержит свойство gradient, которое, однако, не заполняется для градиента по умолчанию, а содержит только те характеристики градиента, которые вы вручную присвоили тепловой карте. Следовательно, чтобы получить точные характеристики градиента, вам нужно будет определить цвета самостоятельно. После этого вы можете просто нарисовать градиент в легенде с помощью CSS.

var gradient = [
    'rgba(0, 255, 255, 0)',
    'rgba(0, 255, 255, 1)',
    ...
];

heatmap.set('gradient', gradient);

var gradientCss = '(left';
for (var i = 0; i < gradient.length; ++i) {
    gradientCss += ', ' + gradient[i];
}
gradientCss += ')';

$('#legendGradient').css('background', '-webkit-linear-gradient' + gradientCss);
$('#legendGradient').css('background', '-moz-linear-gradient' + gradientCss);
$('#legendGradient').css('background', '-o-linear-gradient' + gradientCss);
$('#legendGradient').css('background', 'linear-gradient' + gradientCss);

Максимальная плотность

Максимальная плотность официально недоступна через API. Однако логика подсказывает нам, что значение должно храниться где-то в объекте. Проведя небольшое исследование с помощью консоли JavaScript Chrome, я обнаружил значение, хранящееся в heatmap['gm_bindings_']['data'][158]['kd']['D']. Однако это значение будет установлено только после визуализации карты. Таким образом, вам нужно обернуть доступ к полю в обработчик событий tilesloaded.

Как только вы добились максимальной плотности, можно легко сгенерировать деления и метки для легенды. Следующий фрагмент кода создает галочки и метки под градиентом легенды, высота которого предполагается равной 15px.

google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
    var maxIntensity = heatmap['gm_bindings_']['data'][158]['kd']['D'];
    var legendWidth = $('#legendGradient').outerWidth();

    for (var i = 0; i <= maxIntensity; ++i) {
        var offset = i * legendWidth / maxIntensity;
        if (i > 0 && i < maxIntensity) {
            offset -= 0.5;
        } else if (i == maxIntensity) {
            offset -= 1;
        }

        $('#legend').append($('<div>').css({
            'position': 'absolute',
            'left': offset + 'px',
            'top': '15px',
            'width': '1px',
            'height': '3px',
            'background': 'black'
        }));
        $('#legend').append($('<div>').css({
            'position': 'absolute',
            'left': (offset - 5) + 'px',
            'top': '18px',
            'width': '10px',
            'text-align': 'center'
        }).html(i));
    }
});

Подведение итогов

Рабочий пример приведенного выше кода можно найти на JSFiddle.

введите здесь описание изображения

Обратите внимание, что способ определения максимальной плотности совершенно неофициальный и недокументированный. Это может не работать в будущих версиях API и даже в текущей версии может работать не во всех случаях.

person hennes    schedule 29.08.2014
comment
Строка с надписью var maxIntensity = heatmap['gm_bindings_']['data'][158]['kd']['D']; — измените ее на var getMax = heatmap['gm_bindings_']['data']; if(typeof getMax !== 'undefined'){ for(var p in getMax){ maxIntensity = getMax[p].md.j; break; } }, что сделает ее совместимой для разных выборок данных. - person James Cordeiro; 07.08.2015
comment
Такие ответы заставляют меня желать, чтобы у стопки были «ответы с золотой звездой» - person Roger; 22.12.2016
comment
Где я могу найти массив цветов градиента по умолчанию (желтый, зеленый, красный)? - person Ankur Akvaliya; 28.09.2017
comment
@hennes Эй, просто быстрая проверка с вами, легенда от jsfiddle не показывает масштаб. Есть идеи? - person BlackMamba; 16.12.2017
comment
@hyperfkcb Извините, у меня нет быстрого решения этой проблемы. Ответ выше основан на недокументированных внутренних структурах данных. Вроде формат изменился. Глядя на ошибку JS, похоже, что определение максимальной интенсивности - это то, что ее ломает. - person hennes; 02.01.2018
comment
@AnkurAkvaliya Вот градиент по умолчанию: gis.stackexchange.com/a/257242 - person ErJab; 08.01.2018
comment
Это фантастическая работа, и я +1. Ужасно, что тот, кто запрограммировал этот код для тепловых карт Google, не учел всех интересных способов его использования. - person ; 08.01.2018
comment
@hennes Я удалил плитки в соответствии с требованиями клиента. Так чтоtileloaded не будет работать для меня. Есть ли какое-либо другое событие, на котором я могу разместить ваш код? Также числа (0,1,2,3) под легендой не отображают вашу скрипку. - person Ankur Akvaliya; 08.01.2018
comment
Привет, у меня такая же проблема, число под легендой (legendLabels) не отображается. Я использую предложение @JamesCordeiro и получаю эту ошибку: «TypeError: getMax[p].md is undefined». Есть идеи? Спасибо. - person Andermutu; 20.08.2019