ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vega Heatmap Transform 深入指南:将栅格网格渲染为热力图图像

Vega Heatmap Transform 深入指南:将栅格网格渲染为热力图图像 数据可视化【免费下载链接】vegaA visualization grammar.项目地址https://gitcode.com/gh_mirrors/ve/vega点击查看免费下载heatmap变换Vega 5.8 引入用于将输入的栅格网格矩阵数据渲染为输出热力图图像Canvas bitmap可用来可视化二维栅格数据、密度估计结果或数学函数。本文以 heatmap 官方文档 为主体结合 vega-geo 包中的 Heatmap 实现源码 与仓库中的 heatmap-sinusoids.vg.json、heatmap-image.vg.json 等测试规格完整讲解参数语义、底层像素渲染原理并给出可直接运行的实战配置。一、功能定位从栅格到像素heatmap 变换接收一个数值栅格网格raster grid / matrix作为输入输出是一个 Canvas bitmap 绘制到画布上。其中Canvas bitmap 的内部尺寸与输入栅格网格完全一致每个网格单元对应一个像素实际渲染出的图像尺寸由 image mark 的width、height属性决定完整示例可参考仓库中的 contour-plot 示例可视化。在数据流层面heatmap 变换位于 vega-geo 包中与其配套的通常是生成栅格网格的 kde2d二维核密度估计或isocontour等值线提取变换。该变换的元数据声明为{modifies: true}意味着它会直接修改数据元组并触发下游重排pulse.reflow(true).modifies(as)这一点在 Heatmap.js 的Heatmap.Definition中可见。二、Transform 参数详解heatmap 变换共支持 5 个参数参数定义与默认值如下表所示PropertyType默认值DescriptionfieldField—数据对象本身承载栅格网格数据的字段。若未指定则数据对象本身被解释为栅格网格colorColor | Expr#888灰色设置每个像素颜色的常量颜色值或表达式。若为表达式将以上下文datum调用其中包含网格的$x、$y、$value、$max字段opacityNumber | Expr$value / $max设置每个像素不透明度的常量值或表达式表达式上下文同样包含$x、$y、$value、$maxresolveStringindependent多个输入网格间最大值datum.$max的求解方式。independent默认对每个网格单独计算最大值shared对所有输入网格使用单一全局最大值asStringimage输出字段名用于写入生成的 bitmap canvas 图像源码中对应的参数声明为Heatmap.jsHeatmap.Definition { type: heatmap, metadata: {modifies: true}, params: [ { name: field, type: field }, { name: color, type: string, expr: true}, { name: opacity, type: number, expr: true}, { name: resolve, type: enum, values: [shared, independent], default: independent }, { name: as, type: string, default: image } ] };值得注意的底层细节像素级表达式上下文$x、$y为像素在网格内的行列坐标$value为当前像素对应的网格数值$max为该网格或共享计算时全体网格的数值最大值依赖分析优化源码中的dependency()函数会检测颜色/不透明度函数是否引用了$x、$y、$value、$max字段Heatmap.js。若表达式不依赖像素数据则只计算一次颜色/不透明度并复用为常量从而显著提升渲染性能反之如opacity缺省时的$value / $max则逐像素求值默认不透明度渐变未指定opacity时默认使用obj (obj.$value / obj.$max) || 0即按网格数值归一化得到 [0, max] 区间的不透明度渐变Heatmap.js默认颜色未指定color时使用中灰色#888Heatmap.js。三、渲染管线源码级逐像素实现理解 heatmap 的关键在于其内部渲染循环Heatmap.jsfunction toCanvas(grid, obj, color, opacity) { const n grid.width, m grid.height, x1 grid.x1 || 0, y1 grid.y1 || 0, x2 grid.x2 || n, y2 grid.y2 || m, val grid.values, value val ? i val[i] : zero, can canvas(x2 - x1, y2 - y1), ctx can.getContext(2d), img ctx.getImageData(0, 0, x2 - x1, y2 - y1), pix img.data; for (let jy1, k0; jy2; j) { obj.$y j - y1; for (let ix1, rj*n; ix2; i, k4) { obj.$x i - x1; obj.$value value(i r); const v color(obj); pix[k0] v.r; pix[k1] v.g; pix[k2] v.b; pix[k3] ~~(255 * opacity(obj)); } } ctx.putImageData(img, 0, 0); return can; }从源码可以确认以下事实栅格网格对象的约定结构为{ width, height, values, x1?, y1?, x2?, y2? }其中values是长度为width * height的一维数值数组按行优先row-major存储x1/y1/x2/y2用于裁剪区域缺省时取[0, 0, width, height]使用vega-canvas包的canvas()创建位图通过ctx.getImageData逐像素写入 RGBA 通道RGB 来自颜色函数Alpha 为255 * opacity~~做截断取整field未指定时代码通过_.field || identity直接使用数据元组本身作为栅格Heatmap.js这与文档中数据对象本身被解释为栅格网格的描述一致。四、实战示例一二维密度热力图kde2d heatmap最常见的组合是先用 kde2d 对数据流做二维核密度估计再把输出的密度网格交给 heatmap 渲染。文档给出的核心配置如下{ type: kde2d, x: x_value, y: y_value, size: [{signal: width}, {signal: height}], as: grid }, { type: heatmap, field: grid, color: steelblue, opacity: {expr: datum.$value / datum.$max} }其中kde2d从x_value、y_value字段读取预计算的像素坐标并用width、height信号指定密度计算区域heatmap 使用纯蓝色steelblue作为颜色opacity表达式即默认的归一化渐变$value / $max数值越大的像素越不透明该opacity表达式与源码中未指定opacity时的默认行为完全一致。仓库中的 contour-plot.vg.json 展示了更完整的实战组合先用kde2d按Origin分组生成密度网格再用 heatmap 通过color: {expr: scale(color, datum.datum.Origin)}按分组着色最后叠加isocontour提取的等值线同时用信号resolve动态切换independent/shared最大值求解方式{ type: heatmap, field: datum.grid, resolve: {signal: resolve}, color: {expr: scale(color, datum.datum.Origin)} }另一个可直接运行的实例是 scatter-plot-heatmap.vg.json它对cars.json的马力与油耗字段做二维密度估计用viridis配色并通过表达式scale(density, datum.$value / datum.$max)把归一化密度映射到颜色cellSize以信号绑定方式在 116 之间切换以控制网格分辨率{ type: heatmap, field: datum.grid, color: {expr: scale(density, datum.$value / datum.$max)}, opacity: 1 }五、实战示例二数学函数热力图纯表达式驱动当输入数据本身不携带栅格数值时heatmap 依然可以工作表达式可用$x、$y像素坐标动态计算每个像素的值。文档给出的二维正弦函数示例{ signals: [ {name: scale, value: 0.05} ], scales: [ { name: color, type: linear, domain: [-1, 1], range: {scheme: spectral} } ], data: [ { name: heatmap, values: [{width: 150, height: 100}], transform: [ { type: heatmap, color: { expr: scale(color, sin(scale * (datum.$x datum.$y)) * sin(scale * (datum.$x - datum.$y))) }, opacity: 1 } ] } ] }要点数据对象只声明width: 150, height: 100不提供values此时栅格数值视为全零完全由$x、$y表达式驱动颜色color表达式引用scale(color, ...)将正弦函数值映射到spectral配色方案opacity: 1设为常量关闭默认的数值归一化透明度使颜色完全由表达式决定渲染出的 Canvas 位图内部尺寸为 150×100 像素最终画布尺寸由 image mark 控制。仓库中的完整交互版 heatmap-sinusoids.vg.json 进一步添加了scale、offset、smooth三个可绑定信号range slider 与 checkbox并在 image mark 上设置aspect: false与smooth开关可以在浏览器中实时调节函数频率并观察平滑效果。六、与 image mark 的配合尺寸、平滑与缩放heatmap 变换的输出必须由 image mark 消费。根据 image mark 文档从 Vega 5.8 起 image mark 的image属性可直接接受动态生成的 Canvas 实例url指定时忽略该属性。关键编码属性如下PropertyType默认值Descriptionwidth / heightNumber—最终渲染尺寸通常绑定width/height信号aspectBooleantrue是否保持图像纵横比。热力图中通常设为false使位图拉伸铺满画布smoothBooleantrue缩放时是否平滑插值。设为false时直接按像素放大利于观察原始网格单元在 heatmap-image.vg.json 中可以看到完整的端到端示例数据经formula/timeunit提取小时与日期kde2d以size: [365, 24]、counts: true、bandwidth: [0, 0]、cellSize: 1生成逐日逐时的温度密度网格heatmap 通过color: {expr: scale(color, datum.$value)}映射到 Viridis 配色image mark 负责将位图拉伸到整个画布并叠加坐标轴与渐变图例形成经典的西雅图年平均温度日历热力图。七、resolve 语义多网格最大值的归一化控制当数据流中包含多个栅格网格例如kde2d使用groupby生成按分组的多组网格时$max的含义取决于resolve参数independent默认每个网格单独计算自己的最大值适用于各网格量纲/数值范围差异较大的场景保证每个网格内部对比度充分shared先对所有输入网格求全局最大值再统一用于各网格的归一化适用于需要在不同网格间进行公平对比的场景。源码中的实现为Heatmap.jsvar shared _.resolve shared, obj { $x: 0, $y: 0, $value: 0, $max: shared ? max(source.map(t max(field(t).values))) : 0 }; source.forEach(t { const v field(t); const o extend({}, t, obj); if (!shared) o.$max max(v.values || []); t[as] toCanvas(v, o, color.dep ? color : constant(color(o)), opacity.dep ? opacity : constant(opacity(o)) ); });可以看到shared模式下$max在遍历前一次性计算完成各网格共享同一最大值independent模式下每个网格在循环内单独求$max。八、性能与最佳实践综合源码实现与仓库示例可总结以下实践建议善用依赖分析优化颜色/不透明度表达式若未引用$x、$y、$value、$max则整张图只求值一次反之则逐像素调用表达式越简单渲染越快控制网格分辨率kde2d的cellSize决定网格粒度1时网格尺寸与size一致4时宽高各减半2 倍降采样。分辨率越高位图越大内存与计算开销随之上升aspect: false保证铺满热力图位图与画布宽高比不一致时应显式关闭 aspect避免出现留白smooth按需开关需要观察网格单元边界时关闭平滑追求视觉连续时保持开启与等值线叠加同一密度网格可同时供 heatmap 与isocontour消费见 contour-plot.vg.json形成热力图底图 等值线轮廓的层次化呈现。九、总结heatmap 变换是 Vega 中把数据矩阵转化为可视化图像的桥梁配合kde2d可快速呈现二维密度分布配合纯表达式可生成函数图像配合isocontour可叠加等值线。理解其$x/$y/$value/$max表达式上下文、resolve归一化语义与 image mark 的尺寸/平滑控制即可在 heatmap 官方文档 基础上自由构建从数据探索到函数可视化的各类热力图应用。赞分享数据可视化【免费下载链接】vegaA visualization grammar.项目地址https://gitcode.com/gh_mirrors/ve/vega点击查看免费下载相关推荐终极指南如何快速将栅格图像转为矢量图像 终极指南如何快速将栅格图像转为矢量图像 在当今数字化时代 图像矢量化 已成为设计师和内容创作者的必备技能。想象一下当你需要将一张低分辨率的PNG或J图像处理deck.gl GridLayer 完全指南网格聚合热力图的属性、渲染与底层原理deck.gl GridLayer 完全指南网格聚合热力图的属性、渲染与底层原理 GridLayer 是 deck.gl 聚合图层AggregationLa前端数据可视化3D渲染图形学Vuetify VHeatmap 组件实战指南用 v-heatmap 构建日历热力图与数据网格Vuetify VHeatmap 组件实战指南用 v heatmap 构建日历热力图与数据网格 v heatmap 是 Vuetify 实验室Labs提供前端UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表