美文网首页
前端热力图制作

前端热力图制作

作者: cendechen | 来源:发表于2018-05-11 19:48 被阅读0次

    最近做一个项目,需要绘制热力图,但是发觉现成的库封装都很不灵活
    heatmap.js
    百度Echarts
    等都有封装

    参考百度echarts的热力图插件,我整理了一下绘制热力图的思路

    数据构成

    [[x, y, cnt], [x, y, cnt]]
    // x y 表示这个点在canvas上的位置
    

    对canvas的简单封装

    function Canvas(w, h) {
      this.canvas = document.createElement('canvas')
      this.canvas.width = w
      this.canvas.height = h
    }
    Canvas.prototype.getContext = function() {
      return this.canvas.getContext('2d') 
    }
    Canvas.prototype.getCanvas = function(){
      return this.canvas
    }
    
    

    创建canvas的每个点的渐变色

    function creatHeadtMapCircle(size) {
      const shadowBlur = size / 2
      const r = size + shadowBlur
      const offsetDistance = 1000
      const circle =  new Canvas(r * 2, r * 2)
      let ctx = circle.getContext()
      ctx.shadowBlur = shadowBlur
      ctx.shadowColor = 'black'
      ctx.shadowOffsetX = ctx.shadowOffsetY = offsetDistance
      ctx.beginPath()
      ctx.arc( r - offsetDistance, r2 - offsetDistance, size, 0, Mathi.PI * 2 , true)
      ctx.closePath()
      ctx.fill()
      return circle
    }
    

    绘制单个点的结果


    image.png

    绘制多个点,根据权重值,可以得到如下的图形, 不同的权重 设置不同的透明度


    image.png

    创一个颜色映射

    class ColorRange {
      constructor (options) {
      this.gradient = options.gradient || {
          0.25: 'rgba(0, 0, 255, 1)',
          0.55: 'rgba(0, 255, 0, 1)',
          0.85: 'rgba(255, 255, 0, 1)',
          1.0: 'rgba(255, 0, 0, 1)'
        }
        this.max = options.max || 30
        this.min = options.min || 0
        this.initPalette()
      }
      initPalette () {
        const gradient = this.gradient
        const canvas = new Canvas(256, 1)
        const ctx = this.ctx = canvas.getContext()
        const lineGradient = ctx.createLinearGradient(0, 0, 256, 1)
        for (let key in gradient) {
          lineGradient.addColorStop(parseFloat(key), gradient[key])
        }
        ctx.fillStyle = lineGradient
        ctx.fillRect(0, 0, 256, 1)
      }
       getImageData (v ) {
        const imageData = this.ctx,getImageData(0, 0, 256, 1).data
        if (v === undefined) return imageData
        if (v > this.max)  v = this.max
        if (v < this.min )  v = this.min
        var index = Math.floor((v - min) / (max - min) * 255 ) * 4
        return [imageData[index], imageData[index + 1], imageData[index + 2], imageData[index + 3]]  
      }
    }
    

    颜色映射

    根据不同的绘图结果把不同的颜色透明度,映射到不同的颜色上,得到色彩图

    let colored = sctx.getImageData(0, 0, canvas.width, canvas.height)
    let gradient = (new ColorRange()).getImageData()
    const opacity = 0.8
    for(let i = 0, len = colored.data.length, j; i < len; i += 4) {
      j = colored.data[i] * 4
      if (colored.data[i] / 256 > opacity) colored.data[i] = 256 * opacity
      colored.data[i - 3] = gradient[j]
      colored.data[i - 2] = gradient[j + 1]
      colored.data[i - 1] = gradient[j + 2]
    }
    ctx.putImageData(colored, 0, 0)
    
    image.png

    最后整理成一个快速好用的库,提供给大家

    相关文章

      网友评论

          本文标题:前端热力图制作

          本文链接:https://www.haomeiwen.com/subject/hnqqdftx.html