Как залить цвет кластера цветами внутренних маркеров? - PullRequest
1 голос
/ 07 мая 2020

На настраиваемой карте листовок я пытаюсь создать функцию для заливки цвета фона значка кластера из цвета маркеров, которые находятся внутри кластера. Например, если в кластере есть 7 зеленых маркеров и 2 красных маркера, заполните кластер на 77% зеленым, а еще - красным.

Я использую markerCluster плагин и замечательный плагин маркеров вместе.

На данный момент вот что у меня есть:

var clusters = L.markerClusterGroup({
  spiderfyOnMaxZoom: false,
  showCoverageOnHover: false,
  zoomToBoundsOnClick: true,
  iconCreateFunction: function (cluster) {
    var markers = cluster.getAllChildMarkers();
    console.log(markers);
    markers.forEach(function (m) {
      var color = m.defaultOptions.icon.options.markerColor;
      console.log(color);
    });
    var html =
      '<span class="circle circle-' + markers[0].feature.properties["Examen"] +
      '">' + markers.length + "</span>";
    return L.divIcon({ html: html, className: "marker-cluster", iconSize: L.point(32, 32) });
  },
});

Я вижу, что могу получить количество маркеров внутри каждого кластера и соответствующий цвет , что-то вроде этого. enter image description here

Итак, мой вопрос: как я могу oop через «цвет» получить процентное содержание каждого цвета внутри кластера?

Моя цель - использовать этот процент для заливки цвета фона кластера ... чтобы получить что-то вроде этого?

enter image description here

Я видел много примеров об этом, например, здесь здесь здесь здесь и здесь но мне интересно, не могу ли я иметь что-то подобное без тонны сложного кода, как в этих примерах?

EDIT:

Хорошо, благодаря любезной помощи @IvanSanchez, я воспроизвел предоставленный код в свой проект, и он работает ! Мне пришлось немного изменить его, чтобы он заработал, и я попытался использовать icon-gradient и linear gradient .

Ниже представлена ​​моя последняя функция culsterGroup, и я показываю полный пример двух версий здесь (iconi c css) и здесь (linear-gradient ). Извините, я не могу опубликовать его здесь, так как код слишком длинный для этого редактора :)

После внедрения я внес некоторые изменения. - Поскольку я получал только первую букву моих цветов, css не работал. Поэтому я написал:

stops.push(color + ' ' + startPercent + '%');
stops.push(color + ' ' + endPercent + '%');

вместо

 stops.push(color[i] + ' ' + startPercent + '%');
 stops.push(color[i] + ' ' + endPercent + '%');
  • Мне также пришлось изменить свой диапазон в переменной 'html' с помощью div, как маркер-кластер css применяется к div по умолчанию.

    var кластеры = L.markerClusterGroup ({spiderfyOnMaxZoom: false, showCoverageOnHover: false, zoomToBoundsOnClick: true,

        iconCreateFunction: function (cluster) {
            var markers = cluster.getAllChildMarkers();
            var childCount = cluster.getChildCount();
            console.log(markers);
            var stops = [];
    
            for (let i=0, l=markers.length; i<l; i++) {
                var color = markers[i].defaultOptions.icon.options.markerColor;         
                let startPercent = 100 * (i/l);
                let endPercent = 100 * (i+1)/l;
                stops.push(color + ' ' + startPercent + '%');
                stops.push(color + ' ' + endPercent + '%');     
            }
            var html = '<div class="circleMarker" style="background: linear-gradient(to right,' + stops.join(',') + '" >' + markers.length + "</div>";
            return L.divIcon({ html: html, className: "marker-cluster", iconSize: L.point(40, 40) });
    
          },
    });
    
  • Кроме того, некоторые смеси цветов больше не работают с этой техникой: если мы посмотрим на цветовую палитру плагина awesomeMarker, некоторые цвета не имеют эквивалента в css, например 'lightRed' или 'dardkRed' . Итак, чтобы соответствовать цвету, который я использую в своем проекте, я изменил цвета градиента, чтобы цвета кластеров идеально подходили к цветам моих маркеров.

  • И поскольку icon-gradient не поддерживается firefox и IE, я добавил условие для отображения кластера icon-gradient для chrome и стандартного linear-gradient для firefox и IE.

Вот последний фрагмент кода:

     var clusters = L.markerClusterGroup({
        spiderfyOnMaxZoom: false,
        showCoverageOnHover: false,
        zoomToBoundsOnClick: true,

        iconCreateFunction: function (cluster) {
            var markers = cluster.getAllChildMarkers();
            var childCount = cluster.getChildCount();
            console.log(markers);
            var stops = [];
            for (let i=0, l=markers.length; i<l; i++) {
            var color= markers[i].defaultOptions.icon.options.markerColor;  
            if (color==="red"){ 
            color="#D13D29";
            }else if( color === "orange"){
            color="#F69730";
            }else if(color === "green"){
            color="#6FAC25";
            }else if(color === "cadetblue"){
            color="#406473";
            }else if(color ==="darkred"){
            color="#A03336 ";
            }else if(color === "beige"){
            color="#FFC78C";
            }else if(color === "darkgreen"){
            color="#708023";
            }else if(color === "lightgreen"){
            color="#B8F471";
            }else if(color === "blue"){
            color="#37A7D9 ";
            }else if(color === "darkblue"){
            color="#0065A0";
            }else if(color === "lightblue"){
            color="#88DAFF";
            }else if(color === "purple"){
            color="#CD50B5";
            }else if(color === "darkpurple"){
            color="#593869";
            }else if(color === "pink"){
            color="#FF90E8";
            }else if(color === "gray"){
            color="#575757";
            }else if(color === "lightgray"){
            color="#A3A3A3";
            }
                let startPercent = 100 * (i/l);
                let endPercent = 100 * (i+1)/l;
                stops.push(color + ' ' + startPercent + '%');
                stops.push(color + ' ' + endPercent + '%');     
            }
            if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1  || navigator.userAgent.indexOf("MSIE") != -1 || !!document.documentMode == true ){
                var html = '<div class="circleMarker" style="background: linear-gradient(to right, ' + stops.join(',') + '" >' + markers.length + "</div>";
                return L.divIcon({ html: html, className: "marker-cluster", iconSize: L.point(40, 40) });
            }else{
                var html = '<div class="circleMarker" style="background: conic-gradient(' + stops.join(',') + '" >' + markers.length + "</div>";
                return L.divIcon({ html: html, className: "marker-cluster", iconSize: L.point(40, 40) });

            }
          },
    });

Окончательно после теста Кроме того, линейный градиент не работает в браузере Ie. Итак, я закончил с этим условием

var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
        if(isChrome){
        var html = '<div class="circleMarker" style="background: conic-gradient(' + stops.join(',') + '" >' + markers.length + '</div>';
            return L.divIcon({ html: html, className: "marker-cluster", iconSize: L.point(40, 40) });
        }

        else if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1  ){
            var html = '<div class="circleMarker" style="background: linear-gradient(to right, ' + stops.join(',') + '" >' + markers.length + '</div>';
            return L.divIcon({ html: html, className: "marker-cluster", iconSize: L.point(40, 40) });
        }else {
             var html = '<div class="markerCluster"><span>' + markers.length + '</span></div>';
            return L.divIcon({ html: html, className: "marker-cluster" });
            }
      },

Теперь, если это chrome, я использую icon-gradient, если это Firefox, linear-gradient, и если это IE, я рисую круги как оригинальный значок кластера.

Я не нашел способ восстановить нормальный значок кластера только для IE браузера ..

1 Ответ

2 голосов
/ 07 мая 2020

Поскольку вы явно упоминаете цвет фона маркера кластера, я бы предложил использовать conic-gradient CSS функцию , которая является специфическим типом c CSS градиента. Как объясняется в статье MDN об использовании CSS градиентов , использование градиентов с дублированными стопами позволяет создавать острые края в таком градиенте.

например, что-то вроде ...

<div style='width:50px; height:50px;
  background:  linear-gradient(to right, 
    lime 0%, lime 25%, 
    red 25%, red 50%,
    cyan 50%, cyan 75%, 
    yellow 75%, yellow 100% ); 
'></div>

... будет выглядеть так:

enter image description here

И что-то вроде ...

<div style='width:50px; height:50px;
  border-radius:25px;
  background:  conic-gradient(
    lime 0%, lime 40%, 
    red 40%, red 60%,
    cyan 60%, cyan 88%, 
    yellow 88%, yellow 100% ); 
'></div>

.. . будет выглядеть как ...

sample conic gradient

Итак, если у вас есть массив строк, представляющих CSS цветов, вы можете сделать немного строковых манипуляций, чтобы превратить это в строку, представляющую функцию CSS для градиента, например:

let colours = ['red','red','red','purple','green','green'];

let stops = [];

for (let i=0, l=colours.length; i<l; i++) {
  let startPercent = 100 * (i/l);
  let endPercent = 100 * (i+1)/l;
  stops.push(colours[i] + ' ' + startPercent + '%');
  stops.push(colours[i] + ' ' + endPercent + '%');
}

let gradient = "conic-gradient(" + stops.join(',') + ")";

..., которая создаст переменную gradient, содержащую строку вроде ...

conic-gradient(red 0%,red 16.666666666666668%,red 16.666666666666664%,red 33.333333333333336%,red 33.33333333333333%,red 50%,purple 50%,purple 66.66666666666667%,green 66.66666666666666%,green 83.33333333333333%,green 83.33333333333334%,green 100%)

... и при применении к элементу на веб-странице это будет выглядеть так:

dynamic conic gradient

См. рабочая демонстрация здесь .


Возможно, вам придется немного подправить вещи, чтобы адаптировать эту технику к вашему коду, но я бы предложил что-то вроде:

var stops = [];

for (let i=0, l=markers.length; i<l; i++) {
    var color = m.defaultOptions.icon.options.markerColor;
    let startPercent = 100 * (i/l);
    let endPercent = 100 * (i+1)/l;
    stops.push(colours[i] + ' ' + startPercent + '%');
    stops.push(colours[i] + ' ' + endPercent + '%');    
});
var html = '<span ' +
    'class="circle circle-' + markers[0].feature.properties["Examen"] + '" ' +
    'style="background: conic-gradient(' + stops.join(',') + '" ' +
>' + markers.length + "</span>";

Обратите внимание, что на th На момент написания этой статьи поддержка браузером conic-gradient CSS функции несовместима. Следовательно, этот метод не следует использовать, если вы хотите, чтобы все работало с людьми, использующими Firefox, по крайней мере, на данный момент.

...