技术标签: 量化 股票 uniapp K线图 uni-app HQChart
由于小程序/app很多局限性(无法创建DOM,canvas异步绘图等)导致HQChart开发的时候分成两个版本(小程序版本和H5页面版本)。
使用条件编译我们可以把这2个版本组件同时包含的工程中,并且通过平台判断动态加载对应版本的js.
插件地址: https://ext.dcloud.net.cn/plugin?id=4591
直接通过HBuilder X就可以安装,一般安装的目录在uni_modules\jones-hqchart2下面
改下import路径就可以,其他不变
// #ifdef H5
import HQChart from '@/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.h5.js'
//HQChart.JSChart.SetDomain("xxxxx.com");
//HQChart.JSComplier.SetDomain("xxxx.com");
// #endif
// #ifndef H5
import {
JSCommon} from '@/uni_modules/jones-hqchart2/js_sdk/umychart.wechat.3.0.js'
import {
JSCommonHQStyle} from '@/uni_modules/jones-hqchart2/js_sdk/umychart.style.wechat.js'
import {
JSCommonComplier} from "@/uni_modules/jones-hqchart2/js_sdk/umychart.complier.wechat.js"
//禁用日志
JSConsole.Complier.Log=()=>{
};
JSConsole.Chart.Log=()=>{
};
// #endif
在工程里建2个目录,把HQChart的2个版本分别考入对应的目录里。
版本对应关系看以前的教程
HQChart使用教程35 - 如何在uni-app创建K线图(h5)
HQChart使用教程37 - 如何在uni-app创建k线图(app)
由于小程序/app是无法动态创建dom,所有只能是先在模板里写死一个画布,在初始化的时候绑定到HQChart中。H5是可以直接内部创建dom,所以只需要传入一个div,HQChart自动会创建画布. 我们使用条件编译在不同的平台使用不同的模板
注意 id的名字尽量使用不一样的,如h5如果使用id=‘kline’ 在app/小程序就使用id=‘kline2’
<!-- #ifdef H5 -->
<div>
<div class='kline' id="kline" ref='kline' v-show="KLine.IsShow"></div>
<div class='minute' id="minute" ref='minute' v-show="Minute.IsShow"></div>
</div>
<!-- #endif -->
<!-- #ifndef H5 -->
<view>
<canvas id="kline2" canvas-id='kline2' class='kline2' v-bind:style="{width: ChartWidth+'px', height: ChartHeight+'px'}" v-show="KLine.IsShow"
@touchstart="KLineTouchStart" @touchmove='KLineTouchMove' @touchend='KLineTouchEnd' ></canvas>
<canvas id="minute2" canvas-id='minute2' class='minute' v-bind:style="{width: ChartWidth+'px', height: ChartHeight+'px'}" v-show="Minute.IsShow"
@touchstart="MinuteTouchStart" @touchmove='MinuteTouchMove' @touchend='MinuteTouchEnd' ></canvas>
</view>
<!-- #endif -->
这样2个模板就同时存在一个页面中了
为每个平台创建一个创建插件的函数,然后通过一个总的创建函数动态调用对应的创建方法
下面是也创建K线图为例子‘CreateKLineChart_h5()'是h5平台的创建插件方法, 'CreateKLineChart_app()'是app和小程序创建的方法,在"CreateKLineChart()'通过条件编译就可以动态选择使用对应的创建函数
为了代码的可读和可维护性我这边是拆分成2个创建函数,你也可以在CreateKLineChart里面把2个平台的创建都写里面,只过不这样可读性比较差。
CreateKLineChart()
{
// #ifdef H5
this.CreateKLineChart_h5();
// #endif
// #ifndef H5
this.CreateKLineChart_app();
// #endif
},
下面是2个平台对应的创建方法,走势图的创建也是一样
CreateKLineChart_h5() //创建K线图
{
if (g_KLine.JSChart) return;
this.KLine.Option.Symbol=this.Symbol;
let chart=HQChart.JSChart.Init(this.$refs.kline);
this.KLine.Option.NetworkFilter=this.NetworkFilter;
chart.SetOption(this.KLine.Option);
g_KLine.JSChart=chart;
},
CreateKLineChart_app()
{
if (this.KLine.JSChart) return;
let element = new JSCommon.JSCanvasElement();
// #ifdef APP-PLUS
element.IsUniApp=true; //canvas需要指定下 是uniapp的app
// #endif
element.ID = 'kline2';
element.Height = this.ChartHeight; //高度宽度需要手动绑定!!
element.Width = this.ChartWidth;
g_KLine.JSChart = JSCommon.JSChart.Init(element);
this.KLine.Option.NetworkFilter=this.NetworkFilter;
this.KLine.Option.Symbol=this.Symbol;
g_KLine.JSChart.SetOption(this.KLine.Option);
},
由于app/小程序无法获取dom,所以只能是在外部把画布的长宽设置到HQChart中(动态获取只能通过其他的查询元素函数获取,比较麻烦,关键还是异步的,非常搞不懂获取一个元素信息还使用异步,难道以目前的手机配置查询几千几万了dom信息不能在毫秒级处理完),
H5是可以动态获取dom,就不存在这个文件,改变了外层的div调用HQChart的OnSize()方法就可以动态把div的大小绑定画布上。
OnSize()
{
// #ifdef H5
this.OnSize_h5();
// #endif
},
OnSize_h5()
{
var chartHeight = this.ChartHeight;
var chartWidth = this.ChartWidth;
var kline=this.$refs.kline;
kline.style.width=chartWidth+'px';
kline.style.height=chartHeight+'px';
if (g_KLine.JSChart) g_KLine.JSChart.OnSize();
var minute=this.$refs.minute;
minute.style.width=chartWidth+'px';
minute.style.height=chartHeight+'px';
if (g_Minute.JSChart) g_Minute.JSChart.OnSize();
},
这样多端支持就完成了。点运行,然后喝杯咖啡吧,编译调试真的很慢。
<template>
<div class='divchart' >
<!-- #ifdef H5 -->
<div>
<div class='kline' id="kline" ref='kline' v-show="KLine.IsShow"></div>
<div class='minute' id="minute" ref='minute' v-show="Minute.IsShow"></div>
</div>
<!-- #endif -->
<!-- #ifndef H5 -->
<view>
<canvas id="kline2" canvas-id='kline2' class='kline2' v-bind:style="{width: ChartWidth+'px', height: ChartHeight+'px'}" v-show="KLine.IsShow"
@touchstart="KLineTouchStart" @touchmove='KLineTouchMove' @touchend='KLineTouchEnd' ></canvas>
<canvas id="minute2" canvas-id='minute2' class='minute' v-bind:style="{width: ChartWidth+'px', height: ChartHeight+'px'}" v-show="Minute.IsShow"
@touchstart="MinuteTouchStart" @touchmove='MinuteTouchMove' @touchend='MinuteTouchEnd' ></canvas>
</view>
<!-- #endif -->
<div class="button-sp-area">
<button class="mini-btn" type="default" size="mini" @click="ChangeMinutePeriod(MINUTE_PERIOD_ID.MINUTE_ID)">分时</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeMinutePeriod(MINUTE_PERIOD_ID.MINUTE_5DAY_ID)">5日</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(KLINE_PERIOD_ID.KLINE_DAY_ID)">日线</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(KLINE_PERIOD_ID.KLINE_WEEK_ID)">周线</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(KLINE_PERIOD_ID.KLINE_MINUTE_ID)">1分钟</button>
<button class="mini-btn" type="default" size="mini" @click="ChangeKLinePeriod(KLINE_PERIOD_ID.KLINE_15MINUTE_ID)">15分钟</button>
</div>
</div>
</template>
<script>
// #ifdef H5
import HQChart from '../../umychart_uniapp_h5/umychart.uniapp.h5.js'
// #endif
// #ifndef H5
import {
JSCommon} from '../../umychart.uniapp/umychart.wechat.3.0.js'
// #endif
function DefaultData() {
}
DefaultData.GetKLineOption = function ()
{
let data =
{
Type: '历史K线图',
Windows: //窗口指标
[
{
Index:"MA",Modify: false, Change: false},
{
Index:"VOL",Modify: false, Change: false}
],
IsCorssOnlyDrawKLine:true,
CorssCursorTouchEnd:true,
Border: //边框
{
Left: 1,
Right: 1, //右边间距
Top: 25,
Bottom: 25,
},
KLine:
{
Right:1, //复权 0 不复权 1 前复权 2 后复权
Period:0, //周期: 0 日线 1 周线 2 月线 3 年线
PageSize:30,
IsShowTooltip:false
},
ExtendChart:
[
{
Name:'KLineTooltip' }, //开启手机端tooltip
],
Frame: //子框架设置
[
{
SplitCount:3},
{
SplitCount:2},
{
SplitCount:3},
],
};
return data;
}
DefaultData.GetMinuteOption=function()
{
var option=
{
Type:'分钟走势图', //创建图形类型
Windows: //窗口指标
[
],
IsAutoUpdate:true, //是自动更新数据
DayCount:1, //1 最新交易日数据 >1 多日走势图
IsShowRightMenu:false, //是否显示右键菜单
CorssCursorTouchEnd:true,
MinuteLine:
{
//IsDrawAreaPrice:false, //是否画价格面积图
},
Border: //边框
{
Left:1, //左边间距
Right:1, //右边间距
Top:20,
Bottom:20
},
Frame: //子框架设置
[
{
SplitCount:3},
{
SplitCount:2},
{
SplitCount:3},
],
ExtendChart: //扩展图形
[
{
Name:'MinuteTooltip' } //手机端tooltip
],
};
return option;
}
//周期枚举
var KLINE_PERIOD_ID=
{
KLINE_DAY_ID:0,
KLINE_WEEK_ID:1,
KLINE_MONTH_ID:2,
KLINE_YEAR_ID:3,
KLINE_MINUTE_ID:4,
KLINE_5MINUTE_ID:5,
KLINE_15MINUTE_ID:6,
KLINE_30MINUTE_ID:7,
KLINE_60MINUTE_ID:8
}
//周期枚举
var MINUTE_PERIOD_ID=
{
MINUTE_ID:1,
MINUTE_2DAY_ID:2,
MINUTE_3DAY_ID:3,
MINUTE_4DAY_ID:4,
MINUTE_5DAY_ID:5,
}
var g_KLine={
JSChart:null };
var g_Minute={
JSChart:null };
export default
{
data()
{
let data=
{
Symbol:'600000.sh',
ChartWidth:300,
ChartHeight:500,
KLine:
{
Option:DefaultData.GetKLineOption(),
IsShow:true,
},
Minute:
{
Option:DefaultData.GetMinuteOption(),
IsShow:false,
},
MINUTE_PERIOD_ID:MINUTE_PERIOD_ID,
KLINE_PERIOD_ID:KLINE_PERIOD_ID,
};
return data;
},
onLoad()
{
},
onReady()
{
this.OnSize();
this.CreateKLineChart();
},
methods:
{
OnSize()
{
// #ifdef H5
this.OnSize_h5();
// #endif
},
OnSize_h5()
{
var chartHeight = this.ChartHeight;
var chartWidth = this.ChartWidth;
var kline=this.$refs.kline;
kline.style.width=chartWidth+'px';
kline.style.height=chartHeight+'px';
if (g_KLine.JSChart) g_KLine.JSChart.OnSize();
var minute=this.$refs.minute;
minute.style.width=chartWidth+'px';
minute.style.height=chartHeight+'px';
if (g_Minute.JSChart) g_Minute.JSChart.OnSize();
},
CreateKLineChart_h5() //创建K线图
{
if (g_KLine.JSChart) return;
this.KLine.Option.Symbol=this.Symbol;
let chart=HQChart.JSChart.Init(this.$refs.kline);
this.KLine.Option.NetworkFilter=this.NetworkFilter;
chart.SetOption(this.KLine.Option);
g_KLine.JSChart=chart;
},
CreateKLineChart_app()
{
if (this.KLine.JSChart) return;
let element = new JSCommon.JSCanvasElement();
// #ifdef APP-PLUS
element.IsUniApp=true; //canvas需要指定下 是uniapp的app
// #endif
element.ID = 'kline2';
element.Height = this.ChartHeight; //高度宽度需要手动绑定!!
element.Width = this.ChartWidth;
g_KLine.JSChart = JSCommon.JSChart.Init(element);
this.KLine.Option.NetworkFilter=this.NetworkFilter;
this.KLine.Option.Symbol=this.Symbol;
g_KLine.JSChart.SetOption(this.KLine.Option);
},
CreateKLineChart()
{
// #ifdef H5
this.CreateKLineChart_h5();
// #endif
// #ifndef H5
this.CreateKLineChart_app();
// #endif
},
//K线周期切换
ChangeKLinePeriod:function(period)
{
this.Minute.IsShow=false;
this.KLine.IsShow=true;
if (!g_KLine.JSChart) //不存在创建
{
this.KLine.Option.Period=period;
this.CreateKLineChart_h5();
}
else
{
g_KLine.JSChart.ChangePeriod(period);
}
},
CreateMinuteChart_h5() //创建日线图
{
if (g_Minute.JSChart) return;
this.Minute.Option.Symbol=this.Symbol;
let chart=HQChart.JSChart.Init(this.$refs.minute);
this.Minute.Option.NetworkFilter=this.NetworkFilter;
chart.SetOption(this.Minute.Option);
g_Minute.JSChart=chart;
},
CreateMinuteChart_app()
{
if (g_Minute.JSChart) return;
var element = new JSCommon.JSCanvasElement();
// #ifdef APP-PLUS
element.IsUniApp=true; //canvas需要指定下 是uniapp的app
// #endif
element.ID = 'minute2';
element.Height = this.ChartHeight; //高度宽度需要手动绑定!!
element.Width = this.ChartWidth;
g_Minute.JSChart = JSCommon.JSChart.Init(element);
this.Minute.Option.NetworkFilter=this.NetworkFilter;
this.Minute.Option.Symbol=this.Symbol;
g_Minute.JSChart.SetOption(this.Minute.Option);
},
CreateMinuteChart()
{
// #ifdef H5
this.CreateMinuteChart_h5();
// #endif
// #ifndef H5
this.CreateMinuteChart_app();
// #endif
},
//走势图多日切换
ChangeMinutePeriod:function(period)
{
this.Minute.IsShow=true;
this.KLine.IsShow=false;
if (!g_Minute.JSChart) //不存在创建
{
this.Minute.Option.DayCount=period;
this.CreateMinuteChart();
}
else
{
g_Minute.JSChart.ChangeDayCount(period);
}
},
NetworkFilter:function(data, callback)
{
console.log(`[HQChart:NetworkFilter] Name=${
data.Name} Explain=${
data.Explain}` );
},
///
//手势事件 app/小程序才有
//KLine事件
KLineTouchStart: function (event)
{
if (g_KLine.JSChart) g_KLine.JSChart.OnTouchStart(event);
},
KLineTouchMove: function (event)
{
if (g_KLine.JSChart) g_KLine.JSChart.OnTouchMove(event);
},
KLineTouchEnd: function (event)
{
if (g_KLine.JSChart) g_KLine.JSChart.OnTouchEnd(event);
},
//走势图事件
MinuteTouchStart: function (event)
{
if (g_Minute.JSChart) g_Minute.JSChart.OnTouchStart(event);
},
MinuteTouchMove: function (event)
{
if (g_Minute.JSChart) g_Minute.JSChart.OnTouchMove(event);
},
MinuteTouchEnd: function (event)
{
if (g_Minute.JSChart) g_Minute.JSChart.OnTouchEnd(event);
},
}
}
</script>
<style>
</style>
如果还有问题可以加交流QQ群: 950092318
HQChart代码地址
地址:github.com/jones2000/HQChart
文章浏览阅读2w次,点赞51次,收藏33次。一、需求给定一个整数,返回大于等于该整数的最小2次幂(2的乘方)。例: 输入 输出 -1 1 1 1 3 4 9 16 15 16二、分析当遇到这个需求的时候,我们可能会很容易想到一个"笨"办法:..._整数 最小的2的几次方
文章浏览阅读865次。选项,以防止命令将 IP 地址解析为主机名。如果只想在命令的输出中显示 unix套接字 连接,可以使用。不带任何选项,用来显示已建立连接的所有套接字的列表。如果只想在命令的输出中显示 tcp 连接,可以使用。如果只想在命令的输出中显示 udp 连接,可以使用。如果不想将ip地址解析为主机名称,可以使用。如果要取消命令输出中的标题行,可以使用。如果只想显示被侦听的套接字,可以使用。如果只想显示ipv4侦听的,可以使用。如果只想显示ipv6侦听的,可以使用。_ss@,,x,, 0
文章浏览阅读568次。CommandNotFoundError: 'activate'_commandnotfounderror: 'activate
文章浏览阅读426次,点赞10次,收藏19次。完成以上步骤后,您已在 Windows 10 上成功安装并验证了 Apache Kafka。在生产环境中,通常会将 Kafka 与外部 ZooKeeper 集群配合使用,并考虑配置安全、监控、持久化存储等高级特性。在生产者窗口中输入一些文本消息,然后按 Enter 发送。ZooKeeper 会在新窗口中运行。在另一个命令提示符窗口中,同样切换到 Kafka 的。Kafka 服务器将在新窗口中运行。在新的命令提示符窗口中,切换到 Kafka 的。,应显示已安装的 Java 版本信息。_win10安装部署kafka
文章浏览阅读1.4w次。缓冲区对象(Buffer Object)是在OpenGL中用于存储和管理数据的一种机制。缓冲区对象可以存储各种类型的数据,例如顶点、纹理坐标、颜色等。在渲染过程中,缓冲区对象中存储的数据可以被复制到渲染管线的不同阶段中,例如顶点着色器、几何着色器和片段着色器等,以完成渲染操作。相比传统的CPU访问内存,缓冲区对象的数据存储和管理更加高效,能够提高OpenGL应用的性能表现。_js 缓冲数据 new float32array
文章浏览阅读912次。(1)图(Graph):图是数学和计算机科学中的一个抽象概念,它由一组节点(顶点)和连接这些节点的边组成。图可以是有向的(有方向的,边有箭头表示方向)或无向的(没有方向的,边没有箭头表示方向)。图用于表示各种关系,如社交网络、电路、地图、组织结构等。(2)网络(Network):网络是一个更广泛的概念,可以包括各种不同类型的连接元素,不仅仅是图中的节点和边。网络可以包括节点、边、连接线、路由器、服务器、通信协议等多种组成部分。网络的概念在各个领域都有应用,包括计算机网络、社交网络、电力网络、交通网络等。_图论与网络优化数学建模
文章浏览阅读1.5k次。我们经常会碰见 正在加载中,加载出错, “暂无商品”等一系列的相似的布局,因为我们有很多请求网络数据的页面,我们不可能每一个页面都写几个“正在加载中”等布局吧,这时候将这些状态的布局封装在一起就很有必要了。我们可以将这些封装为一个自定布局,然后每次操作该自定义类的方法就行了。 首先一般来说,从服务器拉去数据之前都是“正在加载”页面, 加载成功之后“正在加载”页面消失,展示数据;如果加载失败,就展示_adnroid加载数据转圈封装全屏转圈封装
文章浏览阅读1.6k次,点赞23次,收藏29次。PS: 如果执行sudo grep 'temporary password' /var/log/mysqld.log 后没有报错,也没有任何结果显示,说明默认密码为空,可以直接进行下一步(后面设置密码时直接填写新密码就行)。3.(可选)当操作系统为Alibaba Cloud Linux 3时,执行如下命令,安装MySQL所需的库文件。下面示例中,将创建新的MySQL账号,用于远程访问MySQL。2.依次运行以下命令,创建远程登录MySQL的账号,并允许远程主机使用该账号访问MySQL。_alibaba cloud linux 3
文章浏览阅读7.8k次。EXCEL中数据如何做离散性分析纠错。离散不是均值抄AVEDEV……=AVEDEV(A1:A100)算出来的是A1:A100的平均数。离散是指各项目间指标袭的离散均值(各数值的波动情况),数值较低表明项目间各指标波动幅百度小,数值高表明波动幅度较大。可以用excel中的离散公式为STDEV.P(即各指标平均离散)算出最终度离散度。excel表格函数求一组离散型数据,例如,几组C25的...用exc..._excel数据分析离散
文章浏览阅读406次,点赞7次,收藏8次。i < 5){ //第3行。int count;System.out.println ("危险!System.out.println(”真”);System.out.println(”假”);System.out.print(“姓名:”);System.out.println("无匹配");System.out.println ("安全");
文章浏览阅读3.6k次。背景测试到性能、压力时,经常需要查看磁盘、网络、内存、cpu的性能值这里简单介绍下各个指标的含义一般磁盘比较关注的就是磁盘的iops,读写速度以及%util(看磁盘是否忙碌)CPU一般比较关注,idle 空闲,有时候也查看wait (如果wait特别大往往是io这边已经达到了瓶颈)iostatiostat uses the files below to create ..._/proc/diskstat
文章浏览阅读2.4k次。问题:在Android上使用 glReadPixel 读取当前渲染数据,在若干机型(华为P9以及魅族某魅蓝手机)上读取数据失败,glGetError()没有抓到错误,但是获取到的数据有误,如果将获取到的数据保存成为图片,得到的图片为黑色。解决方法:glReadPixels实际上是从缓冲区中读取数据,如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓..._glreadpixels 全黑