当前位置: 首页 > 工具软件 > mk.js > 使用案例 >

HQChart--uniApp v3 中使用 render.js

罗建弼
2023-12-01

前言

由于uniApp 官方升级了v3编译器,升级后不知道为什么会导致官方提供的画图工具变得特别慢~也就是卡,导致之前写的 HQChart用的页面打开特别卡,所以可以使用render.js能大幅度提升流畅度。
使用前要看看这个:renderjs是一个运行在视图层的js。它比WXS更加强大。它只支持app-vue和h5。

uniapp插件市场hqchart地址
要用到里面的 umychart.uniapp.h5.js 文件
将其放在 根目录/static/umychart_uniapp_h5/umychart.uniapp.h5.js
具体代码我封装层一个组件了,当然这仅仅是给大家一个参考方案,毕竟你们的项目需求和我的肯定不一样的。kLine-main.vue 如下

代码

<template>
	<view class="kLine-main" style="height: 1200rpx;width: 750rpx;">
		<view class="kline" id="HQChart" ref="kline" style="height: 1200rpx;width: 750rpx;" :prop="deployData" :change:prop="HQChart.updateChart"></view>
	</view>
</template>

<script>
import { mapActions, mapMutations, mapState } from 'vuex';
export default {
	name: 'kLine-main', //k线 图表
	components: {},
	props: {
		klineData: {
			Type: Array,
			default: function() {
				return [];
			}
		},
		kLineDataDailyCache:{
			Type: Array,
			default: function() {
				return [];
			}
		},
		tradePairInfo: {
			Type: Object,
			default: function() {
				return {};
			}
		},
		
		menuPeriod: Number
	},
	data() {
		return {
			//官方没有给直接调用视图层的方法所以这个通过改变状态来触发视图层的方法,不知道后期官方是否可以给个更好解决方案
			deployData: {
				hqchartData: { // 分线的历史数据
					name: '',
					symbol: 'BTCUSDT.BIT',
					count: '',
					start: -1,
					end: 0,
					data: [] //date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7;
				},
				kLineDataDailyCache:{ //日线的历史数据
					name: '',
					symbol: 'BTCUSDT.BIT',
					count: '',
					start: -1,
					end: 0,
					data: [] //date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7;
				},
				period: 4,
				Windows: [],
				FloatPrecision: 4, //币种的小数位数
				isHqchartData: false, //是否有新的数据
				isDestroy: false, // 组件是否要销毁了,通知视图层销毁
				switchWindows: false, //指标是否改动了的通知开关
				isRefresh: false //是否改变了币种
			}
		};
	},
	computed: {
		...mapState('kline', ['kLineWindows', 'isChangeTemplate'])
	},
	created() {
		//console.log(this.klineData);
		this.deployData.period = this.menuPeriod;
		this.deployData.Windows = this.kLineWindows;
		this.deployData.hqchartData.data = this.klineData;
		this.deployData.hqchartData.name = this.tradePairInfo.tradePairsName;
		this.deployData.hqchartData.count = this.klineData.length;
		this.deployData.hqchartData.symbol = this.tradePairInfo.tradePairsName + '.BIT';
		this.deployData.FloatPrecision = this.tradePairInfo.tradeDecimal > 2 ? this.tradePairInfo.tradeDecimal : 2; //小数位
		this.deployData.kLineDataDailyCache = {
			name: this.tradePairInfo.tradePairsName,
			symbol: this.tradePairInfo.tradePairsName + '.BIT',
			count: this.kLineDataDailyCache.length,
			start: -1,
			end: 0,
			data:this.kLineDataDailyCache
		}
	},
	mounted() {},
	watch: {
		klineData(val) {
			this.deployData.hqchartData.data = this.klineData;
			this.deployData.hqchartData.count = this.klineData.length;
			this.deployData.isHqchartData = true;
			setTimeout(() => {
				this.deployData.isHqchartData = false;
			}, 2000);
		},
		tradePairsName(val) {
			this.hqchartData.name = val;
			//this.hqchartData.symbol = val;
		},
		/* 指标模版改变了 */
		isChangeTemplate(val) {
			console.log('指标模版改变了');
			this.deployData.Windows = this.kLineWindows; //变动了指标
			this.deployData.switchWindows = true; // 通知视图开关
			setTimeout(() => {
				this.deployData.switchWindows = false;
			}, 1000);
		}
	},
	beforeDestroy() {
		this.deployData.isDestroy = true; //组件是否要销毁了
	},
	methods: {
		...mapState('system', ['theme']),
		changePeriod(period) {
			this.deployData.period = period;
		},
		destroyView() {
			this.deployData.isDestroy = true; //组件是否要销毁了
		},
		refresh() {
			this.deployData.isRefresh = true; //变动了指标
			setTimeout(() => {
				this.deployData.isRefresh = false;
			}, 1000);
		}
	}
};
</script>
<script module="HQChart" lang="renderjs" type="module">
import HQChart from 'static/umychart_uniapp_h5/umychart.uniapp.h5.js'; //这个可以转化es5并压缩js 大概可以达到0.95MK 左右
var g_KLine = {
	JSChart: null
};
function DefaultData() {}

DefaultData.GetKLineOption = function() {
	let data = {
		Type: '历史K线图',

		//窗口指标
		Windows: [{ Index: 'MA', Modify: false, Change: false }, { Index: 'VOL', Modify: false, Change: false }, { Index: 'MACD', Modify: false, Change: false }],

		IsAutoUpdate: false, //是自动更新数据 ,好像用不了,
		AutoUpdateFrequency: 1000, //数据更新频率
		IsCorssOnlyDrawKLine: true, //十字光标只能在K线上
		IsClickShowCorssCursor: true, //手势点击出现十字光标
		EnableScrollUpDown: true, //允许手势上下操作滚动页面
		CorssCursorTouchEnd: false, //手势结束十字光标自动隐藏
		IsShowCorssCursorInfo: true, //是否显示十字光标的刻度信息
		CorssCursorInfo: {
			Left: 2,
			Right: 2,
			Bottom: 1,
			IsShowCorss: true,
			VPenType: 2,
			HPenType: 1
		}, //十字光标刻度设置
		Border: {
			//边框
			Left: 1,
			Right: 1, //右边间距
			Top: 25,
			Bottom: 25
		},

		KLine: {
			Right: 1, //复权 0 不复权 1 前复权 2 后复权
			Period: 4, //周期: 0 日线 1 周线 2 月线 3 年线
			PageSize: 60,
			IsShowTooltip: false,
			DrawType: 0 //K线类型 0=实心K线柱子 1=收盘价线 2=美国线 3=空心K线柱子 4=收盘价面积图
		},
		//子框架设置 (Height 窗口高度比例值)
		Frame: [
			{
				SplitCount: 3, //最多输出3个分隔线
				Height: 5,
				IsShowLeftText: false, //不显示左边刻度文字
				IsShowRightText: true, //显示右边刻度文字
				Custom: [
					{
						Type: 0,
						Position: 'right'
					}
				]
			},
			{
				SplitCount: 2,
				Height: 2,
				IsShowLeftText: true,
				IsShowRightText: false
			},
			{
				SplitCount: 2,
				Height: 2,
				IsShowLeftText: true,
				IsShowRightText: false
			}
		],
		ExtendChart: [
			{ Name: 'KLineTooltip' } //开启手机端tooltip
		]
	};

	return data;
};
var KLine = {
	JSChart: null,
	Option: DefaultData.GetKLineOption(),
	IsShow: true
};
var loadingChart = false;

export default {
	mounted() {
		console.log('视图层加载完毕');
		if (typeof window.HQChart === 'function') {
			this.CreateKLineChart();
		} else {
			// 动态引入较大类库避免影响页面展示 --动态加载好像没什么卵用,废弃不用了
			// const script = document.createElement('script');
			// console.log('创建K线图');
			// // view 层的页面运行在 www 根目录,其相对路径相对于 www 计算
			// script.src = 'static/umychart_uniapp_h5/umychart.uniapp.h5.js';
			// script.onload = this.CreateKLineChart.bind(this);
			// document.head.appendChild(script);

			this.CreateKLineChart();
		}
	},
	methods: {
		CreateKLineChart() {
			//创建K线图
			if (KLine.JSChart) {
				KLine.JSChart.OnSize();
			}
			if (KLine.JSChart) return;

			KLine.Option.Symbol = this.deployData.hqchartData.symbol;
			console.log('[this.deployData.Windows]', this.deployData.Windows);
			if (this.deployData.Windows && this.deployData.Windows.length) {
				KLine.Option.Windows = this.deployData.Windows; //用全局的
			}
			KLine.Option.KLine.Period = this.deployData.period; //周期

			KLine.Option.NetworkFilter = this.NetworkFilter;

			HQChart.MARKET_SUFFIX_NAME.GetBITDecimal = symbol => {
				return this.deployData.FloatPrecision;
			}; // 不同品种虚拟币,使用不同小数位数

			var blackStyle = HQChart.HQChartStyle.GetStyleConfig(1); //读取黑色风格配置
			HQChart.JSChart.SetStyle(blackStyle);

			g_KLine.JSChart = HQChart.JSChart.Init(document.getElementById('HQChart'));

			g_KLine.JSChart.SetOption(KLine.Option);

			KLine.JSChart = g_KLine.JSChart;
			console.log('创建K线图结束');
		},
		//网络协议回调
		NetworkFilter: function(data, callback) {
			console.log('[HQChart:NetworkFilter] data', data);
			data.PreventDefault = true; //设置hqchart不请求数据
			//console.log('[数据] data', this.deployData.hqchartData);
			
			switch (data.Name) {
				case 'KLineChartContainer::ReqeustHistoryMinuteData': // 1分钟全量数据下载
					console.log('[1分钟全量数据下载]');
					callback(this.deployData.hqchartData); //把数据传回hqchart
					break;
				case 'KLineChartContainer::RequestDragMinuteData': // 拖拽1分钟K线数据下载
					console.log('[拖拽1分钟K线数据下载]');
					break;	
				case 'KLineChartContainer::RequestMinuteRealtimeData': //1分钟增量数据更新
					//this.RequestMinuteRealtimeData(data, callback);
					break;
				case 'KLineChartContainer::RequestHistoryData': //日线全量数据下载
					console.log('[日线全量数据下载]',this.deployData.kLineDataDailyCache);
					if(this.deployData.kLineDataDailyCache.length){
						callback(this.deployData.kLineDataDailyCache); //把数据传回hqchart
					}else{
						callback(this.deployData.hqchartData); //把数据传回hqchart
					}
					break;
				case 'KLineChartContainer::RequestRealtimeData': //日线增量数据更新
					//this.RequestRealtimeData(data, callback);
					break;
				default:
					console.log('[1分钟全量数据下载]');
					callback(this.deployData.hqchartData); //把数据传回hqchart
					break;
			}
		},
		//K线周期切换
		ChangeKLinePeriod: function(period) {
			console.log('K线周期切换', period);
			if (!KLine.JSChart) {
				//不存在创建
				KLine.Option.Period = period;
				this.CreateKLineChart();
			} else {
				KLine.Option.Period = period;
				g_KLine.JSChart.ChangePeriod(period);
			}
		},
		//动态切换指标模板
		ChangeKLineTemplate: function(Windows) {
			let option = {
				Windows: Windows
			};
			if (g_KLine.JSChart) {
				g_KLine.JSChart.ChangeIndexTemplate(option);
			} else {
				this.CreateKLineChart();
			}
		},
		/* 数据更新了 */
		updateChart(val) {
			if (loadingChart) {
				return;
			} else {
				loadingChart = true;
			}
			console.log(val.switchWindows);
			if (KLine.Option.Period != val.period) {
				this.ChangeKLinePeriod(val.period); //改变周期
			} else if (val.isDestroy) {
				//清空实例
				console.log('准备清空实例');
				g_KLine.JSChart = null;
				KLine.JSChart = null;
			} else if (val.switchWindows && val.Windows.length) {
				console.log('开始更新指标');
				this.ChangeKLineTemplate(val.Windows);
			} else if (val.isRefresh) {
				this.CreateKLineChart();
			} else if (val.isHqchartData) {
				var hqChartData = {
					code: 0,
					data: val.hqchartData.data,
					ver: 2.0,
					symbol: val.hqchartData.symbol,
					name: val.hqchartData.name
				};
				console.log('[有更新数据] data', val.hqchartData.data[val.hqchartData.data.length - 1]);
				if (KLine.JSChart) {
					KLine.JSChart.JSChartContainer.RecvMinuteRealtimeData(hqChartData); //接受到socket的数据改变,开始重新画
				}
			}
			loadingChart = false;
		}
	}
};
</script>
<style lang="scss">
.kline {
}
</style>

使用

<view class="kline-box" style="height: 1200rpx;width: 750rpx;">
	<kLineMain :klineData="klineDataCache" :tradePairInfo="tradePairInfo" :kLineDataDailyCache="kLineDataDailyCache" ref="refKLineMain"></kLineMain>
</view>
import kLineMain from './components/kLine-main.vue'
export default {
	components: {
			kLineMain
		},
}

我这边收到的数据是和火币一样的,要进行 数据的格式化:

/** @description 将获取到数据 格式化 */
			initData(val) {
				let resDate = [];
				let data = [];
				let time = new Date();
				
				for (let i in val) {
					resDate[0] = this.getTime(val[i].time, 'day');
					resDate[1] = val[i - 1] ? val[i - 1].close : "";
					resDate[2] = val[i].open;
					resDate[3] = val[i].height;
					resDate[4] = val[i].low;
					resDate[5] = val[i].close;
					resDate[6] = val[i].num;
					resDate[7] = '';
					resDate[8] = this.getTime(val[i].time, 'minute');
					data.push(resDate);
					resDate = [];
				}
				let time1 = new Date();
				console.info('【处理数据耗时】', time1 - time);
				console.info('【处理数据长度】', data.length);
				//console.log("初始数据", this.hqchartData);
				return data;
			},
属性说明
klineData分线数据
tradePairInfo交易的详细信息
kLineDataDailyCache日线数据
this.$refs.refKLineMain.changePeriod(period);这个可以直接调用组件里的方法用来改变周期

比较坑的是无法使用v-if 来刷新组件,第二次显示组件图表就是一片空白,所以没法子,切换交易对我直接重新打开这个页面:

/* 选择了新的交易对 */
changeTradePair(val) {
	console.log(val);
	//重新加载这个页面 //带的item是交易对详细信息
	uni.redirectTo({
		url:'/pages/contract/kLine?item='+encodeURIComponent(JSON.stringify(val))
	})
},

至于动态改变指标我是在vuex里写好的配置 store/modules/kline.js:


const state = {
	kLineWindows:[
		{
			Index: "MA",
			Args: [{ Name: 'M1', Value: 5 }, { Name: 'M2', Value: 10 }, { Name: 'M3', Value: 20 }],
			Modify: false,
			Change: false
		}, {
			Index: "VOL",
			Modify: false,
			Change: false
		}, {
			Index: "MACD",
			Modify: false,
			Change: false
		}
	],
	templateMainWindow:[
		{Index:"MA", Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10 },{ Name:'M3', Value:20 }]},
		{Index:"BOLL",Args:[ { Name:'M', Value:20}]}
	],
	templateSecondaryWindow:[
		{Index:"MACD",Args:[ { Name:'SHORT', Value:12}, { Name:'LONG', Value:26 },{ Name:'MID', Value:9 }]},
		{Index:"KDJ",Args:[ { Name:'N', Value:9}, { Name:'M1', Value:3 },{ Name:'M2', Value:3 }]},
		{Index:"RSI",Args:[ { Name:'N1', Value:6}, { Name:'N2', Value:12 },{ Name:'N3', Value:24 }]},
		{Index:"WR",Args:[ { Name:'N', Value:10}, { Name:'N1', Value:6 }]},
	],
	isChangeTemplate:0, //是否改变了指标模版
}
const mutations = {
}

const actions = {
	setMainWindow({state,dispatch},val){
		state.templateMainWindow = val;
		let option = {
			index:0,
			item:state.templateMainWindow.find((res)=>{
				return res.Index == state.kLineWindows[0].Index;
			})
		}
		dispatch('setKLineWindows',option);
	},
	setSecondaryWindow({state,dispatch},val){
		state.templateSecondaryWindow = val;
		let option = {
			index:2,
			item:state.templateSecondaryWindow.find((res)=>{
				return res.Index == state.kLineWindows[2].Index;
			})
		}
		dispatch('setKLineWindows',option);
	},
	//修改图表中显示的指标
	setKLineWindows({state},val){
		console.log('切换指标',val);
		state.kLineWindows[val.index] = val.item;
		console.log('切换指标完成',state.kLineWindows);
		++state.isChangeTemplate;//通知刷新指标
	}
}

export default {
	namespaced: true,
	state,
	mutations,
	actions
}

大概就这这样,因为是公司代码具体逻辑不大方便直接贴出,所以就这吧!有问题可以留言!

 类似资料: