AMCharts Maps v4 - 有没有办法在 heatLegend 中拥有两种以上的颜色? [英] AMCharts Maps v4 - Is there a way to have more than two colors in a heatLegend?

查看:23
本文介绍了AMCharts Maps v4 - 有没有办法在 heatLegend 中拥有两种以上的颜色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

认为能够为热图设置一系列颜色而不是两种(最小和最大)会很好.就像我们对渐变列表所做的一样.

类似……

function am4themes_myHeatmap(target) {如果(am4core.ColorSet 的目标实例){目标.list = [am4core.color("#F7E3D4"),am4core.color("#FFC480"),am4core.color("#DC60BF"),am4core.color("#A43B7D"),am4core.color("#5B0A25")];}}

查看样机示例

如果这样的东西已经存在,我很乐意看到它.

解决方案

不存在这样的东西.

不幸的是,没有一种简单的方法可以仅使用 heatRulesHeatLegend 并让他们使用其他颜色.但是模拟 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.在那里,我们将比较 mapPolygonvalue 与值的最小值/最大值,后者可以通过系列的 dataItem.values 找到["value"].low.high.这将为我们提供一个小数百分比,以便从一系列颜色中获取一种颜色.从范围中选择颜色的实用函数是 am4core.colors.interpolate,它的前两个参数是 iRGBs(带有rgba 属性/值),第三个是小数百分比.如果百分比在前半部分,我们将让适配器在上面的 heatColors 中返回前两者之间的颜色,如果在后半部分,我们将返回后两者的颜色.

代码如下所示:

polygonSeries.mapPolygons.template.adapter.add("fill", function(填,地图多边形){var workingValue = mapPolygon.dataItem.values["value"].workingValue;var minValue =polygonSeries.dataItem.values["value"].low;var maxValue =polygonSeries.dataItem.values["value"].high;var 百分比 = (workingValue - minValue)/(maxValue - minValue);如果(am4core.type.isNumber(百分比)){如果(百分比 > 0.5){返回新的 am4core.Color(am4core.colors.interpolate(heatColors[1].rgb,heatColors[2].rgb,(百分比 - 0.5)* 2));} 别的 {返回新的 am4core.Color(am4core.colors.interpolate(heatColors[0].rgb,heatColors[1].rgb,百分比 * 2));}}回填;});

如果您有一个 1-marker heatLegend,即只是一个带有渐变的条形,您也可以制作自己的渐变并将其分配到适配器中:

var gradient = new am4core.LinearGradient();heatColors.forEach(函数(颜色){渐变添加颜色(颜色);});heatLegend.markers.template.adapter.add("fill", function() {返回梯度;});

如果您在 heatLegend 中有多个标记(根据图片中顶部的热图),自定义着色将更像我们为 heatRules 所做的,除了不是适配器,因为我们需要知道它们的位置并且没有 dataItemindex 可用,我们将遍历 markers 一次他们准备好了,然后在那里覆盖他们的颜色:

var heatLegendTop = chart.createChild(am4maps.HeatLegend);heatLegendTop.series = 多边形系列;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) {//渐变色!如果 (markerIndex < heatLegendTop.markerCount/2) {标记.fill = new am4core.Color(am4core.colors.interpolate(heatColors[0].rgb,heatColors[1].rgb,(markerIndex/heatLegendTop.markerCount) * 2));} 别的 {标记.fill = new am4core.Color(am4core.colors.interpolate(heatColors[1].rgb,heatColors[2].rgb,((markerIndex - heatLegendTop.markerCount/2)/heatLegendTop.markerCount) *2));}});});

我将我们的美国热度(choropleth)地图演示与上述内容分叉代码,然后是一些更接近您共享的图像的外观/感觉:

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

3650/p>

Was thinking that it would be nice to be able to set a range of colors for a heatmap instead of just two (min and max). Like what we do for the gradient list.

Something like...

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")
    ];
  }
}

See example from mockup

If something like this already exists, I would the love to see it.

解决方案

Something like this didn't exist.

Unfortunately there's not a simple way to just use heatRules and HeatLegend and have them use additional colors. But it's not overly complicated to emulate heatRules and if you're only using 1 marker in your HeatLegend (i.e. one long bar as opposed to multiple bars), to override its gradient with a custom one.

I grabbed 2 colors from the image you provided and threw those and black in an array:

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

It's not necessary, but can be useful. Those are the colors of a 3-color gradient. I elected to use 3 colors so we can split the calculations evenly between left/right halves of the gradient, it ought to simplify the demo below. The picture you shared might require an additional color in the left half, you would have to adjust calculations accordingly, but it's just as doable.

To emulate heatRules, we'll provide an adapter for mapPolygons' fill. In there, we'll compare a mapPolygon's value against the min/max of the values, the latter can be found via the series' dataItem.values["value"].low and .high. This will give us a percentage in decimals to grab a color from a range of colors. The utility function to pick a color from a range is am4core.colors.interpolate, its first two arguments are iRGBs (plain object with r, g, b, and a properties/values), and the third is the percentage in decimals. If the percentage is within the first half, we'll have the adapter return a color between the first two in heatColors above, if it's in the second half, we'll return a color from the latter two.

Here's what that code looks like:

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;
});

If you have a 1-marker heatLegend, i.e. just a bar with a gradient going across, you can make your own gradient and assign it in an adapter, too:

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

If you have multiple markers in a heatLegend (as per the top heat legend in your picture), custom coloring would be more like what we did for the heatRules, except instead of an adapter, because we need to know their place and there's no dataItem or index available, we'll iterate through the markers once they're ready and then override their colors there:

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
        )
      );
    }
  });
});

I forked our US heat (choropleth) map demo with the above code and then some to get closer to the look/feel of the image you shared:

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

这篇关于AMCharts Maps v4 - 有没有办法在 heatLegend 中拥有两种以上的颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆