服务器之家:专注于服务器技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - vue.js - vue+canvas实现数据实时从上到下刷新瀑布图效果(类似QT的)

vue+canvas实现数据实时从上到下刷新瀑布图效果(类似QT的)

2022-02-25 16:07Carl323 vue.js

这篇文章主要介绍了vue+canvas实现数据实时从上到下刷新瀑布图效果(类似QT的),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

话不多说了,先上一张Demo图,实现的功能有:左侧图例、右侧瀑布图、鼠标移入弹出当前坐标对应的数据信息(有优化的空间,大家自由发挥)。

vue+canvas实现数据实时从上到下刷新瀑布图效果(类似QT的)

图例使用到的插件

这里推荐使用安装npm插件colormap

瀑布图主体内容

这里不多做解释了,都是一些原生标签还有vue绑定的事件,可以根据实际项目情况自己封装成组件,我这里是写在一起的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
    <div>
        <div class="content">
            <div class="neirong">
                <!--图例-->
                <div class="legend">
                    <canvas ref="legend"></canvas>
                </div>
                <!--瀑布图-->
                <div class="waterFall" ref="waterFallContent"
                     @mousemove="waterFallMove($event)"
                     @mouseleave="waterFallLeave"
                >
                    <canvas ref="waterFall"></canvas>
                    <!--鼠标移入弹出框-->
                    <div ref="tip" class="tip"></div>
                </div>
            </div>
        </div>
    </div>
</template>

这里是用到的Data数据

  • colormap:颜色库
  • legend:图例
  • waterFall:瀑布图
  • waterFallList:瀑布图源数据
  • waterFallIndex:瀑布图定时器用到的计数标识
  • waterFallCopyList:瀑布图二维数组(用来显示数据做的临时储存)
  • waterFallIntervals:瀑布图定时器
  • waterFallWidth:瀑布图的宽度(后端返回的数据length)
  • waterFallHeight:瀑布图定高度(也可以理解成渲染次数 例如30次渲染完成)
  • maxNum:图例最大值
  • minNum:图例最小值
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>
    export default {
        name: "index",
        data() {
            return {
                colormap: [],
                legend: null,
                waterFall: null,
                waterFallList: [],
                waterFallIndex: 0,
                waterFallCopyList: [],
                waterFallIntervals: null,
                waterFallWidth: 0,
                waterFallHeight: 0,
                maxNum: 10,
                minNum: 0
            }
        },

下面是具体的方法,写的比较粗略,大家凑活看吧,觉得有用的大家拿走,不足之处自由发挥修改

方法调用这就不解释了,离开页面销毁定时器。

?
1
2
3
4
5
6
7
8
9
10
mounted() {
            let dx = this
            dx.setColormap()
            dx.createLegendCanvas()
            dx.queryChartList()
        },
        destroyed() {
            let dx = this
            clearInterval(dx.waterFallIntervals)
        },

创建颜色库

这个地方具体看上面插件的官网有详细的介绍

?
1
2
3
4
5
6
7
8
9
10
setColormap() {
      let dx = this
      let colormap = require('colormap')
      dx.colormap = colormap({
          colormap: 'jet',
          nshades: 150,
          format: 'rba',
          alpha: 1,
   })
},

创建图例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
createLegendCanvas() {
                let dx = this
                let legendRefs = dx.$refs.legend
                dx.legend = legendRefs.getContext('2d')
                let legendCanvas = document.createElement('canvas')
                legendCanvas.width = 1
                let legendCanvasTemporary = legendCanvas.getContext('2d')
                const imageData = legendCanvasTemporary.createImageData(1, dx.colormap.length)
                for (let i = 0; i < dx.colormap.length; i++) {
                    const color = dx.colormap[i]
                    imageData.data[imageData.data.length - i * 4 + 0] = color[0]
                    imageData.data[imageData.data.length - i * 4 + 1] = color[1]
                    imageData.data[imageData.data.length - i * 4 + 2] = color[2]
                    imageData.data[imageData.data.length - i * 4 + 3] = 255
                }
                legendCanvasTemporary.putImageData(imageData, 0, 0)
                dx.legend.drawImage(legendCanvasTemporary.canvas,
                0, 0, 1, dx.colormap.length, 50, 0, 200, dx.legend.canvas.height)
            },

创建瀑布图

?
1
2
3
4
5
6
7
createWaterFallCanvas() {
               let dx = this
               let waterFall = dx.$refs.waterFall
               dx.waterFall = waterFall.getContext('2d')
               waterFall.width = dx.waterFallWidth
               waterFall.height = dx.$refs.waterFallContent.offsetHeight
           },

绘制单行图像

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
rowToImageData(data) {
               let dx = this
               if (dx.$refs.waterFallContent !== undefined) {
                   let canvasHeight = Math.floor(dx.$refs.waterFallContent.offsetHeight / dx.waterFallHeight)
                   let imgOld = dx.waterFall.getImageData(0, 0, dx.waterFallWidth, canvasHeight * dx.waterFallIndex + 1)
                   const imageData = dx.waterFall.createImageData(data.length, 1)
                   for (let i = 0; i < imageData.data.length; i += 4) {
                       const cindex = dx.colorMapData(data[i / 4], 0, 130)
                       const color = dx.colormap[cindex]
                       imageData.data[i + 0] = color[0]
                       imageData.data[i + 1] = color[1]
                       imageData.data[i + 2] = color[2]
                       imageData.data[i + 3] = 255
                   }
                   for (let i = 0; i < canvasHeight; i++) {
                       dx.waterFall.putImageData(imageData, 0, i)
                   }
                   dx.waterFall.putImageData(imgOld, 0, canvasHeight)
               }
           },

返回数据对应的Colormap颜色

?
1
2
3
4
5
6
7
8
9
colorMapData(data, outMin, outMax) {
                let dx = this
                if (data <= dx.minNum) {
                    return outMin
                } else if (data >= dx.maxNum) {
                    return outMax
                }
                return Math.round(((data - dx.minNum) / (dx.maxNum - dx.minNum)) * outMax)
            },

鼠标移入瀑布图

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
waterFallMove(event) {
    let dx = this
    let dataWidth = (dx.$refs.waterFallContent.offsetWidth / dx.waterFallWidth).toFixed(2)
    let dataHeight = (dx.$refs.waterFallContent.offsetHeight / dx.waterFallHeight).toFixed(2)
    let x = Math.floor(event.offsetX / dataWidth)
    let y = Math.floor(event.offsetY / dataHeight)
    try {
        dx.$refs.tip.innerHTML = '数值:' + JSON.parse(JSON.stringify(dx.waterFallCopyList[y][x]))
        let xx = event.offsetX + 5
        let yy = event.offsetY - 20
        if (event.offsetX > 1300) {
            xx = event.offsetX - 160
            yy = event.offsetY - 20
        }
        dx.$refs.tip.style.position = 'absolute'
        dx.$refs.tip.style.left = xx + 'px'
        dx.$refs.tip.style.top = yy + 'px'
        dx.$refs.tip.style.display = 'block'
    } catch (e) {
        dx.$refs.tip.style.display = 'none'
    }
},

鼠标移出瀑布图

?
1
2
3
4
waterFallLeave() {
                let dx = this
                dx.$refs.tip.style.display = 'none'
            },

瀑布图假数据模拟

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
queryChartList() {
                let dx = this
                dx.waterFallWidth = 1500
                dx.waterFallHeight = 30
                let data = []
                for (let i = 0; i < 1500; i++) {
                    data.push(Math.floor(Math.random() * (20 - 1)) + 1)
                }
                if (dx.waterFall === null) {
                    dx.createWaterFallCanvas(data.length)
                }
                dx.rowToImageData(data)
                dx.waterFallCopyList.unshift(data)
                dx.waterFallIndex++
                if (dx.waterFallIndex > dx.waterFallHeight) {
                    dx.waterFallCopyList.pop()
                }
                dx.waterFallIntervals = setTimeout(() => {
                    dx.queryChartList()
                }, 1000)
            },

样式代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
.neirong {
        width: 1800px;
        height: 100%;
        margin: 80px auto;
        display: flex;
        justify-content: center;
    }
 
    .legend {
        width: 25px;
        height: 500px;
    }
 
    canvas {
        width: 100%;
        height: 100%;
    }
 
    .waterFall {
        width: 1500px;
        height: 500px;
        position: relative;
    }
 
    .tip {
        pointer-events: none;
        display: none;
        background-color: #0404049e;
        border-radius: 10px;
        color: #fff;
        padding: 10px;
        box-sizing: border-box;
    }

到这里这个Demo基本就是可以运行的,不会有任何报错,代码写的不是很高级,我本人也是个初级的小菜鸟,也是第一次写文章,希望大佬可以给出一些更好的建议我也会好好学习的,也希望那些遇到类似这个需求没什么思路的小伙伴可以借鉴我的踩坑之旅,可以更快的成长起来。

到此这篇关于vue+canvas实现数据实时从上到下刷新瀑布图效果(类似QT的)的文章就介绍到这了,更多相关vue+canvas实时刷新瀑布图 内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/6947886319179677703

延伸 · 阅读

精彩推荐
  • vue.js梳理一下vue中的生命周期

    梳理一下vue中的生命周期

    看过很多人讲vue的生命周期,但总是被绕的云里雾里,尤其是自学的同学,可能js的基础也不是太牢固,听起来更是吃力,那我就已个人之浅见,以大白话...

    CRMEB技术团队7992021-12-22
  • vue.js用vite搭建vue3应用的实现方法

    用vite搭建vue3应用的实现方法

    这篇文章主要介绍了用vite搭建vue3应用的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    Asiter7912022-01-22
  • vue.jsVue中引入svg图标的两种方式

    Vue中引入svg图标的两种方式

    这篇文章主要给大家介绍了关于Vue中引入svg图标的两种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    十里不故梦10222021-12-31
  • vue.jsVue2.x-使用防抖以及节流的示例

    Vue2.x-使用防抖以及节流的示例

    这篇文章主要介绍了Vue2.x-使用防抖以及节流的示例,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下...

    Kyara6372022-01-25
  • vue.jsVue2.x 项目性能优化之代码优化的实现

    Vue2.x 项目性能优化之代码优化的实现

    这篇文章主要介绍了Vue2.x 项目性能优化之代码优化的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    优小U9632022-02-21
  • vue.jsVue项目中实现带参跳转功能

    Vue项目中实现带参跳转功能

    最近做了一个手机端系统,其中遇到了父页面需要携带参数跳转至子页面的问题,现已解决,下面分享一下实现过程,感兴趣的朋友一起看看吧...

    YiluRen丶4302022-03-03
  • vue.jsVue多选列表组件深入详解

    Vue多选列表组件深入详解

    这篇文章主要介绍了Vue多选列表组件深入详解,这个是vue的基本组件,有需要的同学可以研究下...

    yukiwu6752022-01-25
  • vue.js详解vue 表单绑定与组件

    详解vue 表单绑定与组件

    这篇文章主要介绍了vue 表单绑定与组件的相关资料,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下...

    Latteitcjz6432022-02-12