AMCharts Maps v4 - есть ли способ использовать более двух цветов в HeatLegend? - PullRequest
0 голосов
/ 20 декабря 2018

Думал, что было бы неплохо иметь возможность установить диапазон цветов для тепловой карты вместо двух (мин и макс).Как то, что мы делаем для списка градиентов.

Что-то вроде ...

function am4themes_myHeatmap(target) {
  if (target instanceof am4core.ColorSet) {
    target.list = [
      am4core.color("#F7E3D4"),
      am4core.color("#FFC480"),
      am4core.color("#DC60BF"),
      am4core.color("#A43B7D"),
      am4core.color("#5B0A25")
    ];
  }
}

См. Пример из макета

Если что-то подобное ужесуществует, я бы с радостью это увидел.

1 Ответ

0 голосов
/ 29 декабря 2018

Что-то вроде этого не существовало.

К сожалению, не существует простого способа просто использовать heatRules и HeatLegend и заставить их использовать дополнительныецвета.Но не слишком сложно эмулировать heatRules и, если вы используете только 1 marker в вашем HeatLegend (т.е. один длинный столбец в отличие от нескольких столбцов), переопределить его градиент с помощьюПользовательский.

Я взял 2 цвета из предоставленного вами изображения и бросил их и черный в массив:

var heatColors = [
  am4core.color("rgb(248, 227, 211)"),
  am4core.color("rgb(237, 137, 166)"),
  am4core.color("rgb(0,0,0)")
];

Это не обязательно, но может быть полезно.Это цвета трехцветного градиента.Я решил использовать 3 цвета, чтобы мы могли разделить вычисления равномерно между левой / правой половинами градиента, это должно упростить демонстрацию ниже.Для картинки, которой вы поделились, может потребоваться дополнительный цвет в левой половине, вам придется соответствующим образом скорректировать вычисления, но это так же выполнимо.

Чтобы подражать heatRules, мы предоставим адаптер для mapPolygons 'fill.Там мы сравним mapPolygon value с минимальным / максимальным значениями, последние можно найти через серии 'dataItem.values["value"].low и .high.Это даст нам процент в десятичных числах, чтобы получить цвет из диапазона цветов.Функция полезности для выбора цвета из диапазона: am4core.colors.interpolate, первые два аргумента: iRGB s (обычный объект с r, g, b и aсвойства / значения), а третий процент в десятичных числах.Если процент находится в пределах первой половины, у нас будет адаптер, возвращающий цвет между первыми двумя в heatColors выше, если он во второй половине, мы вернем цвет из последних двух.

Вот как выглядит этот код:

polygonSeries.mapPolygons.template.adapter.add("fill", function(
  fill,
  mapPolygon
) {
  var workingValue = mapPolygon.dataItem.values["value"].workingValue;
  var minValue = polygonSeries.dataItem.values["value"].low;
  var maxValue = polygonSeries.dataItem.values["value"].high;
  var percent = (workingValue - minValue) / (maxValue - minValue);
  if (am4core.type.isNumber(percent)) {
    if (percent > 0.5) {
      return new am4core.Color(
        am4core.colors.interpolate(
          heatColors[1].rgb,
          heatColors[2].rgb,
          (percent - 0.5) * 2
        )
      );
    } else {
      return new am4core.Color(
        am4core.colors.interpolate(
          heatColors[0].rgb,
          heatColors[1].rgb,
          percent * 2
        )
      );
    }
  }
  return fill;
});

Если у вас есть 1-маркер heatLegend, то есть просто полоса с градиентом поперек, вы можете сделать свой собственный градиент и назначить его в видеАдаптер тоже:

var gradient = new am4core.LinearGradient();
heatColors.forEach(function(color) {
  gradient.addColor(color);
});
heatLegend.markers.template.adapter.add("fill", function() {
  return gradient;
});

Если у вас есть несколько маркеров в heatLegend (согласно верхней легенде на вашей картинке), пользовательская раскраска будет больше похожа на то, что мы сделали для heatRules,за исключением того, что вместо адаптера, поскольку нам нужно знать их место и нет доступных dataItem или index, мы проведем итерацию по markers, как только они будут готовы, а затем переопределим их цвета там:

var heatLegendTop = chart.createChild(am4maps.HeatLegend);
heatLegendTop.series = polygonSeries;
heatLegendTop.minColor = heatColors[0];
heatLegendTop.maxColor = heatColors[2];
heatLegendTop.marginBottom = 10;
heatLegendTop.markerCount = 10;
heatLegendTop.events.on("inited", function() {
  heatLegendTop.markers.each(function(marker, markerIndex) {

    // Gradient colors!
    if (markerIndex < heatLegendTop.markerCount / 2) {
      marker.fill = new am4core.Color(
        am4core.colors.interpolate(
          heatColors[0].rgb,
          heatColors[1].rgb,
          (markerIndex / heatLegendTop.markerCount) * 2
        )
      );
    } else {
      marker.fill = new am4core.Color(
        am4core.colors.interpolate(
          heatColors[1].rgb,
          heatColors[2].rgb,
          ((markerIndex - heatLegendTop.markerCount / 2) /
            heatLegendTop.markerCount) *
            2
        )
      );
    }
  });
});

Я разбудил демонстрационную карту US heat (choropleth) с приведенным выше кодом, а затем немного, чтобы приблизиться к внешнему виду изображения, которым вы поделились:

https://codepen.io/team/amcharts/pen/7fd84c880922a6fc50f80330d778654a

...