此处利用bootstrap+echarts画布配置参数实现响应式,并且利用socket实时通信实现数据的实时更新
(一)介绍
- ECharts (Enterprise Charts 商业产品图表库)
- ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript
图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。创新的拖拽重计算、数据视图、值域漫游等特性大大增强了用户体验,赋予了用户对数据进行挖掘、整合的能力。 提供商业产品常用图表,底层基于ZRender - (一个全新的轻量级canvas类库),创建了坐标系,图例,提示,工具箱等基础组件,并在此上构建出折线图(区域图)、柱状图(条状图)、散点图(气泡图)、饼图(环形图)、K
线图、地图、力导向布局图以及和弦图, - 同时支持任意维度的堆积和多图表混合展现。 优势:拖拽重计算,大规模数据模式直角系图表(折、柱、散点、K线)
- 20万数据秒级出图,拥有值域漫游的功能,让你可以轻松进行数值筛选。
(二)使用
一、插件的下载(echarts+bootstrap)
-
echarts
地址:http://echarts.baidu.com/download.html
或者使用npm拉取:npm install echarts --save
详情查看官网手册:http://echarts.baidu.com/tutorial.html#%E5%9C%A8%20webpack%20%E4%B8%AD%E4%BD%BF%E7%94%A8%20ECharts
bootstrap
地址:http://v3.bootcss.com/getting-started/#download
二、引入echarts+bootstrap+socket.io
-
echarts
只需要像普通的 JavaScript 库一样用 script 标签引入。
代码如下:
<!DOCTYPE html> <html> <header> <meta charset="utf-8"> <!-- 引入 ECharts 文件 --> <script src="echarts.min.js"></script> <script type="text/javascript" src="/statics/js/echarts/echarts-all-3.js"></script> <script type="text/javascript" src="/statics/js/echarts/extension/dataTool.min.js"></script> <script type="text/javascript" src="/statics/js/echarts/map/china.js"></script> <script type="text/javascript" src="/statics/js/echarts/map/world.js"></script> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=ZUONbpqGBsYGXNIYHicvbAbM"></script> <script type="text/javascript" src="/statics/js/echarts/extension/bmap.min.js"></script> <script src="/statics/js/socket.io.js"></script> <script src="/statics/js/echarts/echarts.js"></script> </header> </html>
-
bootstrap
我这里设置的啦ravel路径,根据自己情况,自行设置
<link rel="stylesheet" href="/statics/css/bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="/statics/css/bootstrap/bootstrap-theme.min.css">
<script src="/statics/js/bootstrap/bootstrap.min.js"></script> socket.io
<script src="/statics/js/socket.io.js"></script>
三、绘制一个简单的图表
-
在绘图前我们需要为 ECharts 准备一个具备高宽的 DOM 容器。
body里设置一个div放置画布使用
代码如下:
<body style="height:100%"> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <div class="container" style="height: 601px;width: 100%" id="container"> <form method="post">{{csrf_field()}}</form>//此处为csrftoken认证,防止跨域攻击 </div> @yield('content')//这里利用了laravel的模板继承 </nav> </body>
-
通过 echarts.init 方法初始化一个 echarts 实例并通过 setOption 方法生成一个简单的图
官网完整简单实例代码。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts</title> <!-- 引入 echarts.js --> <script src="echarts.min.js"></script> </head> <body> <!-- 为ECharts准备一个具备大小(宽高)的Dom --> <div id="main" style="width: 600px;height:400px;"></div> <script type="text/javascript"> // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('main')); // 指定图表的配置项和数据 var option = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data:['销量'] }, xAxis: { data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); </script> </body> </html>
我的初始化
> 因为使用了模板继承,将html头部和画布的div初始化到了一个模板中,代码如下
文件名:'zoushi.blade.com'
<!DOCTYPE html>
<html style="height: 100%" lang="en">
<head>
<style>
@media (min-width: 1200px) {
.col--2-5 {
float: left;
width: 8%;
margin-right: 1.4%;
}
}
</style>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Starter Template for Bootstrap</title>
<link rel="stylesheet" href="/statics/css/bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="/statics/css/bootstrap/bootstrap-theme.min.css">
<script src="/statics/js/jquery.min.js"></script>
<script src="/statics/js/bootstrap/bootstrap.min.js"></script>
<script type="text/javascript" src="/statics/js/echarts/echarts-all-3.js"></script>
<script type="text/javascript" src="/statics/js/echarts/extension/dataTool.min.js"></script>
<script type="text/javascript" src="/statics/js/echarts/map/china.js"></script>
<script type="text/javascript" src="/statics/js/echarts/map/world.js"></script>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=ZUONbpqGBsYGXNIYHicvbAbM"></script>
<script type="text/javascript" src="/statics/js/echarts/extension/bmap.min.js"></script>
<script src="/statics/js/socket.io.js"></script>
<script src="/statics/js/echarts/echarts.js"></script>
</head>
<body style="height:100%">
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container" style="height: 601px;width: 100%" id="container">
<form method="post">{{csrf_field()}}</form>
</div>
@yield('content')
</nav>
</body>
</html>
< 一下代码均在js中实现
1. K线图(需要的数据有:开盘价,闭盘价,最高价,最低价,时间)
1. 获取dom节点初始化
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
option = null;
app.title = '2015 年上证指数';
var limit=50;
function calculateMA(dayCount, data) {
var result = [];
for (var i = 0, len = data.length; i < len; i++) {
if (i < dayCount) {
result.push('-');
continue;
}
var sum = 0;
for (var j = 0; j < dayCount; j++) {
sum += data[i - j][1];
}
result.push(sum / dayCount);
}
return result;
}
var data=[['4654','6485','5456','6684']];
var dates=['122/12/4'];
require.config({
paths: {
echarts: 'http://echarts.baidu.com/build/dist'
}
});
2. 设置K线图的画布配置参数//详情见代码注释
require(
[
'echarts',
'echarts/chart/bar',// 使用柱状图就加载bar模块,按需加载
'echarts/chart/line',
'echarts/chart/k',
],
function (ec) {
// 基于准备好的dom,初始化echarts图表
var option = {
backgroundColor: '#21202D',
legend: {
data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30'],
inactiveColor: '#777',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
animation: false,
lineStyle: {
color: '#376df4',
width: 2,
opacity: 1
}
}
},
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: {readOnly: false},
magicType: {type: ['line', 'bar']},
restore: {},
saveAsImage: {}
}
},
xAxis: {
type: 'category',
data: dates,
axisLine: { lineStyle: { color: '#8392A5' } }
},
yAxis: {
min:'100%',
scale: true,
axisLine: { lineStyle: { color: '#8392A5' } },
splitLine: { show: false }
},
dataZoom: [{
textStyle: {
color: '#8392A5'
},
handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
handleSize: '80%',
dataBackground: {
areaStyle: {
color: '#8392A5'
},
lineStyle: {
opacity: 0.8,
color: '#8392A5'
}
},
handleStyle: {
color: '#fff',
shadowBlur: 3,
shadowColor: 'rgba(0, 0, 0, 0.6)',
shadowOffsetX: 2,
shadowOffsetY: 2
}
}, {
type: 'inside'
}],
animation: false,
series: [
{
type: 'candlestick',
name: '日K',
data: data,
markLine: {
symbol: ['none', 'none'],
symbolOffset:[0, '50%'],
data : [
[
{name: '标线2起点', value: data[data.length-1][1], x: '100%', yAxis: data[data.length-1][1]},
{name: '标线2终点', x: '10%', yAxis: data[data.length-1][1]}
]
]
},
itemStyle: {
normal: {
color: '#FD1050',
color0: '#0CF49B',
borderColor: '#FD1050',
borderColor0: '#0CF49B'
}
}
},
{
name: 'MA5',
type: 'line',
data: calculateMA(5, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'MA10',
type: 'line',
data: calculateMA(10, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'MA20',
type: 'line',
data: calculateMA(20, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'MA30',
type: 'line',
data: calculateMA(30, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
}
]
};
// 为echarts对象加载数据
myChart.setOption(option);
}
);
3. 写实时刷新需要改变的参数,封装为刷新函数//详情见代码注释
function refreshData(){
if(!myChart){
return;
}
//更新数据
var option = myChart.getOption();
option.series[0].data = data;
option.xAxis[0].dates = dates;
option.series[0].markLine.data[0][0].value=data[data.length-1][1];
option.series[0].markLine.data[0][0].yAxis=data[data.length-1][1];
option.series[0].markLine.data[0][1].value=data[data.length-1][1];
option.series[0].markLine.data[0][1].yAxis=data[data.length-1][1];
option.series[1].data=calculateMA(5, data);
option.series[2].data=calculateMA(10, data);
option.series[3].data=calculateMA(20, data);
option.series[4].data=calculateMA(30, data);
myChart.setOption(option);
console.log(data[data.length-1])
}
4. 利用socket通信,实时监听数据的到来
var socket = io('http://192.168.100.121:6002');
socket.on('connection', function (data) {
console.log(data);
});
socket.on('zxz:App\\Events\\Push', function(message){
window.onresize = myChart.resize;
if(message.open==data[data.length-1][0])
{
data[data.length-1][1]=message.close;
data[data.length-1][2]=message.max;
data[data.length-1][3]=message.min;
refreshData();
}else{
data.push([message.open,message.close,message.max,message.min]);
dates.push(message.time);
console.log(data.length+"----"+dates.length);
if(data.length==limit)
{
data.shift();
dates.shift();
refreshData();
}else{
refreshData();
}
}
});
2. 折线图(需要的数据有:闭盘价,时间)
1. 获取dom节点初始化
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
option = null;
app.title = '2015 年上证指数';
var limit = 50;
function calculateMA(dayCount, data) {
var result = [];
for (var i = 0, len = data.length; i < len; i++) {
if (i < dayCount) {
result.push('-');
continue;
}
var sum = 0;
for (var j = 0; j < dayCount; j++) {
sum += data[i - j];
}
result.push(sum / dayCount);
}
return result;
}
var data = ['4654'];
var dates = ['122/12/4'];
require.config({
paths: {
echarts: 'http://echarts.baidu.com/build/dist'
}
});
2. 设置折线图的画布配置参数+画布响应式//详情见代码注释
require(
[
'echarts',
'echarts/chart/line'
],
function (ec) {
// 基于准备好的dom,初始化echarts图表
var option = {
baseOption:{
backgroundColor: '#21202D',
legend: {
data: ['折线', 'MA5', 'MA10', 'MA20', 'MA30'],
inactiveColor: '#777',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
animation: false,
lineStyle: {
color: '#376df4',
width: 2,
opacity: 1
}
}
},
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: {readOnly: false},
magicType: {type: ['line', 'bar']},
restore: {},
saveAsImage: {}
}
},
xAxis: {
type: 'category',
data: dates,
axisLine: {lineStyle: {color: '#8392A5'}}
},
yAxis: {
position:'right',
scale: true,
axisLine: {lineStyle: {color: '#8392A5'}},
splitLine: {show: false}
},
dataZoom: [{
textStyle: {
color: '#8392A5'
},
handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
handleSize: '80%',
dataBackground: {
areaStyle: {
color: '#8392A5'
},
lineStyle: {
opacity: 0.8,
color: '#8392A5'
}
},
handleStyle: {
color: '#fff',
shadowBlur: 3,
shadowColor: 'rgba(0, 0, 0, 0.6)',
shadowOffsetX: 2,
shadowOffsetY: 2
}
}, {
type: 'inside',
show: false
}],
animation: false,
series: [
{
type: 'line',
name: '日K',
data: data,
showSymbol: false,
hoverAnimation: false,
data: data,
markLine: {
symbol: ['none', 'none'],
symbolOffset:[0, '50%'],
data : [
[
{name: '标线2起点', value: data[data.length-1], x: 100, yAxis: data[data.length-1]},
{name: '标线2终点', x: '90%', yAxis: data[data.length-1]}
]
]
}
},
{
name: 'MA5',
type: 'line',
data: calculateMA(5, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'MA10',
type: 'line',
data: calculateMA(10, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'MA20',
type: 'line',
data: calculateMA(20, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
},
{
name: 'MA30',
type: 'line',
data: calculateMA(30, data),
smooth: true,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
}
}
]
},
media:[{
query:{
maxWidth:500
},
option:{
legend: {
data: ['日K'],
inactiveColor: '#777',
textStyle: {
color: '#fff'
}
},
toolbox: {
show: false
},
series: [
{
name: 'MA5',
showSymbol: false,
hoverAnimation: false,
data: data
},
{
name: 'MA10',
showSymbol: false,
hoverAnimation: false,
data: data
},
{
name: 'MA20',
showSymbol: false,
hoverAnimation: false,
data: data
},
{
name: 'MA30',
showSymbol: false,
hoverAnimation: false,
data: data
}
],
dataZoom: [{show:false}]
}
}
]
};
// 为echarts对象加载数据
window.onresize = myChart.resize;
myChart.setOption(option);
}
);
3. 写实时刷新需要改变的参数,封装为刷新函数//详情见代码注释
function refreshData() {
if (!myChart) {
return;
}
//更新数据
var option = myChart.getOption();
option.series[0].data = data;
option.xAxis[0].dates = dates;
option.series[1].data = calculateMA(5, data);
option.series[2].data = calculateMA(10, data);
option.series[3].data = calculateMA(20, data);
option.series[4].data = calculateMA(30, data);
option.series[0].markLine.data[0][0].value=data[data.length-1];
option.series[0].markLine.data[0][0].yAxis=data[data.length-1];
option.series[0].markLine.data[0][1].value=data[data.length-1];
option.series[0].markLine.data[0][1].yAxis=data[data.length-1];
myChart.setOption(option);
}
4. 利用socket通信,实时监听数据的到来
var socket = io('http://192.168.100.121:6002');
socket.on('connection', function (data) {
console.log(data);
});
socket.on('zxz:App\\Events\\Push', function (message) {
window.onresize = myChart.resize;
if (message.open == open) {
} else {
data.push(message.open);
dates.push(message.time);
open = message.open;
console.log(data.length);
if (data.length == limit) {
data.shift();
dates.shift();
refreshData();
} else {
refreshData();
}
}
});