heatmap.js热力图【vue3】
1.代码
<template>
<div>
<div>实时热力图</div>
<div id="heatmap" ref="heatmapContainer" class="demo-wrapper">
<div class="tooltip"></div>
<div class="legend-area">
<h4>图例</h4>
<span id="min">-40℃</span>
<span id="max">40℃</span>
<img id="gradient" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAKCAYAAABCHPt+AAAAAXNSR0IArs4c6QAAAO1JREFUWEftl1ELgzAMhE9MwP7//+n2tApTHHGLqChtpUZhChJCpT4c311SAH2Pox96A1UDuAaoPOD8wf33P8QtKgAOMK3sATz2vYWJINz+hFBBbCrTOYJQA6AG8EyvNoIIISMdOcUQ6oQ2oU7unfdEbZAOJSgnRXQTsi7yaYRcXpCBEM0Nu0rUBQnJSYbSNhByacv6twy5PCEsU5b6vF1l6kynK6WNXpETlob+ZCKzCXUhZMuyVCg9D/XLe5bfT865TA/1Zcjv6WehrtYVOQYbCXITEruX2AkSJGRjaRwJSF8qzyBEbKuMtawVaj499OBUDrGT6AAAAABJRU5ErkJggg==" style="width:100%">
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import h337 from 'heatmap.js';
// 创建用于保存 heatmap 实例的引用
const heatmapInstance = ref(null);
const heatmapContainer = ref(null);
onMounted(() => {
// 确保容器已经被挂载到 DOM
if (heatmapContainer.value) {
heatmapInstance.value = h337.create({
container: heatmapContainer.value,
backgroundColor: 'rgba(255,255,255,0)',
gradient: {
'0': 'blue',
'0.2': 'blue',
'0.4': 'green',
'0.6': 'green',
'0.8': 'yellow',
'1': 'red'
},
radius: 5, // 设置光圈的半径大小,值>=0,=0取得是默认值
opacity: 0.7, // 光圈透明度设置[0,1],如果值设置了,会重写maxOpacity和minOpacity的值
maxOpacity: .5, minOpacity: 0,
// blur: .9,
onExtremaChange: function(data) {
updateLegend(data);
}
});
var points=[]
for (let index = 0; index < 40; index++) {
var point=generateData(90,12.4,59,155,80+ index*5.2,5)
points=[...points,...point]
}
for (let index = 0; index < 40; index++) {
var point=generateData(190,12.5,59,105,510 + index*5,7)
points=[...points,...point]
}
/* tooltip code start */
var demoWrapper = document.querySelector('.demo-wrapper');
var tooltip = document.querySelector('.tooltip');
function updateTooltip(x, y, value) {
// + 15 for distance to cursor
var transl = 'translate(' + (x + 15) + 'px, ' + (y + 15) + 'px)';
tooltip.style.webkitTransform = transl;
var temValue=value-40
tooltip.innerHTML = temValue+'℃';
};
demoWrapper.onmousemove = function(ev) {
var x = ev.layerX +15;
var y = ev.layerY +15;
// getValueAt gives us the value for a point p(x/y)
var value = heatmapInstance.value.getValueAt({
x: x,
y: y
});
// console.log({value});
tooltip.style.display = 'block';
updateTooltip(x, y, value);
};
// hide tooltip on mouseout
demoWrapper.onmouseout = function() {
tooltip.style.display = 'none';
};
/* tooltip code end */
/* start legend code */
var legendCanvas = document.createElement('canvas');
legendCanvas.width = 100;
legendCanvas.height = 10;
var min = document.querySelector('#min');
var max = document.querySelector('#max');
var gradientImg = document.querySelector('#gradient');
var legendCtx = legendCanvas.getContext('2d');
var gradientCfg = {};
function updateLegend(data) {
min.innerHTML = data.min + '℃';
max.innerHTML = data.max+ '℃';
// // regenerate gradient image
if (data.gradient != gradientCfg) {
gradientCfg = data.gradient;
var gradient = legendCtx.createLinearGradient(0, 0, 100, 1);
for (var key in gradientCfg) {
gradient.addColorStop(key, gradientCfg[key]);
}
legendCtx.fillStyle = gradient;
legendCtx.fillRect(0, 0, 100, 10);
gradientImg.src = legendCanvas.toDataURL();
}
};
/* legend code end */
setInterval(()=>{
// 为每个对象生成一个新的随机value值
points.forEach((item,index) => {
// item.value = Math.floor(Math.random() * 50);
if(index>=400 && index<=411){
item.value = generateRandomValue(-40, 40);
}
if(index>=500 && index<=501){
item.value = generateRandomValue(-40, 40);
}
if(index>=600 && index<=601){
item.value = generateRandomValue(-40, 40);
}
if(index>=700 && index<=709){
item.value = generateRandomValue(-40, 40);
}
if(index>=1000 && index<=1001){
item.value = generateRandomValue(-40, 40);
}
if(index>=1200 && index<=1201){
item.value = generateRandomValue(-40, 40);
}
if(index>=1600 && index<=1609){
item.value = generateRandomValue(-40, 40);
}
if(index>=2000 && index<=2009){
item.value = generateRandomValue(-40, 40);
}
if(index>=2200 && index<=2201){
item.value = generateRandomValue(-40, 40);
}
if(index>=2400 && index<=2411){
item.value = generateRandomValue(-40, 40);
}
if(index>=2500 && index<=2501){
item.value = generateRandomValue(-40, 40);
}
if(index>=2600 && index<=2601){
item.value = generateRandomValue(-40, 40);
}
if(index>=2700 && index<=2709){
item.value = generateRandomValue(-40, 40);
}
if(index>=31000 && index<=3001){
item.value = generateRandomValue(-40, 40);
}
if(index>=3200 && index<=3201){
item.value = generateRandomValue(-40, 40);
}
if(index>=3600 && index<=3609){
item.value = generateRandomValue(-40, 40);
}
if(index>=4000 && index<=4009){
item.value = generateRandomValue(-40, 40);
}
if(index>=4200 && index<=4201){
item.value = generateRandomValue(-40, 40);
}
// console.log(generateRandomValue(-40, 40));
});
var max = points.reduce((max, item) => item.value > max ? item.value : max, points[0].value);
var min = points.reduce((min, item) => item.value < min ? item.value : min, points[0].value);
// console.log(points);
var data = {
max: max,
min:min,
data: points
}
// console.log(data);
heatmapInstance.value.setData(data); //数据绑定还可以使用
},1000)
}
});
function generateData(width, height, len, pos1, pos2,r) {
const points = [];
while (len--) {
const val = generateRandomValue(-40, 40);
const point = {
x: Math.floor(Math.random() * width) + pos1,
y: Math.floor(Math.random() * height) + pos2,
value: val,
radius:r
};
points.push(point);
}
return points;
}
function generateRandomValue(min, max) {
// 生成 min 到 max 之间的随机整数
return Math.floor(Math.random() * (max - min + 1) + min);
}
</script>
<style scoped>
#heatmap {
width: 400px;
height: calc(100vh - 71px);
/* width: 100%; */
/* height: 100%; */
/* border: 1px solid; */
border-color: grey;
background-image: url("../../../assets/images/罐子.png");
background-size: contain; /* 背景图将会完全显示在区域内,保持宽高比例 */
background-repeat: no-repeat; /* 禁止背景图重复 */
background-position: center; /* 将背景图居中显示 */
}
.tooltip{
background: rgba(0,0,0,.8);
padding: 5px;
line-height: 18px;
color: white;
width: fit-content;
position: absolute;
display: none;
}
.legend-area {
position: absolute;
bottom: 10px;
right: -140px;
padding: 10px;
background: white;
outline: 2px solid rgb(0, 0, 0);
line-height: 1em;
}
#min {
float: left;
}
#max {
float: right;
}
span{
margin: 0;
padding: 0;
}
h4 {
margin: 0;
padding: 0;
margin-bottom: 5px;
}
</style>
2.安装heatmap.js
npm install heatmap.js
3.使用
import h337 from 'heatmap.js';
4.问题
Cannot assign to read only property 'data' of object #219
5.解决方法
删除源码node_modules中的heatmap.js中的527
执行yarn dev --force