2 changed files with 835 additions and 391 deletions
@ -0,0 +1,457 @@ |
|||
<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> |
Loading…
Reference in new issue