uniapp 使用renderjs 实现app使用echarts
·
由于项目需要在app端实现图表效果 ucharts无法实现 就打算使用echarts来实现,下面是我实现的具体步骤仅供参考
html 代码
通过prop进行绑定变量用:change:prop传递给renderjs的函数,当绑定的变量发生改变就会触发change里面的函数从而实现页面给renderjs发送消息
:change:prop="echartsRender.updateMap"里面的map是<script module="echartsRender" lang="renderjs">里面module的名称
<view :prop="msg" :change:prop="echartsRender.onChange" style="width: 100%;height: 400rpx;" ref="echrtsBox"
id="echrts-box">
</view>
data里面数据
msg: "",
option: {
tooltip: {
trigger: 'axis',
axisPointer: {
animation: false
},
},
axisPointer: {
link: [{
xAxisIndex: 'all'
}]
},
dataZoom: [{
show: false,
realtime: true,
start: 0,
end: 100,
xAxisIndex: [0, 1]
},
{
type: 'inside',
realtime: true,
start: 0,
end: 100,
xAxisIndex: [0, 1]
}
],
grid: [{
top: '3%',
left: '10%',
right: '8%',
height: '47%',
// containLabel: true
},
{
left: '10%',
right: '8%',
top: '50%',
height: '40%',
// containLabel: true
}
],
xAxis: [{
type: 'category',
boundaryGap: false,
axisLine: {
onZero: true,
},
// data: timeData,
show: false,
axisLabel: {
// interval: 105
interval: 'auto'
}
},
{
axisLabel: {
interval: 'auto'
},
gridIndex: 1,
type: 'category',
boundaryGap: false,
axisLine: {
onZero: true
},
// data: timeData,
position: 'bottom',
show: true,
axisTick: {
show: false
}
}
],
yAxis: [{
type: 'value',
splitNumber: 3,
splitLine: { // 坐标轴在 grid 区域中的分隔线
lineStyle: { // 分隔线
type: 'dashed', // 线的类型
color: '#666' // 分隔线颜色
}
},
},
{
gridIndex: 1,
type: 'value',
inverse: true,
splitNumber: 3,
splitLine: { // 坐标轴在 grid 区域中的分隔线
lineStyle: { // 分隔线
type: 'dashed', // 线的类型
color: '#666' // 分隔线颜色
}
},
}
],
series: [{
barWidth: 16,
name: this.$t('发电功率'),
type: 'line',
symbolSize: 0,
smooth: true,
symbol: false,
itemStyle: {
color: '#67A100',
// barBorderRadius: [100, 100, 0, 0],
borderRadius: [100, 100, 0, 0],
},
lineStyle: {
width: 2,
color: "#67A100",
},
showSymbol: true,
areaStyle: {
opacity: 0.8,
color: "#D2E3B3",
},
emphasis: {
focus: "series",
},
data: this.consumerData,
},
{
barWidth: 16,
name: this.$t('用电功率'),
type: 'line',
xAxisIndex: 1,
yAxisIndex: 1,
symbolSize: 0,
smooth: true,
symbol: false,
itemStyle: {
color: 'rgba(255,164,0,1)',
// barBorderRadius: [0, 0, 100, 100],
borderRadius: [0, 0, 100, 100],
},
lineStyle: {
width: 2,
color: "rgba(255,164,0,1)",
},
areaStyle: {
opacity: 0.8,
color: "#FFE4B3",
},
emphasis: {
focus: "series",
},
data: this.producerData
}
]
},
触发函数 改msg的值
setEchartTwo里面传递过来的数据的值通过改msg的值去触发renderjs的方法
this.msg = {
radioValue: radioValue,
token: Date.now(),
option: this.option
}
goClear() {
console.log("msg为空")
this.msg = '';
},
setEchartTwo(consumerData, producerData, radioValue) {
this.option.xAxis.data = [];
this.producerData = [
["00:00", 0],
["00:15", 0],
["00:30", 0],
["01:00", 0],
];
this.consumerData = [
["00:00", 0],
["00:15", 0],
["00:30", 0],
["01:00", 0],
];
const x0 = [];
const d0 = [];
const x1 = [];
const d1 = [];
if (radioValue === 2) {
consumerData.forEach((item, index) => {
x1.push(item[0].slice(0, 5));
d1.push(item[1]);
})
producerData.forEach((item, index) => {
x0.push(item[0].slice(0, 5));
d0.push(item[1]);
})
this.option.xAxis[0].data = x1;
this.option.series[0].data = d1;
this.option.xAxis[1].data = x0;
this.option.series[1].data = d0;
}
if (radioValue == 4) {
consumerData.forEach((item, index) => {
item[0] = item[0].slice(-2);
})
producerData.forEach((item, index) => {
item[0] = item[0].slice(-2);
})
}
if (radioValue !== 2) {
// this.option.series[0].data = consumerData || this.consumerData;
// this.option.series[1].data = producerData || this.producerData;
// console.log('consumerDataconsumerDataconsumerDataconsumerData',consumerData);
// console.log('producerDataproducerDataproducerDataproducerData',producerData);
consumerData.forEach((item, index) => {
x0.push(item[0]);
d0.push(item[1]);
})
producerData.forEach((item, index) => {
x1.push(item[0]);
d1.push(item[1]);
})
this.option.xAxis[0].data = x0;
this.option.series[0].data = d0;
this.option.xAxis[1].data = x1;
this.option.series[1].data = d1;
}
this.option.series[0].type = [1, 2].includes(radioValue) ? 'line' : 'bar'
this.option.series[1].type = [1, 2].includes(radioValue) ? 'line' : 'bar';
console.log('this.option.xAxis[0]', this.option.xAxis[0].axisLabel);
if (radioValue === 2) {
this.option.xAxis[0].axisLabel.interval = 105;
this.option.xAxis[1].axisLabel.interval = 105;
} else {
this.option.xAxis[0].axisLabel.interval = 'auto';
this.option.xAxis[1].axisLabel.interval = 'auto';
}
if (this.optionTwo.series[0].type == 'bar') {
this.optionTwo.xAxis[0].boundaryGap = true;
}
this.option.series[0].name = [1, 2].includes(radioValue) ? this.$t('发电功率') : this.$t('发电量')
this.option.series[1].name = [1, 2].includes(radioValue) ? this.$t('用电功率') : this.$t('用电量')
this.$nextTick(function() {
console.log('========================================================');
console.log('this.option', this.option);
console.log('========================================================');
this.msg = {
radioValue: radioValue,
token: Date.now(),
option: this.option
}
})
},
renderjs的onChange方法
onChange(newValue, oldValue, ownerInstance, instance) {
console.log('新值newValue', newValue)
let t = this;
let obj = newValue.option ? JSON.parse(JSON.stringify(newValue.option)) : '';
if (obj) {
if (obj.tooltip) {
obj.tooltip.formatter = function(params) {
let time = t.calculateTimeFromIndex(params[0].dataIndex, 15);
let tooltipText = newValue.radioValue == 2 ? `${params[0].axisValue} ${time}<br/>` :
`${params[0].axisValue}<br/>`;
params.forEach(item => {
// 根据系列名称或数据索引来定义单位
let unit = '';
tooltipText += `
<div style="display: flex;justify-content:space-between;">
<span style="margin-right:30px;">${item.marker}${item.seriesName}</span> <span style="font-weight:bold;">
${item.value===0?0:item.value?item.value:'-'}
</span>
</div>`;
});
return tooltipText;
}
}
if (myChart) {
document.getElementById('echrts-box').removeAttribute('_echarts_instance_');
}
this.setEchart(obj);
} else {
if (myChart) {
document.getElementById('echrts-box').removeAttribute('_echarts_instance_')
myChart.dispatchAction({
type: 'hideTip'
});
myChart.clear();
}
}
},
renderjs给页面传递值的函数
// 发送数据到service层
emitData(event, ownerInstance) {
// event是事件对象
ownerInstance.callMethod('acceptDataFromRenderjs', {
content: this.content
})
// 或者
/* this.$ownerInstance.callMethod('acceptDataFromRenderjs',{
content:this.content
}) */
// 需要注意的是:只有通过在template中用户手动操作触发renderjs的方法参数是这两个:event, ownerInstance;通过其他方法触发的函数参数不一样
},
接收renderjs传递过来值的函数
// 接收renderjs发回的数据
acceptDataFromRenderjs(data) {
console.log('从renderjs中接收到的数据', data)
},
完整代码
<template>
<view class="history-data-box">
<view class="header-box">
<!-- <view class="echarts-control">
<view class="control-item">
<view class="line"></view>
<span>{{ $t('发电功率') }}(kW)</span>
</view>
<view class="control-item">
<view class="line2"></view>
<span>{{ $t('用电功率') }}(kW)</span>
</view>
</view> -->
<view :prop="msg" :change:prop="echartsRender.onChange" style="width: 100%;height: 400rpx;" ref="echrtsBox"
id="echrts-box">
</view>
<!-- <canvas canvas-id="myChart" :style="{width: '100%', height: '500px'}"></canvas> -->
</view>
</view>
</template>
<script>
export default {
data() {
return {
dateValue: '',
radioValue: 1,
radioData: [{
label: this.$t('日'),
value: 1
},
{
label: this.$t('周'),
value: 2
},
{
label: this.$t('月'),
value: 3
},
{
label: this.$t('年'),
value: 4
},
{
label: this.$t('总'),
value: 5
},
],
id: '',
consumerData: [
], // 用电功率
producerData: [], // 发电功率
loading: false,
lineEcharts: null,
msg: "",
option: {
tooltip: {
trigger: 'axis',
axisPointer: {
animation: false
},
},
axisPointer: {
link: [{
xAxisIndex: 'all'
}]
},
dataZoom: [{
show: false,
realtime: true,
start: 0,
end: 100,
xAxisIndex: [0, 1]
},
{
type: 'inside',
realtime: true,
start: 0,
end: 100,
xAxisIndex: [0, 1]
}
],
grid: [{
top: '3%',
left: '10%',
right: '8%',
height: '47%',
// containLabel: true
},
{
left: '10%',
right: '8%',
top: '50%',
height: '40%',
// containLabel: true
}
],
xAxis: [{
type: 'category',
boundaryGap: false,
axisLine: {
onZero: true,
},
// data: timeData,
show: false,
axisLabel: {
// interval: 105
interval: 'auto'
}
},
{
axisLabel: {
interval: 'auto'
},
gridIndex: 1,
type: 'category',
boundaryGap: false,
axisLine: {
onZero: true
},
// data: timeData,
position: 'bottom',
show: true,
axisTick: {
show: false
}
}
],
yAxis: [{
type: 'value',
splitNumber: 3,
splitLine: { // 坐标轴在 grid 区域中的分隔线
lineStyle: { // 分隔线
type: 'dashed', // 线的类型
color: '#666' // 分隔线颜色
}
},
},
{
gridIndex: 1,
type: 'value',
inverse: true,
splitNumber: 3,
splitLine: { // 坐标轴在 grid 区域中的分隔线
lineStyle: { // 分隔线
type: 'dashed', // 线的类型
color: '#666' // 分隔线颜色
}
},
}
],
series: [{
barWidth: 16,
name: this.$t('发电功率'),
type: 'line',
symbolSize: 0,
smooth: true,
symbol: false,
itemStyle: {
color: '#67A100',
// barBorderRadius: [100, 100, 0, 0],
borderRadius: [100, 100, 0, 0],
},
lineStyle: {
width: 2,
color: "#67A100",
},
showSymbol: true,
areaStyle: {
opacity: 0.8,
color: "#D2E3B3",
},
emphasis: {
focus: "series",
},
data: this.consumerData,
},
{
barWidth: 16,
name: this.$t('用电功率'),
type: 'line',
xAxisIndex: 1,
yAxisIndex: 1,
symbolSize: 0,
smooth: true,
symbol: false,
itemStyle: {
color: 'rgba(255,164,0,1)',
// barBorderRadius: [0, 0, 100, 100],
borderRadius: [0, 0, 100, 100],
},
lineStyle: {
width: 2,
color: "rgba(255,164,0,1)",
},
areaStyle: {
opacity: 0.8,
color: "#FFE4B3",
},
emphasis: {
focus: "series",
},
data: this.producerData
}
]
},
optionTwo: {
tooltip: {
trigger: 'axis',
},
grid: {
bottom: '3%',
top: '3%',
left: '3.8%',
right: '3.8%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
axisLabel: {
interval: 'auto'
}
}],
yAxis: [{
type: 'value',
splitLine: { // 坐标轴在 grid 区域中的分隔线
lineStyle: { // 分隔线
type: 'dashed', // 线的类型
color: '#666' // 分隔线颜色
}
},
}],
series: [{
name: '',
type: '',
symbolSize: 0,
smooth: true,
symbol: false,
barWidth: 16,
itemStyle: {
color: '#67A100',
// barBorderRadius: [100, 100, 0, 0],
borderRadius: [100, 100, 0, 0],
},
lineStyle: {
width: 2,
color: "#67A100",
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: "#D2E3B3",
},
emphasis: {
focus: 'series'
},
data: this.consumerData
}, ]
}
}
},
methods: {
goClear() {
console.log("msg为空")
this.msg = '';
},
// 接收renderjs发回的数据
acceptDataFromRenderjs(data) {
console.log('从renderjs中接收到的数据', data)
this.msg = data.content
},
setEchartTwo(consumerData, producerData, radioValue) {
this.option.xAxis.data = [];
this.producerData = [
["00:00", 0],
["00:15", 0],
["00:30", 0],
["01:00", 0],
];
this.consumerData = [
["00:00", 0],
["00:15", 0],
["00:30", 0],
["01:00", 0],
];
const x0 = [];
const d0 = [];
const x1 = [];
const d1 = [];
if (radioValue === 2) {
consumerData.forEach((item, index) => {
x1.push(item[0].slice(0, 5));
d1.push(item[1]);
})
producerData.forEach((item, index) => {
x0.push(item[0].slice(0, 5));
d0.push(item[1]);
})
this.option.xAxis[0].data = x1;
this.option.series[0].data = d1;
this.option.xAxis[1].data = x0;
this.option.series[1].data = d0;
}
if (radioValue == 4) {
consumerData.forEach((item, index) => {
item[0] = item[0].slice(-2);
})
producerData.forEach((item, index) => {
item[0] = item[0].slice(-2);
})
}
if (radioValue !== 2) {
// this.option.series[0].data = consumerData || this.consumerData;
// this.option.series[1].data = producerData || this.producerData;
// console.log('consumerDataconsumerDataconsumerDataconsumerData',consumerData);
// console.log('producerDataproducerDataproducerDataproducerData',producerData);
consumerData.forEach((item, index) => {
x0.push(item[0]);
d0.push(item[1]);
})
producerData.forEach((item, index) => {
x1.push(item[0]);
d1.push(item[1]);
})
this.option.xAxis[0].data = x0;
this.option.series[0].data = d0;
this.option.xAxis[1].data = x1;
this.option.series[1].data = d1;
}
this.option.series[0].type = [1, 2].includes(radioValue) ? 'line' : 'bar'
this.option.series[1].type = [1, 2].includes(radioValue) ? 'line' : 'bar';
console.log('this.option.xAxis[0]', this.option.xAxis[0].axisLabel);
if (radioValue === 2) {
this.option.xAxis[0].axisLabel.interval = 105;
this.option.xAxis[1].axisLabel.interval = 105;
} else {
this.option.xAxis[0].axisLabel.interval = 'auto';
this.option.xAxis[1].axisLabel.interval = 'auto';
}
if (this.optionTwo.series[0].type == 'bar') {
this.optionTwo.xAxis[0].boundaryGap = true;
}
this.option.series[0].name = [1, 2].includes(radioValue) ? this.$t('发电功率') : this.$t('发电量')
this.option.series[1].name = [1, 2].includes(radioValue) ? this.$t('用电功率') : this.$t('用电量')
this.$nextTick(function() {
console.log('========================================================');
console.log('this.option', this.option);
console.log('========================================================');
this.msg = {
radioValue: radioValue,
token: Date.now(),
option: this.option
}
})
},
setEchartThree(consumerData, producerData, radioValue) {
this.producerData = [
["00:00", 0],
["00:15", 0],
["00:30", 0],
["01:00", 0],
];
this.consumerData = [
["00:00", 0],
["00:15", 0],
["00:30", 0],
["01:00", 0],
];
const x0 = [];
const d0 = [];
console.log('进入了setEchartThree');
if (radioValue === 2) {
consumerData.forEach((item, index) => {
x0.push(item[0].slice(0, 5));
d0.push(item[1]);
})
this.optionTwo.xAxis[0].data = x0;
this.optionTwo.series[0].data = d0;
}
if (radioValue !== 2) {
consumerData.forEach((item, index) => {
x0.push(item[0]);
d0.push(item[1]);
})
this.optionTwo.xAxis[0].data = x0;
this.optionTwo.series[0].data = d0;
}
this.optionTwo.series[0].name = [1, 2].includes(radioValue) ? this.$t('发电功率') : this.$t('发电量')
this.optionTwo.series[0].type = [1, 2].includes(radioValue) ? 'line' : 'bar'
if (this.optionTwo.series[0].type == 'bar') {
this.optionTwo.xAxis[0].boundaryGap = true;
}
if (radioValue === 2) {
this.optionTwo.xAxis[0].axisLabel.interval = 105;
// this.optionTwo.xAxis[1].axisLabel.interval = 105;
} else {
this.optionTwo.xAxis[0].axisLabel.interval = 'auto';
// this.optionTwo.xAxis[1].axisLabel.interval = 'auto';
}
console.log(' this.optionTwo', this.optionTwo);
this.msg = {
radioValue: radioValue,
token: Date.now(),
option: this.optionTwo
}
},
}
}
</script>
<script module="echartsRender" lang="renderjs">
import * as echarts from "echarts";
var myChart;
export default {
data() {
return {
content: "",
}
},
methods: {
// 发送数据到service层
emitData(event, ownerInstance) {
// event是事件对象
ownerInstance.callMethod('acceptDataFromRenderjs', {
content: this.content
})
// 或者
/* this.$ownerInstance.callMethod('acceptDataFromRenderjs',{
content:this.content
}) */
// 需要注意的是:只有通过在template中用户手动操作触发renderjs的方法参数是这两个:event, ownerInstance;通过其他方法触发的函数参数不一样
},
onChange(newValue, oldValue, ownerInstance, instance) {
console.log('新值newValue', newValue)
let t = this;
let obj = newValue.option ? JSON.parse(JSON.stringify(newValue.option)) : '';
if (obj) {
if (obj.tooltip) {
obj.tooltip.formatter = function(params) {
let time = t.calculateTimeFromIndex(params[0].dataIndex, 15);
let tooltipText = newValue.radioValue == 2 ? `${params[0].axisValue} ${time}<br/>` :
`${params[0].axisValue}<br/>`;
params.forEach(item => {
// 根据系列名称或数据索引来定义单位
let unit = '';
tooltipText += `
<div style="display: flex;justify-content:space-between;">
<span style="margin-right:30px;">${item.marker}${item.seriesName}</span> <span style="font-weight:bold;">
${item.value===0?0:item.value?item.value:'-'}
</span>
</div>`;
});
return tooltipText;
}
}
if (myChart) {
document.getElementById('echrts-box').removeAttribute('_echarts_instance_');
}
this.setEchart(obj);
} else {
if (myChart) {
document.getElementById('echrts-box').removeAttribute('_echarts_instance_')
myChart.dispatchAction({
type: 'hideTip'
});
myChart.clear();
}
}
},
setEchart(newValue) {
myChart = echarts.init(document.getElementById('echrts-box'))
// 观测更新的数据在 view 层可以直接访问到
if (!newValue.series) {
return
}
myChart.dispatchAction({
type: 'hideTip'
});
// myChart.dispatchAction({
// type: 'clear'
// });
newValue.series[0].areaStyle = {
origin: "start",
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: "#8EDE00",
},
{
offset: 1,
color: "rgba(142,222,0, 0.1)",
},
]),
};
if (newValue.series[1]) {
newValue.series[1].areaStyle = {
origin: "start",
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: "rgba(255,132,0, 0.1)",
},
{
offset: 1,
color: "#FF8400",
},
]),
};
}
myChart.setOption(newValue)
},
calculateTimeFromIndex(index, intervalMinutes) {
// 计算总分钟数
const totalMinutes = index * intervalMinutes;
// 计算小时和分钟
const hours = Math.floor(totalMinutes / 60) % 24; // 总分钟数除以60得到小时
const minutes = totalMinutes % 60; // 总分钟数取模60得到剩余分钟
// 格式化为两位数的时分格式
const formattedHours = String(hours).padStart(2, '0');
const formattedMinutes = String(minutes).padStart(2, '0');
return `${formattedHours}:${formattedMinutes}`;
},
},
}
</script>
<style lang="scss" scoped>
.history-data-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.header-box {
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: column;
.echarts-control {
display: flex;
align-items: center;
color: #333333;
font-size: 12px;
font-weight: 400;
gap: 16px;
.control-item {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
.line {
width: 50px;
height: 4px;
background: #67A100;
border-radius: 3px;
position: relative;
}
.line::after {
content: '';
width: 10px;
height: 10px;
background: #67A100;
border-radius: 50%;
position: absolute;
left: 50%;
transform: translateX(-50%);
top: -3px;
}
.line2 {
width: 50px;
height: 4px;
background: #FFA400;
border-radius: 3px;
position: relative;
}
.line2::after {
content: '';
width: 10px;
height: 10px;
background: #FFA400;
border-radius: 50%;
position: absolute;
left: 50%;
transform: translateX(-50%);
top: -3px;
}
}
}
.search-box {
display: flex;
align-items: center;
gap: 12px;
.radio-box {
display: flex;
align-items: center;
// border: 1px solid red;
border-radius: 4px;
.radio-item {
min-width: 50px;
padding: 6px 18px;
border-top: 1px solid #EBEBEB;
border-bottom: 1px solid #EBEBEB;
border-right: 1px solid #EBEBEB;
font-size: 12px;
font-weight: 400;
cursor: pointer;
color: #666666;
}
.item-first {
border-radius: 4px 0px 0px 4px;
border-left: 1px solid #EBEBEB;
}
.item-last {
border-radius: 0px 4px 4px 0px;
}
.check-item {
border: 1px solid #67A100;
background: #67A100;
color: #FFFFFF;
}
}
.date-box {
display: flex;
align-items: center;
border-radius: 4px;
border: 1px solid #EBEBEB;
padding-right: 8px;
.date-icon {
width: 16px;
height: 16px;
}
}
}
}
#echrts-box {
flex: 1;
margin-top: 16px;
}
}
::v-deep {
.date-box {
.el-input__inner {
padding-left: 8px;
padding-right: 4px;
height: 29px;
font-size: 12px;
line-height: 29px;
// width: 126px;
border: none;
}
.el-input__prefix {
display: none;
}
}
}
</style>
更多推荐
所有评论(0)