uniapp + renderjs + heatmap.js 实现热力图

uniapp + renderjs + heatmap.js 实现热力图

app项目中需要热力图展示,第一次用uniapp的renderjs操作dom,遇到了一些坑,包括引入组件,请求传参啥的

项目安装heatmap.js热力图插件,插件支持pc app

heatmap api文档
https://www.patrick-wied.at/static/heatmapjs/docs.html#h337-register

heatmap.js官网
https://www.patrick-wied.at/static/heatmapjs/

首先项目安装插件
npm i heatmap

这个插件需要获取到原生的dom元素,然后uniapp提供的方法只能获取元素数据,不支持操作dom,但是提供了另一种方式renderjs

renderjs使用
在需要热力图组件的页面新增一个script为renderjs模式
在新增的script中引入 heatmap
module相当于是这个模块的名字

<script module="map" lang="renderjs">
	import Heatmap from "heatmap.js";
	export default {
		data() {
			return {
				heapMapIns: null,
			}
		},

		methods: {
			//创建热力图
			initHotImg(newV) {
              this.deleteHotMap();
				let config = {
					container: document.getElementById("hotMap"),
					radius: 35,
					maxOpacity: 0.5,
					minOpacity: 0,
					blur: 0.85,
					value: "value",
					gradient: {
						"0": "rgb(0,0,255)", //value为0的颜色
						"0.2": "rgb(0,255,255)", //value为50的颜色
						"0.4": "rgb(0,255,0)", //value为200的颜色
						"0.6": "yellow", //value为500的颜色
						"1": "rgb(255,0,0)" //value为1000的颜色
					}
				};
				// create heatmap with configuration
				this.heapMapIns = Heatmap.create(config);

				let dataList = {
					max: 200,
					min: 0,
					data: newV
				};

				this.heapMapIns.setData(dataList);
			},
			// 删除之前的热力图,每次重载热力图时canvas都会新增一个,所以要删除前一个canvas
			deleteHotMap() {
				var heatmapBox = document.querySelector("#hotMap");

				if (heatmapBox.children.length > 1) {
					var oldCanvas = heatmapBox.children[1];
					heatmapBox.removeChild(oldCanvas);
				}
			},
		}
	}
</script>

renderjs中不支持uni.request,意思就是renderjs中不能发送请求,所以请求后台拿数据的操作得到原有的script中进行,然后监听参数变化,将参数传递过来进行渲染

<script>
	export default {
		data() {
			return {
				pointsArr : [],//
				h:'',
			}
		},

		methods: {
					//获取热力图数据
			gethotData() {

				//这里的请求是获取热力图数据通过临时变量接收,然后赋值给被监听的需要传给renderjs的热力图数据
				Api.floorAreas(this.clientId).then(res => {
					if (res.data.code == 200) {
						this.areaId = res.data.data[0].listArea[0].areaId;
						this.mapParams.areaId = this.areaId;
						Api.clientHeatMapArea(this.mapParams).then(resd => {
							if (resd.data.code == 200) {
								this.imgSrc = resd.data.data.areaMapUrl;
								this.url = "url(" + 'http://pic.ccc.com' + resd.data.data.areaMapUrl +
									") 0% 0% /100% 100% no-repeat";
								let bi = resd.data.data.areaHeight / resd.data.data.areaWidth;
								bi = bi.toFixed(0);
								this.h = this.screenWidth * bi;
								let dataList = resd.data.data.listAreaMap;
								let mapData = [];
								if (dataList.length !== 0) {
									dataList.forEach(item => {
										mapData.push({
											x: item.x / 3,
											y: item.y / 5,
											value: item.times
										});

									})
									this.pointsArr = mapData;
								}

							}
						})
					}
				})
			}
			
	},
	mounted(){
		this.gethotData();
}
	}
</script>

h5代码


				<view id="hotMap" :style="'width'+':' +screenWidth * 2 + 'upx'+';' + 'height'+':' +h + 'upx' +';' +
				'background:'+url + ';'"  :prop="pointsArr" :change:prop="map.initHotImg">

				</view>

这里监听pointsArr数据变化,只要pointsArr数据改变,就会触发map.initHotImg方法,然后传递参数过去,我这里的高宽和背景图是动态获取的,可以忽略

热力图效果
在这里插入图片描述

坑:
1、官方说renderjs中可以操作dom,我实践过来,发现renderjs仅支持获取原生的dom元素
,想通过原生的el.style.height的方式去修改元素的宽高,没有成功,最后是采用的绑定style的方式实现的宽高控制
2、传参方式:我在百度里搜寻了很多从script向renderjs传参的方式,都行不通,最后采用的这个通过监听实现的传参可行
3、开发时一定要用usb连接实机进行调试,pc浏览器模拟的手机窗口和实机展示的会有差别。

**

简单dome示例完整代码

**

<template>
	<view>
		<view class="detial" style="display: flex;flex-direction: column;">

			<view name='热力分析' style="flex: 1; display: flex;flex-direction: column;">
				<!-- 死宽度无背景图 -->

				<view id="hotMap" :prop="pointsArr" :change:prop="renderMap.initHotImg"
					style="margin: 5px auto;width: 400upx;height: 400upx;border: 1px solid #ccc;"
					@click="renderMap.initHotImg">

				</view>
				<!-- 后台数据设定宽度和背景图 -->
				<!-- 	<view id="hotMap" :style="'width'+':' +screenWidth  + 'px'+';' + 'height'+':' +h + 'px' +';' +
			'background:'+url + ';'"  :prop="pointsArr" :change:prop="map.initHotImg" style="margin: 5px auto;">
			
			</view> -->
			</view>

		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				pointsArr: [],
			}
		},
		methods: {

			//模拟后端请求,获取热力图数据
			getHotData() {
				setTimeout(()=>{
					this.pointsArr = [{
						x: 0,
						y: 0,
						value: 100
					}]
				},500)
			},

		},
		created() {},
		mounted() {
         this.getHotData();
		},

	}
</script>
<script module="renderMap" lang="renderjs">
	import Heatmap from "heatmap.js";
	export default {
		data() {
			return {
				heapMapIns: null,
			}
		},
		methods: {
			initHotImg(newV) {
				let config = {
					container: document.getElementById("hotMap"),
					radius: 35,
					maxOpacity: 0.5,
					minOpacity: 0,
					blur: 0.85,
					value: "value",
					gradient: {
						"0": "rgb(0,0,255)", //value为0的颜色
						"0.2": "rgb(0,255,255)", //value为50的颜色
						"0.4": "rgb(0,255,0)", //value为200的颜色
						"0.6": "yellow", //value为500的颜色
						"1": "rgb(255,0,0)" //value为1000的颜色
					}
				};
				// create heatmap with configuration
				this.heapMapIns = Heatmap.create(config);

				let dataList = {
					max: 50,
					min: 0,
					data: newV
				};

				this.heapMapIns.setData(dataList);
			},
			// 删除之前的热力图,pc端使用,因为插件会在浏览器未清楚缓存,然后开发者通过再次触发请求的方式拿到数据重新渲染热力图,
			//就会一直创建canvas画布,所以页面上会出现好几个热力图板块,所以在每次渲染热力图,都需要把上一个删除
			deleteHotMap() {
				var heatmapBox = document.querySelector("#hotMap");
				if (heatmapBox.children.length > 1) {
					var oldCanvas = heatmapBox.children[1];
					heatmapBox.removeChild(oldCanvas);
				}
			},
		},


	}
</script>
<style scoped lang="scss">
	.detial {
		position: fixed;
		width: 100%;
		height: 100%;
		background: #2c367b;
		background-size: 100% 100%;
		display: flex;
		flex-direction: column;

	}
</style>

demo效果
在这里插入图片描述

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值