zoukankan      html  css  js  c++  java
  • 【JS】heatmap.js v1.0 到 v2.0,详细总结一下:)

    前段时间,项目要开发热力图插件,研究了heatmap.js,打算好好总结一下。

    本文主要有以下几部分内容:

    1. 部分源码理解
    2. 如何迁移到v2.0
    3. v2.0官方文档译文

    关于heatmap.js介绍,请看这里: http://www.oschina.net/p/heatmap-js

    目前,对于热力图的开发,百度、高德开发平台上使用的都是这款JS开源库。当然,现在还有我们公司:P

    百度示例:http://developer.baidu.com/map/jsdemo.htm#c1_15

    高德示例:http://lbs.amap.com/api/javascript-api/example/layers/heatmap/

    PS:本人对JS只能算是初级水平,刚开始写热力图插件的时候,真是一头雾水。充分利用搜索引擎后,在百度的开源库发现了这个(示例源文件),总算有点眉目了。替换了地图实例对象,剩下的难点是图层处理和像素坐标转换,删删改改,也弄出了插件的1.0版。v2.0版本的内容与v1.0相比还是有很多不同的,经过大半天废寝忘食的努力,终于迁移到了2.0(准确的说是v2.0.5),也算对得起忘吃的午饭。

    部分源码理解

    参数max

      经过源码阅读和测试,数据集合中的max参数表示热力点权值的最大值,用于热力颜色渐变的计算。其本质是热力区域内部填充颜色的透明度。

    使用到max的算式:

    (value-min)/(max-min)    
    /* 其中,
            value是某个热力点的权值;
            max是最大权值,默认是1;
            min是最小权值,默认是10;
    */

    当热力点权值大于等于max,热力点颜色达到最大渐变程度。

    当热力点权值远远小于max,热力点颜色较浅,甚至显示不出来。

    所以,max的设定值会影响到热力图的展现效果,需要均衡热力点权值,合理设置max值。
     
    (——为什么显示不出?根据前面算式,计算结果小于0.01已经不能被识别了。请查看canvas的globalalpha属性)
     

    addData方法

      该方法的参数可以是单个点的对象,也可以是个数组。但是方法内的处理是,在原图的基础上每增加一个点就渲染一次。如果参数类型是数组,则递归调用本方法,逐个点的增加并渲染。

      如果数据是少量动态增加的,则可以实时的呈现出热力状况。当大数据量频繁更新的时候,推测对性能还是会有一点影响吧,这个需要测试验证。

      ——2016-11-28 补充验证结果:使用此方法添加10条数据,几乎是立刻呈现;添加100条,需要2秒左右;添加1000条,需要20秒左右。测试浏览器为Chrome 版本53。

    使用删除方法(即用setData方法重新绘图)删除100条、1000条数据,基本都在1秒以内。

      另外一点需要注意的是,新增的热力点的权值对max的值有影响。源码中,会对同一坐标点的权值进行累加然后设置到Store._max属性,这会使颜色渐变的标准发生改变,影响热图的一致性。

      github上也有人提出这个问题[How not to change 'max' when adding point with addData?]正问题中所描述的那样,要想保证颜色渐变的标准在增加热力点前后保持一致性,需要调用setDataMax方法重新设定max值,目前只能这样。

    removeData方法

      我所使用的是heatmap v2.0.5版本,其中removeData方法还是空的,具体处理还没有实现。所以我在插件中自己写了一个方法。

    采用二次循环,将现存的数据与要删除的数据进行比对,只保留那些经纬度不相同的数据,以及经纬度相同但是权值差大于0的数据,然后清空画布,调用setData重新赋值绘图。

    方法有点low,求指点~~

    内部数据存储

      heatmap.js内部把数据存储在Store._data属性中。其数据格式是二维数组[x: [y: value]],x、y是热力点的像素坐标,value是热力点的权值。例如: 
    data = [460: [280:15, 255:6], 490: [251:8], 416: [289:9]]

    数组的长度是可变的,最外层长度是所有x值中最大的那个数值加1,如 data.length = 491。

    每个x元素所对应的y值数组的长度,是x坐标下所有y值中最大的那个数值加1,如 data[460].length = 281 。
     
    两个处理数据的方法:

       _organiseData方法会将外部传入数据存储到Store._data中,并且会累计权值。如果本方法是被setData调用,则按照传入参数中max来渲染;如果是被addData方法调用,则会按累计权值渲染。

       _unOrganizeData方法内部并无特殊处理,只是将内部以二维数组存储的数据转换为外部数据格式对象,该方法被getData方法调用,返回热力数据。

     

    如何迁移到v2.0

    以下内容来自这里:https://github.com/pa7/heatmap.js/blob/master/docs/how-to-migrate.md

    1. element -> container 

     作为热图canvas的容器,heatmap作者认为“container”能更加形象的描述这个配置参数,所以原来的element属性现在叫container。

    var cfg = {
       "container": domElement
    };

    2. opacity -> maxOpacity

    heatmap.js v2.0中的透明度属性opacity,会对全局的透明度产生影响(它会为所有热力点设置透明度,还会阻止颜色渐变的平滑性)。
    如果你想让热点数据的颜色渐变达到平滑的效果,现在起你需要使用配置属性maxOpacity。
    var cfg = {
       "maxOpacity": .8
    }

     另外,opacity、maxOpacity、minOpacity这仨属性现在都是[0,1]范围内的数。

    3. 装填数据

    heatmap.js的作者决定减少API,使其变为更扁平的结构。为了添加数据你不必访问heatmap的数据存储,而是向heatmap实例直接添加新数据。同时也摆脱了重复命名。(heatmap.store.addDataPoint -> heatmap.addData, heatmap.store.setDataSet -> heatmap.setData).
    var datapoint = { x: 100, y: 100, value: 10 }; 
    
    heatmap.addData(datapoint); 
    
    heatmap.setData({ 
        max: 10, 
        data: [datapoint] 
    });

    同时,你可能注意到:热力点的权值属性count现在默认叫value,为了顺利迁移你可以把“count”设置为valueField属性的值。

    var datapoint = { x: 100, y: 100, count: 10 };
    
    var heatmap = h337.create({
       container: domElement,
       // ...
       valueField: 'count'
    });
    
    heatmap.addData(datapoint);
    
    heatmap.setData({
       max: 10,
       data: [datapoint]
    });

    4. 总结

    旧的配置实例:

    var cfg = { 
        "element": domElement,
        "opacity": 80 
    } 
    
    var heatmap = h337.create(cfg);
    
    heatmap.store.setDataSet(data);

    变成了新的配置:

    var cfg = {
       "container": domElement,
       "maxOpacity": .8
    }
    
    var heatmap = h337.create(cfg);
    
    heatmap.setData(data);

    本人补充几条:

    1. 支持自定义热点数据的属性名称

    如果之前你的热力数据是这样的:

    {"lng":123.456789, "lat":987.654321, "count": 10}

    为了向heatmap内部设置数据,你需要将数据转换成这样的:

    {"x":123.456789, "y":987.654321, "value": 10}

    现在,配置参数中新增加了三个属性xField、yField、valueField,分别对应x坐标、y坐标、权值的属性名称。设置了这三个属性就不需要上面的数据格式转换了。例如:xField="lng"; yField="lat"; valueField="count;

    2. 清空画布

    我之前的做法是:

    heatmap.clear();

    现在是:

    heatmap._renderer._clear();

    3. 重置画布大小

    之前是:

    heatmap.set("width", w);
    heatmap.set("height", h);
    heatmap.store.get("heatmap").resize();

    现在改为:

    heatmap._renderer.setDimensions(w, h);

    v2.0官方文档译文

    下面是我翻译的heatmap.js v2.0官方文档。水平有限,如有疏漏或错误请指正。

    API函数的优先级排序:

      红色 最常用的函数;-)
      绿色 用于自定义实现
      蓝色 较少使用的功能

    h337

    • create(configObject)
    • register(pluginKey, plugin)

    heatmapInstance

    • addData(object|array)
    • setData(object)
    • setDataMax(number)
    • setDataMin(number)
    • configure(configObject)
    • getValueAt(object)
    • getData()
    • getDataURL()
    • repaint() 

    h337

    "h337"是heatmap.js注册的全局对象的名字。你可以用它创建heatmap实例。

    h337.create(configObject)

    返回一个heatmap实例对象heatmapInstance
    使用h337.create创建heatmap实例。通过设置配置参数configObject可以实现热力图的自定义。配置参数configObject是必需参数。

    可配置的属性:

    • container 图像容器 (DOMNode)  必需参数

      它是热力图像canvas所依附的DOM节点(热图将适应节点的大小)。

    • backgroundColor 背景色 (string)  可选参数

      背景色字符串可以是16进制编码、英文颜色名称、rgb颜色。

    • gradient 渐变度 (object)  可选参数

      代表颜色渐变的对象(语法:数值字符串[0,1]: 颜色字符串),请查看代码示例。

    • radius  半径 (number)  可选参数

      每个热力点的半径(如果节点本身未被指定)。

    • opacity  透明度 (number) [0,1]  可选参数 default = .6   

      heatmap的全局透明度。将覆盖之前设置的maxOpacity 和 minOpacity。

    • maxOpacity  最大透明度 (number) [0,1]  可选参数

      heatmap将拥有的最大透明度。(会被opacity的设置覆盖)。

    • minOpacity 最小透明度 (number) [0,1]  可选参数

      heatmap将拥有的最小透明度。(会被opacity的设置覆盖)。

    • onExtremaChange function callback 回调函数

      传递一个回调函数来接收极值变化更新。对于DOM legends很有用。

    • blur  滤镜系数 (number) [0,1] 可选参数 default = 0.85 ,应用于所有点数据。系数越高,渐变越平滑,默认是0.85

      滤镜系数将应用于所有热点数据。系数越高,颜色渐变越平滑。

    • xField (string) 可选参数 default = "x" 

      热点数据x坐标的属性名称。

    • yField (string) 可选参数 default = "y" 

      热点数据y坐标的属性名称。

    • valueField (string) 可选参数 default = "value" 

      热点数据权值的属性名称。

    配置示例

    简单配置和标注颜色渐变
    // create configuration object 
    var config = { 
        container: document.getElementById('heatmapContainer'),
        radius: 10, 
        maxOpacity: .5, 
        minOpacity: 0, 
        blur: .75};
    // create heatmap with configuration 
    var heatmapInstance = h337.create(config);

     自定义颜色渐变

    // create configuration object 
    var config = { 
        container: document.getElementById('heatmapContainer'), 
        radius: 10, 
        maxOpacity: .5, 
        minOpacity: 0, 
        blur: .75, 
        gradient: { 
            // enter n keys between 0 and 1 here 
            // for gradient color customization 
            '.5': 'blue', 
            '.8': 'red', 
            '.95': 'white' 
        }};var heatmapInstance = h337.create(config);

    heatmapInstance

    热力图实例是通过 h337.create方法返回的。热力图实例有自己的内部数据存储对象和渲染对象,你可以通过它们来操作数据,使热力图得到更新(根据需要决定是局部更新,还是全部更新)。

    heatmapInstance.addData(object|array)

    返回heatmapInstance
    使用此功能只是用于随时添加数据,而不是用于数据初始化。addData方法可以向heatmap的数据存储对象添加单个或者多个点的数据。
    // a single datapoint 
    var dataPoint = { 
        x: 5, // x coordinate of the datapoint, a number 
        y: 5, // y coordinate of the datapoint, a number 
        value: 100 // the value at datapoint(x, y) 
    }; 
    heatmapInstance.addData(dataPoint);
    // multiple datapoints (for data initialization use setData!!) 
    var dataPoints = [dataPoint, dataPoint, dataPoint, dataPoint]; heatmapInstance.addData(dataPoints);

    heatmapInstance.setData(object)

    返回heatmapInstance

    通过数据集合初始化heatmap。“min”、“max”和“data”这三个参数是必需的。setData从实例中清除所有之前存储的数据,然后重新初始化数据存储对象。
    var data = { 
        max: 100, 
        min: 0, 
        data: [ 
            dataPoint, dataPoint, dataPoint, dataPoint 
        ]}; 
    heatmapInstance.setData(data);

    heatmapInstance.setDataMax(number)

    返回heatmapInstance
    改变数据集的上限并且触发完全渲染。
    heatmapInstance.setDataMax(200);
    // setting the maximum value triggers a complete rerendering of the heatmap 
    heatmapInstance.setDataMax(100);

    heatmapInstance.setDataMin(number)

    返回heatmapInstance
    改变数据集的下限并且触发完全渲染。
    heatmapInstance.setDataMin(10);
    // setting the minimum value triggers a complete rerendering of the heatmap 
    heatmapInstance.setDataMin(0);

    heatmapInstance.configure(configObject)

    返回heatmapInstance
    在heatmap实例初始化之后重新配置参数。触发完全渲染。
    var nuConfig = { 
        radius: 10, 
        maxOpacity: .5, 
        minOpacity: 0, 
        blur: .75}; 
    heatmapInstance.configure(nuConfig);

    heatmapInstance.getValueAt(object)

    返回热力点的权值。
    注意:如果该点没有被存储的话,返回值是基于颜色渐变混合后的填充值。
    heatmapInstance.addData({ x: 10, y: 10, value: 100});
    // get the value at x=10, y=10 
    heatmapInstance.getValueAt({ x: 10, y: 10 }); // returns 100

    heatmapInstance.getData()

    返回一个持久化并且可重装的JSON对象。

    var currentData = heatmapInstance.getData();
    // now let's create a new instance and set the data 
    var heatmap2 = h337.create(config); 
    heatmap2.setData(currentData); // now both heatmap instances have the same content

    heatmapInstance.getDataURL()

    返回值是base64编码的dataURL字符串。

    heatmapInstance.getDataURL(); // data:image/png;base64... 
    // ready for saving locally or on the server

    heatmapInstance.repaint()

    返回heatmapInstance
    重新绘制整个热力图canvas。

    ----------------------完 结----------------------------------------------------------------------------------------------------------------------

  • 相关阅读:
    2010浙大:zoj问题
    Meta 数据中文显示
    django 中间件
    url的配置
    django.contirb
    os模块
    线程和异步
    ADO.NET
    C#托管代码 CLR
    C#垃圾回收
  • 原文地址:https://www.cnblogs.com/quiet-snowy-day/p/6100088.html
Copyright © 2011-2022 走看看