Compare commits
4 Commits
87311436e2
...
44b8bb8a65
Author | SHA1 | Date |
---|---|---|
|
44b8bb8a65 | 3 years ago |
|
279789f8ca | 3 years ago |
|
88d070852e | 3 years ago |
|
6c2bd0e017 | 3 years ago |
6 changed files with 924 additions and 441 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> |
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue