内容简介:网上那些炫酷的热力图是如何绘制的? 相信你也很好奇,本文将以 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.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 每日一博|Python 数据可视化----绘制各种图形
- iOS可视化动态绘制连通图(Swift版)
- Python绘制六种可视化图表详解(建议收藏)
- Python 数据可视化:DataFrame.plot() 函数绘制数据图
- iOS可视化动态绘制八种排序过程(Swift版)
- Python 可视化(4):WordCloud 中英文词云图绘制方法汇总
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Persuasive Technology
B.J. Fogg / Morgan Kaufmann / 2002-12 / USD 39.95
Can computers change what you think and do? Can they motivate you to stop smoking, persuade you to buy insurance, or convince you to join the Army? "Yes, they can," says Dr. B.J. Fogg, directo......一起来看看 《Persuasive Technology》 这本书的介绍吧!