You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
12 KiB
457 lines
12 KiB
<template>
|
|
<view class="content">
|
|
<!-- #ifdef APP-PLUS || H5 -->
|
|
<view @click="echarts.onClick" :prop="option" :change:prop="echarts.updateEcharts" id="echarts" class="echarts">
|
|
</view>
|
|
<!-- #endif -->
|
|
<!-- #ifndef APP-PLUS || H5 -->
|
|
<view>非 APP、H5 环境不支持</view>
|
|
<!-- #endif -->
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
// 数据意义:开盘(open),收盘(close),最低(lowest),最高(highest),数量(vol)
|
|
|
|
function splitData(rawData) {
|
|
let raw = JSON.parse(JSON.stringify(rawData))
|
|
let categoryData = [];
|
|
let values = [];
|
|
let volumes = [];
|
|
for (let i = 0; i < raw.length; i++) {
|
|
categoryData.push(raw[i].splice(0, 1)[0]);
|
|
values.push(raw[i]);
|
|
// console.log(raw[i],'*****')
|
|
// volumes.push([i, raw[i][4], raw[i][0] >= raw[i][1] ? 1 : -1]);
|
|
volumes.push([i, raw[i][3], raw[i][0] >= raw[i][1] ? 1 : -1]);
|
|
}
|
|
return {
|
|
categoryData: categoryData,
|
|
values: values,
|
|
volumes: volumes
|
|
};
|
|
}
|
|
|
|
function calculateMA(dayCount, values) {
|
|
let result = [];
|
|
for (let i = 0, len = values.length; i < len; i++) {
|
|
if (i < dayCount) {
|
|
result.push('-');
|
|
continue;
|
|
}
|
|
let sum = 0;
|
|
for (let j = 0; j < dayCount; j++) {
|
|
sum += values[i - j][1];
|
|
}
|
|
result.push(+(sum / dayCount).toFixed(3));
|
|
}
|
|
return result;
|
|
}
|
|
export default {
|
|
props: {
|
|
kData,
|
|
// 初始数据
|
|
initData: {
|
|
type: Array,
|
|
required: true
|
|
},
|
|
upColor: {
|
|
type: String,
|
|
default: 'rgb(49,186,160)'
|
|
},
|
|
downColor: {
|
|
type: String,
|
|
default: 'rgb(252,95,95)'
|
|
},
|
|
// 警戒线颜色
|
|
markLineColor: {
|
|
type: String,
|
|
default: '#ffffff'
|
|
},
|
|
// 警戒线文字颜色
|
|
markLineLabelColor: {
|
|
type: String,
|
|
default: '#ffffff'
|
|
},
|
|
// 警戒线第二排文字
|
|
markLineYTime: {
|
|
type: String,
|
|
default: '最新价'
|
|
},
|
|
// 警戒线文字背景颜色
|
|
markLineLabelBackgroundColor: {
|
|
type: String,
|
|
default: '#00b6ff'
|
|
},
|
|
// Y轴颜色
|
|
yAxisSplitLineColor: {
|
|
type: String,
|
|
default: '#333'
|
|
},
|
|
// Y轴刻度值颜色
|
|
yAxisAxisLabelColor: {
|
|
type: String,
|
|
default: '#fff'
|
|
},
|
|
// 背景图
|
|
backgroundImageUrl: {
|
|
type: String,
|
|
default: '#000'
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
option: {},
|
|
oldData: {}
|
|
}
|
|
},
|
|
onShow() {
|
|
console.log(this.kData);
|
|
this.init(this.kData)
|
|
},
|
|
mounted() {
|
|
if (this.initData.length > 0) {
|
|
this.init(this.initData)
|
|
}
|
|
},
|
|
methods: {
|
|
// 追加数据
|
|
addData(oo) {
|
|
let isUp = false;
|
|
let isUpIndex = true;
|
|
for (let i = 0; i < this.oldData.length; i++) {
|
|
// console.log(listData[i][0], oo[0],listData[i][0] != oo[0])
|
|
if (this.oldData[i][0] == oo[0]) {
|
|
isUp = true;
|
|
isUpIndex = i;
|
|
this.oldData[isUpIndex] = oo
|
|
}
|
|
}
|
|
|
|
if (!isUp) {
|
|
this.oldData.shift();
|
|
this.oldData.push(oo)
|
|
}
|
|
this.changeOption(this.oldData)
|
|
|
|
},
|
|
// 初始化数据
|
|
init(data) {
|
|
// console.log(data);
|
|
this.oldData = JSON.parse(JSON.stringify(data));
|
|
this.changeOption(this.oldData)
|
|
},
|
|
changeOption(res) {
|
|
let data = splitData(JSON.parse(JSON.stringify(res)));
|
|
this.option = {
|
|
// animation: false,
|
|
animationEasing: 'elasticOut',
|
|
legend: {
|
|
show: false,
|
|
bottom: 10,
|
|
left: 'center',
|
|
data: ['Dow-Jones index', 'MA5', 'MA10']
|
|
},
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
confine: true,
|
|
axisPointer: {
|
|
type: 'line',
|
|
},
|
|
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
|
position: function (pos, params, el, elRect, size) {
|
|
let obj = { top: 10 };
|
|
obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 30;
|
|
return obj;
|
|
},
|
|
extraCssText: 'width: 170px'
|
|
},
|
|
axisPointer: {
|
|
type: 'line',
|
|
lineStyle: {
|
|
type: 'solid',
|
|
color: '#ffffff'
|
|
},
|
|
link: { xAxisIndex: 'all' },
|
|
label: {
|
|
backgroundColor: '#777'
|
|
}
|
|
},
|
|
visualMap: {
|
|
show: false,
|
|
seriesIndex: 3,
|
|
dimension: 2,
|
|
pieces: [{
|
|
value: 1,
|
|
color: this.downColor
|
|
}, {
|
|
value: -1,
|
|
color: this.upColor
|
|
}]
|
|
},
|
|
grid: [
|
|
{
|
|
top: '4%',
|
|
left: '2%',
|
|
right: '18%',
|
|
height: '65%',
|
|
bottom: '0%',
|
|
borderWidth: 20
|
|
},
|
|
{
|
|
left: '2%',
|
|
right: '18%',
|
|
bottom: '5%',
|
|
height: '25%'
|
|
}
|
|
],
|
|
graphic: [
|
|
{
|
|
type: 'image', // 图形元素类型
|
|
id: 'logo', // 更新或删除图形元素时指定更新哪个图形元素,如果不需要用可以忽略。
|
|
right: 'center', // 根据父元素进行定位 (居中)
|
|
bottom: 'middle', // 根据父元素进行定位 (0%), 如果bottom的值是 0,也可以删除该bottom属性值。
|
|
z: 0, // 层叠
|
|
bounding: 'all', // 决定此图形元素在定位时,对自身的包围盒计算方式
|
|
style: {
|
|
image: this.backgroundImageUrl, // 这里一定要注意、注意,必须是https开头的图片路径地址
|
|
width: '100%',
|
|
height: '100%'
|
|
}
|
|
}],
|
|
xAxis: [
|
|
{
|
|
show: false,
|
|
type: 'category',
|
|
},
|
|
{
|
|
type: 'category',
|
|
gridIndex: 1,
|
|
data: data.categoryData,
|
|
// scale: true,
|
|
// boundaryGap: false,
|
|
axisTick: { show: false },
|
|
minorTick: { show: false },
|
|
axisLine: { onZero: false },
|
|
axisLabel: { onZero: false },
|
|
// splitNumber: 20,
|
|
min: 'dataMin',
|
|
max: 'dataMax',
|
|
axisPointer: {
|
|
label: {
|
|
formatter: function (params) {
|
|
let seriesValue = (params.seriesData[0] || {}).value;
|
|
return params.value
|
|
+ (seriesValue != null
|
|
? '\n' + echarts.format.addCommas(seriesValue)
|
|
: ''
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
],
|
|
yAxis: [
|
|
{
|
|
scale: true,
|
|
position: 'right',
|
|
splitLine: {
|
|
show: true,
|
|
lineStyle: {
|
|
color: this.yAxisSplitLineColor
|
|
}
|
|
},
|
|
axisLabel: {
|
|
show: true,
|
|
color: this.yAxisAxisLabelColor,
|
|
},
|
|
minorTick: {
|
|
show: true,
|
|
splitNumber: 10,
|
|
lineStyle: {
|
|
color: this.yAxisAxisLabelColor,
|
|
}
|
|
}
|
|
},
|
|
{
|
|
scale: true,
|
|
gridIndex: 1,
|
|
splitNumber: 1,
|
|
axisLabel: { show: false },
|
|
axisLine: { show: false },
|
|
axisTick: { show: false },
|
|
splitLine: { show: false }
|
|
}
|
|
],
|
|
dataZoom: [
|
|
{
|
|
type: 'inside',
|
|
xAxisIndex: [0, 1],
|
|
zoomOnMouseWheel: false,
|
|
moveOnMouseMove: false,
|
|
moveOnMouseWheel: false,
|
|
start: 0,
|
|
end: 100,
|
|
},
|
|
{
|
|
show: true,
|
|
xAxisIndex: [0, 1],
|
|
type: 'inside',
|
|
zoomOnMouseWheel: false,
|
|
moveOnMouseMove: false,
|
|
moveOnMouseWheel: false,
|
|
top: '85%',
|
|
start: 0,
|
|
end: 100,
|
|
}
|
|
],
|
|
series: [
|
|
{
|
|
name: 'Dow-Jones index',
|
|
type: 'candlestick',
|
|
data: data.values,
|
|
itemStyle: {
|
|
color: this.upColor,
|
|
color0: this.downColor,
|
|
borderColor: null,
|
|
borderColor0: null
|
|
},
|
|
tooltip: {
|
|
formatter: function (param) {
|
|
param = param[0];
|
|
return [
|
|
'Date: ' + param.name + '<hr size=1 style="margin: 3px 0">',
|
|
'Open: ' + param.data[0] + '<br/>',
|
|
'Close: ' + param.data[1] + '<br/>',
|
|
'Lowest: ' + param.data[2] + '<br/>',
|
|
'Highest: ' + param.data[3] + '<br/>'
|
|
].join('');
|
|
}
|
|
},
|
|
markLine: {
|
|
symbol: 'none', //去掉警戒线最后面的箭头
|
|
data: [
|
|
{
|
|
silent: false,//鼠标悬停事件 true没有,false有
|
|
yAxis: data.values[data.values.length - 1][1],// 警戒线的标注值,可以有多个yAxis,多条警示线 或者采用 {type : 'average', name: '平均值'},type值有 max min average,分为最大,最小,平均值
|
|
lineStyle: { //警戒线的样式 ,虚实 颜色
|
|
type: "solid",
|
|
color: this.markLineColor,
|
|
},
|
|
label: {
|
|
position: "end",//将警示值放在哪个位置,三个值“start”,"middle","end" 开始 中点 结束
|
|
color: this.markLineLabelColor,
|
|
// backgroundColor:"#00b6ff",
|
|
fontSize: "12px",
|
|
formatter: [
|
|
'{a|{c}}',
|
|
'{b|' + this.markLineYTime + '}'
|
|
].join('\n'),
|
|
// formatter:"{c}\n最新价",
|
|
rich: {
|
|
a: {
|
|
padding: 4,
|
|
backgroundColor: this.markLineLabelBackgroundColor,
|
|
align: 'right',
|
|
},
|
|
b: {
|
|
padding: 4,
|
|
backgroundColor: this.markLineLabelBackgroundColor,
|
|
align: 'right',
|
|
},
|
|
}
|
|
},
|
|
},
|
|
]
|
|
},
|
|
},
|
|
{
|
|
name: 'MA5',
|
|
type: 'line',
|
|
symbol: "none",
|
|
data: calculateMA(5, data.values),
|
|
smooth: true,
|
|
lineStyle: {
|
|
opacity: 0.5
|
|
}
|
|
},
|
|
{
|
|
name: 'MA10',
|
|
type: 'line',
|
|
symbol: "none",
|
|
data: calculateMA(10, data.values),
|
|
smooth: true,
|
|
lineStyle: {
|
|
opacity: 0.5
|
|
}
|
|
},
|
|
{
|
|
name: 'Volume',
|
|
type: 'bar',
|
|
xAxisIndex: 1,
|
|
yAxisIndex: 1,
|
|
data: data.volumes
|
|
}
|
|
]
|
|
}
|
|
},
|
|
onViewClick(options) {
|
|
// console.log(options)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<script module="echarts" lang="renderjs">
|
|
let myChart
|
|
export default {
|
|
mounted() {
|
|
if (typeof window.echarts === 'function') {
|
|
this.initEcharts()
|
|
} else {
|
|
// 动态引入较大类库避免影响页面展示
|
|
const script = document.createElement('script')
|
|
// view 层的页面运行在 www 根目录,其相对路径相对于 www 计算
|
|
script.src = 'static/echarts.min.js'
|
|
script.onload = this.initEcharts.bind(this)
|
|
document.head.appendChild(script)
|
|
}
|
|
},
|
|
methods: {
|
|
initEcharts() {
|
|
myChart = echarts.init(document.getElementById('echarts'), null, {renderer: 'svg'})
|
|
// 观测更新的数据在 view 层可以直接访问到
|
|
myChart.setOption(this.option)
|
|
},
|
|
updateEcharts(newValue, oldValue, ownerInstance, instance) {
|
|
// 监听 service 层数据变更
|
|
if (myChart) {
|
|
myChart.setOption(newValue)
|
|
}
|
|
},
|
|
onClick(event, ownerInstance) {
|
|
// 调用 service 层的方法
|
|
ownerInstance.callMethod('onViewClick', {
|
|
test: 'test'
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.echarts {
|
|
width: 100%;
|
|
height: 482px;
|
|
overflow: hidden;
|
|
width: 100%;
|
|
background-color: #12023e;
|
|
}
|
|
</style>
|
|
|