dc.js 热图 - 使顶行矩形从 y="0" 开始
dc.js heatmap - make the top row rects to begin at y="0"
我有一个 dc.js 热图在工作:
但是我想给它添加网格线,像这样:
您可以看到线条与矩形的底部边缘不匹配。自己插入线条很容易,您只需从零开始,然后根据矩形的高度添加 11 行,在本例中始终为 11 / chart.effectiveHeight().
它们不匹配的原因似乎是最上面的 rect 行并不总是从 0 开始,相反,图表似乎有一个随机的(?)y 位置开始,这会改变与图表容器的高度,例如这个 y 位置从 5 开始:
如果它是一致的,那么我可以从该数字而不是 0 开始追加行,但事实并非如此。我已经尝试了几个 hacky 解决方法,但是我不确定如何在 DOM.
中可用后获得所有矩形的 y 位置
有趣的是演示热图没有这个问题:
这是热图的代码:
const heat_map = dc.heatMap('#heatmap');
heat_map
.width(0)
.height(0)
.margins(margins)
.dimension(hm_dim)
.group(hm_group)
.keyAccessor(function(d) { return +d.key[0]; })
.valueAccessor(function(d) { return +d.key[1]; })
.colorAccessor(function(d) { return +d.value; })
.colors(color_scale)
.calculateColorDomain()
.yBorderRadius(0)
.xBorderRadius(0)
heat_map.render();
有没有办法强制矩形从 0 开始?或者获取顶行的随机 y 位置?我确实看过源代码,但有点迷路了。我还考虑过创建一个包含网格中每个矩形的假组,然后网格线可以是矩形边界,但我认为这有点笨拙。
使用 CSS
勾勒单元格
使用 CSS 可以很容易地勾勒出单元格的轮廓:
rect.heat-box {
stroke-width: 1;
stroke: black;
}
但是,正如您所指出的,这仅在所有单元格都有值的情况下才有效; crossfilter 不会创建空的,我同意只为某些行使用假组来填充它们是荒谬的。
那么,回答你原来的问题...
为什么图表顶部有空隙?
热图计算单元格的整数大小,可能还有 space 剩余(因为 space 不能完美划分)。
这有点令人讨厌,但热图示例通过使用每个维度中的单元格计数计算图表的宽度和高度,避免了额外的 space:
chart
.width(45 * 20 + 80)
.height(45 * 5 + 40)
默认边距为 {top: 10, right: 50, bottom: 30, left: 30}
,因此这会为每个单元格分配 45x45 像素并增加边距以获得正确的图表大小。
由于本例中的热图绘制了 20 列乘 5 行,因此它将计算单元格的宽度和高度为 45。
Responsive/Resizable 图表的替代答案
在重写我的热图图表以响应之后,我正在重新审视这个问题 - 使用 dc.js resizing examples and Gordon's answer to
中概述的“ResizeObserver”方法
虽然在 Gordon 的回答中为热图指定图表宽度和高度仍然有效,但它不能很好地与调整大小的方法结合,因为调整大小的图表会将其 .width 和 .height 设置为 'null'。这意味着这个舍入问题将再次发生,热箱将再次被 0 到 5 之间任意整数 x 或 y 值偏移(除非您想为热图编写自定义调整大小函数)。
备选答案相对简单,只需在热图中选择一个热箱元素即可确定。
热箱的垂直偏移值是热箱 y 属性除以热箱高度属性的余数。
const heatbox_y = heat_map.select('.heat-box').attr('y);
const heatbox_height = heat_map.select('.heat-box').attr('height')
const vertical_offset = heatbox_y % heatbox_height
模数 % 将 return 余数。
水平偏移可以用同样的方法确定。
因此,您可以按 heatbox_height + vertical_offset 值确定的固定间隔向图表添加线条。
如果您在图表中选择任何热箱,这将起作用,因此它适用于无法保证在每个 x 或 y 级别都有一个热箱的情况。这意味着如果需要,您可以自由地将图表高度和宽度设置为 'null'。
我有一个 dc.js 热图在工作:
但是我想给它添加网格线,像这样:
您可以看到线条与矩形的底部边缘不匹配。自己插入线条很容易,您只需从零开始,然后根据矩形的高度添加 11 行,在本例中始终为 11 / chart.effectiveHeight().
它们不匹配的原因似乎是最上面的 rect 行并不总是从 0 开始,相反,图表似乎有一个随机的(?)y 位置开始,这会改变与图表容器的高度,例如这个 y 位置从 5 开始:
如果它是一致的,那么我可以从该数字而不是 0 开始追加行,但事实并非如此。我已经尝试了几个 hacky 解决方法,但是我不确定如何在 DOM.
中可用后获得所有矩形的 y 位置有趣的是演示热图没有这个问题:
这是热图的代码:
const heat_map = dc.heatMap('#heatmap');
heat_map
.width(0)
.height(0)
.margins(margins)
.dimension(hm_dim)
.group(hm_group)
.keyAccessor(function(d) { return +d.key[0]; })
.valueAccessor(function(d) { return +d.key[1]; })
.colorAccessor(function(d) { return +d.value; })
.colors(color_scale)
.calculateColorDomain()
.yBorderRadius(0)
.xBorderRadius(0)
heat_map.render();
有没有办法强制矩形从 0 开始?或者获取顶行的随机 y 位置?我确实看过源代码,但有点迷路了。我还考虑过创建一个包含网格中每个矩形的假组,然后网格线可以是矩形边界,但我认为这有点笨拙。
使用 CSS
勾勒单元格使用 CSS 可以很容易地勾勒出单元格的轮廓:
rect.heat-box {
stroke-width: 1;
stroke: black;
}
但是,正如您所指出的,这仅在所有单元格都有值的情况下才有效; crossfilter 不会创建空的,我同意只为某些行使用假组来填充它们是荒谬的。
那么,回答你原来的问题...
为什么图表顶部有空隙?
热图计算单元格的整数大小,可能还有 space 剩余(因为 space 不能完美划分)。
这有点令人讨厌,但热图示例通过使用每个维度中的单元格计数计算图表的宽度和高度,避免了额外的 space:
chart
.width(45 * 20 + 80)
.height(45 * 5 + 40)
默认边距为 {top: 10, right: 50, bottom: 30, left: 30}
,因此这会为每个单元格分配 45x45 像素并增加边距以获得正确的图表大小。
由于本例中的热图绘制了 20 列乘 5 行,因此它将计算单元格的宽度和高度为 45。
Responsive/Resizable 图表的替代答案
在重写我的热图图表以响应之后,我正在重新审视这个问题 - 使用 dc.js resizing examples and Gordon's answer to
虽然在 Gordon 的回答中为热图指定图表宽度和高度仍然有效,但它不能很好地与调整大小的方法结合,因为调整大小的图表会将其 .width 和 .height 设置为 'null'。这意味着这个舍入问题将再次发生,热箱将再次被 0 到 5 之间任意整数 x 或 y 值偏移(除非您想为热图编写自定义调整大小函数)。
备选答案相对简单,只需在热图中选择一个热箱元素即可确定。
热箱的垂直偏移值是热箱 y 属性除以热箱高度属性的余数。
const heatbox_y = heat_map.select('.heat-box').attr('y);
const heatbox_height = heat_map.select('.heat-box').attr('height')
const vertical_offset = heatbox_y % heatbox_height
模数 % 将 return 余数。
水平偏移可以用同样的方法确定。
因此,您可以按 heatbox_height + vertical_offset 值确定的固定间隔向图表添加线条。
如果您在图表中选择任何热箱,这将起作用,因此它适用于无法保证在每个 x 或 y 级别都有一个热箱的情况。这意味着如果需要,您可以自由地将图表高度和宽度设置为 'null'。