HQChart实战教程18 - 多股同列

151 篇文章 33 订阅

多股同列

在一屏中显示多个K线图,使用统一的周期和指标, 下面是传统PC终端的多股同列截图
在这里插入图片描述

步骤

1. 创建div数组

创建div数组,同来绑定多个hqchart.
 <div class="klinelist" ref='klinelist'>
      <div class='kline' ref='kline' v-for='item in HQChartList' :key='item.ID'>
      </div>
 </div>
export default 
{ 
    name: 'MultiKLine',
    
    data() 
    {
        let data =
        {
            HQChartList: [],    //{ Symbol: ,Chart:null , ID:} 
            Period:0,   //周期
            HQChartType:0,  //0=K线  1=分时图
            ..........
        }
        return data;
    },

2. 创建多个hqchart

根据当前的周期类型, 创建分时图或K线图
创建K线图数组

CreateKLineChart()
{
     for(var i in this.$refs.kline)
     {
         var item=this.$refs.kline[i];
         let chart=HQChart.Chart.JSChart.Init(item);
         let option=DefaultData.GetKLineOption();
         option.KLine.Period=this.Period;
         option.Symbol=this.HQChartList[i].Symbol;
         chart.SetOption(option);

         this.HQChartList[i].Chart=chart;
     }
 },

创建分时图

CreateMinuteChart()
{
    for(var i in this.$refs.kline)
    {
        var item=this.$refs.kline[i];
        let chart=HQChart.Chart.JSChart.Init(item);
        let option=DefaultData.GetMinuteOption();
        option.Symbol=this.HQChartList[i].Symbol;
        chart.SetOption(option);

        this.HQChartList[i].Chart=chart;
    }
},

3. 多个hqchart位置计算

目前就计算了 9图,6图,4图分布, 如果要更多的图的分布,可以在这里加

 CalculateChartSize()   //计算布局
{
 var divList=this.$refs.klinelist;
 var height= divList.offsetHeight;
 var width = divList.offsetWidth; //获取外层div的大小
 var top=this.$refs.toptoolbar.offsetHeight;
 height-=top;
 console.log(`[MultiKLine::CalculateChartSize] height=${height} width=${width}, top=${top}`);

 var itemHeight = 0;
 var itemWidth = 0;
 var count = this.HQChartList.length;
 var rowCount = 0;  //一行放几个图

 if(count == 9)
 {
     itemHeight = height / 3;
     itemWidth = width / 3;
     rowCount = 3;
 }
 else if(count == 6)
 {
     itemHeight = height / 3;
     itemWidth = width / 2;
     rowCount = 2;
 }
 else if(count == 4)
 {
     itemHeight = height / 2;
     itemWidth = width / 2;
     rowCount = 2;
 }

 //调整div位置
 var aryKLine=this.$refs.kline;
 for(let i = 0; i < aryKLine.length; i++)
 {
     var divKLine=aryKLine[i];
     var rowIndex = i % rowCount;
     var colIndex = Math.floor(i / rowCount);
     divKLine.style.left = itemWidth * rowIndex + 'px';
     divKLine.style.top = (itemHeight*colIndex+top) + 'px';
     divKLine.style.width = itemWidth + 'px';
     divKLine.style.height = itemHeight + 'px';
 }
}

4. 鼠标和键盘事件

鼠标滚轴上下是用来翻页
键盘上下是统一缩放所有的K线图

  1. 首先我们要禁止hqchart内置的鼠标和键盘事件,
  2. 在外层的div的绑定鼠标,键盘事件
//K线配置信息
var option= 
 {
     Type:'历史K线图',   //创建图形类型
     
     ......
     IsAutoUpdate:true,              //是自动更新数据(不自动更新由外部更新)
     IsShowRightMenu:false,          //右键菜单

     CorssCursorInfo:{ IsShowCorss:false },  //不显示十字光标线

     KLine:  //K线设置
     {
         ........
         IsShowTooltip:false,           //是否显示 div K线提示信息 (手机端要填false)
     },

     Listener:   //去掉内置的滚动条和键盘事件
     {
         KeyDown:false,
         Wheel:false
     },
     ........
 };

绑定鼠标和键盘事件

mounted()
{
  ...........
  this.$refs.klinelist.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); 
  this.$refs.klinelist.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); 
}

键盘上下缩放K线

OnKeyDown(e)
{
    console.log("[MultiKLine::OnKeyDown]", e);

    var keyID = e.keyCode ? e.keyCode :e.which;
    switch(keyID)
    {
        case 38:   //up
        case 40:   //down
            this.ZoomUpDownChart(e);
            break;
    } 
},

ZoomUpDownChart(e)      //上下缩放K线图
{
     for(var i in this.HQChartList)
     {
         var item=this.HQChartList[i];
         if (!item.Chart) continue;

         item.Chart.JSChartContainer.OnKeyDown(e);
     }
 },

鼠标滚轴上下翻页

OnWheel(e)
{
     var wheelValue=e.wheelDelta;
     if (!HQChart.Chart.IFrameSplitOperator.IsObjectExist(e.wheelDelta))
         wheelValue=e.deltaY* -0.01;

     console.log("[MultiKLine::OnWheel] e, wheelValue ", e, wheelValue);

     if (wheelValue<0)
     {
         this.OnNextPage();
     }
     else if ( wheelValue>0)
     {
         this.OnPrevPage();
     }
 },

5. 切换一屏显示K线图个数

  1. 删除当前的hqchart实例和它内部创建的dom
  2. 通过this.HQChartList 创建出新的div
  3. 调整div的布局
  4. 创建hqchart实例
OnChangeChartCount(count)   //窗口个数
{
     if (this.HQChartList.length==count) return;

     this.DeleteChart();

     this.HQChartList=[];
     for(var i=0;i<count;++i)
     {
         var index=this.SymbolList.Index+i;
         var item={ Symbol:this.SymbolList.List[index], Chart:null , ID:HQChart.Chart.JSChart.CreateGuid() };
         this.HQChartList.push(item);
     }

     this.$nextTick(() => {
         this.OnSize();
         this.CreateChart(); 
     })
 },

DeleteChart() //参数hqchart实例
{
     for(var i in this.$refs.kline)
     {
         var divKLine=this.$refs.kline[i];
          while (divKLine.hasChildNodes()) 
         {
             divKLine.removeChild(divKLine.lastChild);
         } 
     }

     for(var i in this.HQChartList)
     {
         var item=this.HQChartList[i];
         if (item.Chart)
         {
             item.Chart.StopAutoUpdate();    //停止定时器
             item.Chart=null;
         }
     }
 },

6. 切换周期

如果是分时图,直接删除所有的分时图,创建线的K图
如果当前是K线图,直接调用ChangePeriod切换周期

OnChangeKLinePeriod(period)  //周期切换
{
    this.Period=period;
    if (this.HQChartType!=0)
    {
        this.HQChartType=0;
        this.DeleteChart();
        this.CreateChart(); 
    }
    else
    {
        for(var i in this.HQChartList)
        {
            var item=this.HQChartList[i];
            if (!item.Chart) continue;

            item.Chart.ChangePeriod(period);
        }
    }
},

7.切换指标

直接调用ChangeIndex切换对应的指标

OnChangeKLineIndex(id, name)
{
    if (this.HQChartType!=0) return;    //only kline has index

    for(var i in this.HQChartList)
    {
        var item=this.HQChartList[i];
        if (!item.Chart) continue;

        item.Chart.ChangeIndex(id, name);
    }
},

如果还有问题可以加交流QQ群: 950092318

HQChart代码地址

地址:github.com/jones2000/HQChart

完整代码

demo地址 https://opensource2.zealink.com/hqweb/vue_multikline/index.html
demo截图
在这里插入图片描述

完整代码

<template>
    <div style="width:100%;height:100%">
        <div ref='toptoolbar'>
            <button class="1D" @click="OnChangeKLinePeriod(0)"></button>
            <button class="1D" @click="OnChangeKLinePeriod(1)"></button>
            <button class="1D" @click="OnChangeKLinePeriod(2)"></button>
            <button class="1D" @click="OnChangeKLinePeriod(4)">1分钟</button>
            <button class="1D" @click="OnChangeKLinePeriod(5)">5分钟</button>
            <button class="1D" @click="OnChangeMinute()">分时</button>


            <button class="1D" @click="OnChangeChartCount(4)">4</button>
            <button class="1D" @click="OnChangeChartCount(6)">6</button>
            <button class="1D" @click="OnChangeChartCount(9)">9</button>

            <button class="1D" @click="OnNextPage()">下一页</button>
            <button class="1D" @click="OnPrevPage()">上一页</button>
        </div>
        <div class="klinelist" ref='klinelist'>
            <div class='kline' ref='kline' v-for='item in HQChartList' :key='item.ID'>
            </div>
        </div>

        <div ref='bottomtoolbar'>
            <button class="1D" @click="OnChangeKLineIndex(0, 'MA')">MA2</button>
            <button class="1D" @click="OnChangeKLineIndex(1, 'MACD')">MACD</button>
            <button class="1D" @click="OnChangeKLineIndex(1, 'RSI')">RSI</button>
        </div>
    </div>
</template>

<script>

import $ from 'jquery'
import HQChart from 'hqchart'
import 'hqchart/src/jscommon/umychart.resource/css/tools.css'
import 'hqchart/src/jscommon/umychart.resource/font/iconfont.css'

//源码调试用
//import Chart from './jscommon/umychart.vue/umychart.vue.js'
//var HQChart={ Chart:Chart };

function DefaultData() { }

DefaultData.GetKLineOption=function()
{
    //K线配置信息
    var option= 
    {
        Type:'历史K线图',   //创建图形类型
        
        Windows: //窗口指标
        [
            {Index:"MA8" , Modify:false,Change:false},
            {Index:"VOL", Modify:false,Change:false}, 
        ], 

        IsAutoUpdate:true,            //是自动更新数据(不自动更新由外部更新)
        IsShowRightMenu:false,          //右键菜单

        CorssCursorInfo:{ IsShowCorss:false },  //不显示十字光标线

        KLine:  //K线设置
        {
            DragMode:1,                   //拖拽模式 0 禁止拖拽 1 数据拖拽 2 区间选择
            Right:1,                      //复权 0 不复权 1 前复权 2 后复权
            Period:0,                     //周期 0 日线 1 周线 2 月线 3 年线 
            MaxReqeustDataCount:2000,     //数据个数
            MaxRequestMinuteDayCount:10,  //分钟数据取5天
            PageSize:30,                  //一屏显示多少数据
            IsShowTooltip:false,           //是否显示 div K线提示信息 (手机端要填false)
            DrawType:0,                   //K线类型 0=实心K线柱子 1=收盘价线 2=美国线 3=空心K线柱子 4=收盘价面积图
            RightSpaceCount:2
        },


        Listener:   //去掉内置的滚动条和键盘事件
        {
            KeyDown:false,
            Wheel:false
        },

        /*
        DragDownload: 
        { 
            Minute: { Enable:true },    //开启分钟数据拖拽下载
            Day: { Enable:true }        //开启日线数据拖拽下载
        },
        */

        KLineTitle: //标题设置
        {
            IsShowName:true,       //不显示股票名称
            IsShowSettingInfo:true //不显示周期/复权
        },

        Border: //边框
        {
            Left:1,         //左边间距
            Right:60,       //右边间距
            Bottom:25,      //底部间距
            Top:25           //顶部间距
        },
        
        Frame:  //子框架设置
        [
            { SplitCount:3,IsShowLeftText:false },
            { SplitCount:2,IsShowLeftText:false },
            { SplitCount:2,IsShowLeftText:false }
        ],

        ExtendChart:    //扩展图形
        [
            //{Name:'KLineTooltip' }  //手机端tooltip
        ],
    };

    return option;
}


DefaultData.GetMinuteOption=function()
{
     //分时图配置信息
    var option= 
    {
        Type:'分钟走势图',   //创建图形类型

        Windows: //窗口指标
        [
            //{Index:"MACD", Modify:false, Change:false, Close:false }
            //{Index:"涨跌趋势", Modify:false,Change:false},
        ], 
        
        Symbol:'000001.sz',              
        IsAutoUpdate:true,              //是自动更新数据
        DayCount:1,                     //1 最新交易日数据 >1 多日走势图
        IsShowRightMenu:false,          //是否显示右键菜单

        CorssCursorInfo:{ IsShowCorss:false},

        MinuteLine:
        {
            IsDrawAreaPrice:false,       //是否画价格面积图
            IsShowAveragePrice:true,   //不显示均线
        },

        Listener:   //去掉内置的滚动条和键盘事件
        {
            KeyDown:false,
            Wheel:false
        },

        Border: //边框
        {
            Left:60,    //左边间距
            Right:60,     //右边间距
            Top:25,
            Bottom:25
        },
    };

    return option;
}

export default 
{ 
    name: 'MultiKLine',

    data() 
    {
        let data =
        {
            HQChartList: [],    //{ Symbol: ,Chart:null , ID:} 
            Period:0,   //周期
            HQChartType:0,  //0=K线  1=分时图

            SymbolList:
            {
                List:
                [
                    "600000.sh",
                    "000001.sz",
                    "000030.sz",
                    "000001.sh",
                    "600999.sh",
                    "000042.sz",
                    "000021.sz",
                    "000030.sz",
                    "000031.sz",
                    "000032.sz",
                    "000034.sz",
                    "000030.sz",
                    "000031.sz",
                ],
                Index:0,
            },
        }
        return data;
    },


    created()
    {
        this.HQChartList=[];
        for(var i=0;i<4; ++i)
        {
            var item={Symbol:this.SymbolList.List[i],Chart:null , ID:HQChart.Chart.JSChart.CreateGuid()};
            this.HQChartList.push(item);
        }
    },

    mounted()
    {
        console.log(`[MultiKLine::mounted]`);

        HQChart.Chart.JSComplier.SetDomain('https://opensource.zealink.com');
        HQChart.Chart.JSChart.SetDomain('https://opensource.zealink.com');
        
        //黑色风格
        var blackStyle=HQChart.Chart.HQChartStyle.GetStyleConfig(HQChart.Chart.STYLE_TYPE_ID.BLACK_ID);
        HQChart.Chart.JSChart.SetStyle(blackStyle);

        //局部修改颜色
        //var resource=HQChart.JSChart.GetResource(); //获取全局资源
        //resource.FrameSplitTextFont='30px 微软雅黑';
        
        window.onresize = ()=>{ this.OnSize() }
        this.OnSize();  
        this.CreateChart();

        this.$refs.klinelist.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); 
        this.$refs.klinelist.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); 
    },

    methods:
    {
        CreateKLineChart()
        {
            for(var i in this.$refs.kline)
            {
                var item=this.$refs.kline[i];
                let chart=HQChart.Chart.JSChart.Init(item);
                let option=DefaultData.GetKLineOption();
                option.KLine.Period=this.Period;
                option.Symbol=this.HQChartList[i].Symbol;
                chart.SetOption(option);

                this.HQChartList[i].Chart=chart;
            }
        },

        CreateMinuteChart()
        {
            for(var i in this.$refs.kline)
            {
                var item=this.$refs.kline[i];
                let chart=HQChart.Chart.JSChart.Init(item);
                let option=DefaultData.GetMinuteOption();
                option.Symbol=this.HQChartList[i].Symbol;
                chart.SetOption(option);

                this.HQChartList[i].Chart=chart;
            }
        },

        CreateChart()
        {
            if (this.HQChartType==0) this.CreateKLineChart();
            else this.CreateMinuteChart();
        },

        OnSize()
        {
            this.CalculateChartSize();

            for(var i in this.$refs.kline)
            {
                var klineItem=this.HQChartList[i];
                if (klineItem && klineItem.Chart) klineItem.Chart.OnSize();
            }
        },

        OnKeyDown(e)
        {
            console.log("[MultiKLine::OnKeyDown]", e);

            var keyID = e.keyCode ? e.keyCode :e.which;
            switch(keyID)
            {
                case 38:   //up
                case 40:   //down
                    this.ZoomUpDownChart(e);
                    break;
            } 
        },

        OnWheel(e)
        {
            var wheelValue=e.wheelDelta;
            if (!HQChart.Chart.IFrameSplitOperator.IsObjectExist(e.wheelDelta))
                wheelValue=e.deltaY* -0.01;

            console.log("[MultiKLine::OnWheel] e, wheelValue ", e, wheelValue);

            if (wheelValue<0)
            {
                this.OnNextPage();
            }
            else if ( wheelValue>0)
            {
                this.OnPrevPage();
            }
        },

        OnChangeKLinePeriod(period)  //周期切换
        {
            this.Period=period;
            if (this.HQChartType!=0)
            {
                this.HQChartType=0;
                this.DeleteChart();
                this.CreateChart(); 
            }
            else
            {
                for(var i in this.HQChartList)
                {
                    var item=this.HQChartList[i];
                    if (!item.Chart) continue;

                    item.Chart.ChangePeriod(period);
                }
            }
        },

        OnChangeMinute()
        {
            if (this.HQChartType!=1)
            {
                this.HQChartType=1;
                this.DeleteChart();
                this.CreateChart(); 
            }
        },

        OnChangeChartCount(count)   //窗口个数
        {
            if (this.HQChartList.length==count) return;

            this.DeleteChart();

            this.HQChartList=[];
            for(var i=0;i<count;++i)
            {
                var index=this.SymbolList.Index+i;
                var item={ Symbol:this.SymbolList.List[index], Chart:null , ID:HQChart.Chart.JSChart.CreateGuid() };
                this.HQChartList.push(item);
            }

            this.$nextTick(() => {
                this.OnSize();
                this.CreateChart(); 
            })
        },

        OnChangeKLineIndex(id, name)
        {
            if (this.HQChartType!=0) return;    //only kline has index

            for(var i in this.HQChartList)
            {
                var item=this.HQChartList[i];
                if (!item.Chart) continue;

                item.Chart.ChangeIndex(id, name);
            }
        },

        OnNextPage()
        {
            if (this.SymbolList.Index+this.HQChartList.length>this.SymbolList.List.length) return;

            var start=this.SymbolList.Index+this.HQChartList.length;
            for(var i=0;i<this.HQChartList.length;++i)
            {
                var item=this.HQChartList[i];
                var index=start+i;
                if (index<this.SymbolList.List.length) 
                {
                    this.HQChartList[i].Symbol=this.SymbolList.List[index];
                    item.Chart.ChangeSymbol(this.SymbolList.List[index]);
                }
                else 
                {
                    this.HQChartList[i].Symbol=null;
                    item.Chart.ChangeSymbol(null);
                }
            }

            this.SymbolList.Index+=this.HQChartList.length;
        },

        OnPrevPage()
        {
            if (this.SymbolList.Index<=0) return;

            var start=this.SymbolList.Index-this.HQChartList.length;
            if (start<0) start=0;
            for(var i=0;i<this.HQChartList.length;++i)
            {
                var item=this.HQChartList[i];
                var index=start+i;
                if (index<this.SymbolList.List.length) 
                {
                    this.HQChartList[i].Symbol=this.SymbolList.List[index];
                    item.Chart.ChangeSymbol(this.SymbolList.List[index]);
                }
                else 
                {
                    this.HQChartList[i].Symbol=null;
                    item.Chart.ChangeSymbol(null);
                }
            }

            this.SymbolList.Index=start;
        },

        //
        //内部方法
        //

        CalculateChartSize()   //计算布局
        {
            var divList=this.$refs.klinelist;
            var height= divList.offsetHeight;
            var width = divList.offsetWidth; //获取外层div的大小
            var top=this.$refs.toptoolbar.offsetHeight;
            height-=top;
            console.log(`[MultiKLine::CalculateChartSize] height=${height} width=${width}, top=${top}`);

            var itemHeight = 0;
            var itemWidth = 0;
            var count = this.HQChartList.length;
            var rowCount = 0;  //一行放几个图

            if(count == 9)
            {
                itemHeight = height / 3;
                itemWidth = width / 3;
                rowCount = 3;
            }
            else if(count == 6)
            {
                itemHeight = height / 3;
                itemWidth = width / 2;
                rowCount = 2;
            }
            else if(count == 4)
            {
                itemHeight = height / 2;
                itemWidth = width / 2;
                rowCount = 2;
            }

            //调整div位置
            var aryKLine=this.$refs.kline;
            for(let i = 0; i < aryKLine.length; i++)
            {
                var divKLine=aryKLine[i];
                var rowIndex = i % rowCount;
                var colIndex = Math.floor(i / rowCount);
                divKLine.style.left = itemWidth * rowIndex + 'px';
                divKLine.style.top = (itemHeight*colIndex+top) + 'px';
                divKLine.style.width = itemWidth + 'px';
                divKLine.style.height = itemHeight + 'px';
            }
        },

        ZoomUpDownChart(e)      //上下缩放K线图
        {
            for(var i in this.HQChartList)
            {
                var item=this.HQChartList[i];
                if (!item.Chart) continue;

                item.Chart.JSChartContainer.OnKeyDown(e);
            }
        },


        DeleteChart()
        {
            for(var i in this.$refs.kline)
            {
                var divKLine=this.$refs.kline[i];
                 while (divKLine.hasChildNodes()) 
                {
                    divKLine.removeChild(divKLine.lastChild);
                } 
            }

            for(var i in this.HQChartList)
            {
                var item=this.HQChartList[i];
                if (item.Chart)
                {
                    item.Chart.StopAutoUpdate();    //停止定时器
                    item.Chart=null;
                }
            }
        },
    }
}

</script>

<style>

.kline
{
  position: absolute;
  background-color: black;
}

.klinelist
{
    width:100%;
    height:80%;
}
</style>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HQChart

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值