好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

图例使用到的插件

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

瀑布图主体内容

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

?

<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:图例最小值

?

<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

             }

         },

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

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

?

mounted() {

             let dx = this

             dx.setColormap()

             dx.createLegendCanvas()

             dx.queryChartList()

         },

         destroyed() {

             let dx = this

             clearInterval(dx.waterFallIntervals)

         },

创建颜色库

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

?

setColormap() {

       let dx = this

       let colormap = require( 'colormap' )

       dx.colormap = colormap({

           colormap: 'jet' ,

           nshades: 150,

           format: 'rba' ,

           alpha: 1,

    })

},

创建图例

?

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)

             },

创建瀑布图

?

createWaterFallCanvas() {

                let dx = this

                let waterFall = dx.$refs.waterFall

                dx.waterFall = waterFall.getContext( '2d' )

                waterFall.width = dx.waterFallWidth

                waterFall.height = dx.$refs.waterFallContent.offsetHeight

            },

绘制单行图像

?

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颜色

?

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)

             },

鼠标移入瀑布图

?

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'

     }

},

鼠标移出瀑布图

?

waterFallLeave() {

                 let dx = this

                 dx.$refs.tip.style.display = 'none'

             },

瀑布图假数据模拟

?

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)

             },

样式代码

?

.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 : #040404 9e;

         border-radius: 10px ;

         color : #fff ;

         padding : 10px ;

         box-sizing: border-box;

     }

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

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

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

查看更多关于vue+canvas实现数据实时从上到下刷新瀑布图效果(类似QT的)的详细内容...

  阅读:41次