【 可视化】热力图绘制原理

栏目: Html5 · 发布时间: 6年前

内容简介:网上那些炫酷的热力图是如何绘制的? 相信你也很好奇,本文将以 canvas 作为绘图示例来讲解热力图的原理。我们经常遇到透明度的概念,如 CSS 中的opacity 属性、rgba 颜色中的 alpha 变量、canvas 中的globalAlpha 属性等。它们的取值范围一般是 0-1 之间,0 表示完全透明,1 表示不透明,值越小,越透明。

网上那些炫酷的热力图是如何绘制的? 相信你也很好奇,本文将以 canvas 作为绘图示例来讲解热力图的原理。

透明度

我们经常遇到透明度的概念,如 CSS 中的opacity 属性、rgba 颜色中的 alpha 变量、canvas 中的globalAlpha 属性等。

它们的取值范围一般是 0-1 之间,0 表示完全透明,1 表示不透明,值越小,越透明。

透明度叠加

思考一个问题:透明度为 0.2 的矩形跟透明度为 0.6 的矩形叠加后的透明度为多少?

结果可以看以下示例,通过 canvas 的 getImageData 方法输出了叠加后的透明度(值除以 255 即可)

See the Pencanvas-opacity by linghuam (@linghuam) onCodePen.

很多人的第一感觉也许是 0.8,其实这是一种想当然的理解。正确的思路如下:

假设把透明度理解成玻璃的透光性,这样 alpha=0.2 表示一束光照射到玻璃上,有 20% 的光线被反射回来(这一部分光线会进入你的眼睛),80% 穿透过去,这时我们看到的东西就会很模糊。同理,alpha=0 表示光线全部穿透过去,所以我们什么都看不见,alpha=1 表示光线全部被反射,所以我们能看见全部。

那么 alpha=0.2 和 alpha=0.6 的叠加相当于两块玻璃叠加,第一块玻璃有 80% 光线穿透, 第二块在第一块穿透过的光线中,有 40% 光线穿透,这样穿过两块玻璃后被反射多少光线呢,计算方法如下: 1*0.2 + (1-0.2)*0.6 = 0.68 , 所以最后的透明度是 0.68 而不是 0.8。

下面一篇文章总结了其计算公式: 两个半透明颜色色的叠加计算方法

热力图原理

其实热力图就是根据透明度的大小和叠加来渲染的。

首先我们的数据集是一个对象数组,每个元素包含了 { x, y, value } 属性。我们首先从这一组值中找出 value 最大值 max,然后用 value/max 的值来表示透明度,这样我们可以在画布中绘制不同透明度的小圆圈,起初这些圆圈都是黑白的,所以下一步需要根据不同透明度来进行着色处理。

通过查看 mapv 源码发现,它实现了一个 Intensity 类用来对不同透明度实现一个渐变色。

首先他创建了一个 256 * 1 的 canvas ,然后利用 canvas 的createLinearGradient 来将渐变色填充进去,这样一个透明度值就可以对应 canvas 上的一个颜色值,通过 getImageData 方法就可以根据透明度来取对应的颜色值。

截取部分核心代码:

// 创建一个 256*1 的 canvas 并填充渐变色
Intensity.prototype.initPalette = function () {

    var gradient = this.gradient;

    var canvas = new Canvas(256, 1);

    var paletteCtx = this.paletteCtx = canvas.getContext('2d');

    var lineGradient = paletteCtx.createLinearGradient(0, 0, 256, 1);

    for (var key in gradient) {
        lineGradient.addColorStop(parseFloat(key), gradient[key]);
    }

    paletteCtx.fillStyle = lineGradient;
    paletteCtx.fillRect(0, 0, 256, 1);

}

// 通过透明度值取到对应的颜色
Intensity.prototype.getImageData = function (value) {

    var imageData = this.paletteCtx.getImageData(0, 0, 256, 1).data;

    if (value === undefined) {
        return imageData;
    }

    var max = this.max;
    var min = this.min;

    if (value > max) {
        value = max;
    }

    if (value < min) {
        value = min;
    }

    var index = Math.floor((value - min) / (max - min) * (256 - 1)) * 4;

    return [imageData[index], imageData[index + 1], imageData[index + 2], imageData[index + 3]];
}
复制代码

当然,为了热力图更好看,作者用了 canvas 的shadowBlur 来实现一个边缘模糊效果。

至此,热力图的实现原理就介绍完了,下面是我根据这个原理做的一个小 Demo:

See the Pencanvas-heatmap by linghuam (@linghuam) onCodePen.


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

jQuery实战(第2版)

jQuery实战(第2版)

[美]Bear Bibeault、[美]Yehuda Katz / 三生石上 / 人民邮电出版社 / 2012-3 / 69.00元

jQuery 是目前最受欢迎的JavaScript/Ajax 库之一,能用最少的代码实现最多的功能。本书全面介绍jQuery 知识,展示如何遍历HTML 文档、处理事件、执行动画、给网页添加Ajax 以及jQuery UI 。书中紧紧地围绕“用实际的示例来解释每一个新概念”这一宗旨,生动描述了jQuery 如何与其他工具和框架交互以及如何生成jQuery 插件。 本书适合各层次Web 开发人......一起来看看 《jQuery实战(第2版)》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器