P-Ⅲ型曲线适线 前端导入xlsx文件计算 绘制echarts

81 阅读3分钟

效果如图

image.png

直接上代码

<template>  
<div class="curve">  
<div class="curve__header">  
<div class="curve__header__title">  
<input type="file" id="uploadExcel" multiple @change="handleChange"/>  
<a-button @click="draw">绘制</a-button>  
<a-button @click="exports">导出</a-button>  
<div class="fillIn">  
<div> <a-input v-model:value="echartsWidth" addon-before="宽度:" addon-after="px" placeholder="请输入"/></div>  
<div> <a-input v-model:value="echartsHeight" addon-before="高度:" addon-after="px" placeholder="请输入"/></div>  
<a-button @click="reset">重置</a-button>  
</div>  
</div>  
</div>  
<div class="curve__body" :style="{width:echartsWidth?echartsWidth+'px':'',height:echartsHeight? echartsHeight+'px':''}">  
<div class="curve__body__chart" id="Charts">  
</div>  
</div>  
</div>  
</template>  
  
<script setup>  
import {nextTick, onMounted, Ref, ref} from 'vue';  
import * as echarts from "echarts";  
import * as XLSX from "xlsx"  
  
let echartsImg=new Image()  
const echartsWidth=ref('1000')  
const echartsHeight=ref('800')  
const initChart = (datas) => {  
console.log(datas)  
let maxValue=0  
for (let i = 0; i < datas.length; i++) {  
for (let j = 0; j < datas[i].data2.length; j++) {  
if (maxValue < datas[i].data2[j][1]) {  
maxValue = datas[i].data2[j][1];  
}  
}  
}  
console.log(maxValue,'maxY')  
const chartDom = document.getElementById('Charts');  
echarts.dispose(chartDom);  
const myChart = echarts.init(chartDom);  
let colorList=['#1dadbf','#9cce40','#d837b7']  
let seriesData=[]  
datas?.forEach((v,i)=>{  
seriesData.push({  
data: v.data2,  
smooth: true,  
type: 'line',  
symbol: "none",  
lineStyle: {  
color: colorList[i]  
}  
})  
seriesData.push({  
data: v.data1,  
smooth: true,  
type: 'scatter',  
symbolSize: 5,  
itemStyle: {  
color: colorList[i]  
}  
})  
})  

//x轴对应频率
let data = [  

];  
const data1 = [  
]  
const data1X = [  
]  
const option = {  
animation: false,  
grid: { // 让图表占满容器  
top: "50px",  
left: "70px",  
right: "50px",  
bottom:"60px"  
},  
  
tooltip: {  
trigger: 'axis',  
formatter: (params) => {  
let result = '';  
// console.log(params,'params')  
for (let i = 0; i < params.length; i++) {  
if (params.length > 3) {  
if (i === 0) {  
result += '量:' + params[i]?.data[1] + '<br />';  
result += '率:' + params[i]?.data[2] + '%' + '<br />';  
}  
if (i === 1) {  
result += '量:' + params[i]?.data[1] + '<br />';  
result += '率:' + params[i]?.data[2] + '%' + '<br />';  
}  
} else {  
if (i === 0) {  
result += '量:' + params[i]?.data[1] + '<br />';  
result += '率:' + params[i]?.data[2] + '%' + '<br />';  
}  
}  
  
}  
return result;  
}  
},  
xAxis: {  
name:echartsXYName[1],  
nameTextStyle: { // y轴name的样式调整  
color: '#000',  
fontSize: 22,  
padding:[10,0,0,0] // 加上padding可以调整其位置  
},  
nameLocation: "center",  
min: 0,  
max: 7781,  
type: 'value',  
interval: 1,  
axisTick: {  
show: false  
},  
splitLine: {  
show: false  
},  
axisLabel: {  
show: true,  
formatter: (value) => {  
let arr = data1X.find((item) => item[0] == value) || [];  
return arr[2] ? arr[2] : '';  
},  
// rotate: -45,  
showMinLabel: true,  
showMaxLabel: true,  
fontSize:16  
},  
axisLine: {  
lineStyle: {  
color: '#000',  
}  
},  
},  
yAxis: {  
name:echartsXYName[0],  
nameTextStyle: { // y轴name的样式调整  
color: '#000',  
fontSize: 22,  
},  
type: 'value',  
axisTick: {  
show: false  
},  
max: (roundedUp(maxValue.toFixed(0))).toFixed(0),  
min: 0,  
splitNumber: 10,  
splitLine: {  
show: true,  
lineStyle: {  
color: ['#000'],  
width: 1,  
type: 'solid'  
}  
},  
axisLine: {  
lineStyle: {  
color: '#000',  
}  
},  
axisLabel: {  
fontSize:16  
}  
},  
series: [  
{  
name:'网格',  
data: dataX1.map((item) => {  
let arr = [...item];  
arr[1] = (roundedUp(maxValue.toFixed(0))).toFixed(0);  
return arr;  
}),  
type: 'bar',  
barWidth: 1,  
cursor: 'auto',  
itemStyle: {  
normal: {  
color: '#000'  
},  
emphasis: {  
color: '#000'  
}  
},  
animation: false,  
tooltip: {  
show: false  
}  
},  
...seriesData  
]  
};  
  
window.addEventListener('resize', function () {  
myChart.resize();  
});  
myChart.setOption(option);  
echartsImg.src=myChart.getDataURL({  
// backgroundColor: "#fff",  
type: "png",  
})  
}  
  
const echartsData = new Map()  
const handleChange = info => {  
let fileList = info.target.files;  
console.log(fileList)  
if (fileList) {  
let reader = new FileReader();  
let file = fileList[0];  
reader.readAsBinaryString(file)  
reader.addEventListener("load", function (e) {  
console.log(e);//FileReader实例对象  
let data = e.target?.result; //读取成功后result中的数据  
let wb = XLSX.read(data, {type: 'binary'});//以base64方法读取 结果  
console.log(wb,'wb')  
wb.SheetNames.length && wb.SheetNames.forEach((v, index) => {  
let sheets = wb.Sheets[v]  
// //将数据解析为json字符串  
let dataList2 = JSON.stringify(XLSX.utils.sheet_to_json(sheets))  
let dataList3 = (JSON.parse(dataList2))  
echartsData.set(v, dataList3)  
})  
})  
}  
};  
  
const echartsXYName=[]  
const getEchartsData = (key) => {  
let data = echartsData.get(key)  
let data1 = []  
let data2 = []  
data.forEach((v, i) => {  
if (i !== 0) {  
const a = 1 - (Number(v['经验历史数据'])) / 100  
let c = Number(normsinv(a).toFixed(3))  
let b = (Number(3.891 - c)*1000).toFixed(0)  
let v1=[b,v['__EMPTY'],v['经验历史数据'].toString()]  
data1.push(v1)  
if(v['理论数据']){  
const a = 1 - (Number(v['理论数据'])) / 100  
let c = Number(normsinv(a).toFixed(3))  
let b = (Number(3.891 - c)*1000).toFixed(0)  
let v1=[b,v['__EMPTY_1'],v['理论数据'].toString()]  
data2.push(v1)  
}  
}else{  
echartsXYName[0]=(v['__EMPTY'])  
echartsXYName[1]=(v['经验历史数据'])  
}  
})  
return {data1,data2}  
}  
const echartsData1 = ref([])  
const draw = () => {  
for(let key of echartsData.keys()){  
const data= getEchartsData(key)  
echartsData1.value.push(data)  
}  
nextTick(() => {  
initChart(echartsData1.value)  
})  
}  
  
const exports = () => {  
let canvas = document.createElement("canvas");  
canvas.width = echartsImg.width;  
canvas.height = echartsImg.height;  
console.log(canvas.width , canvas.height)  
let ctx = canvas.getContext("2d");  
ctx.fillStyle = '#fff';  
ctx?.fillRect(0, 0, canvas.width, canvas.height);  
ctx?.drawImage(echartsImg, 0, 0);  
let dataURL = canvas.toDataURL("image/png");  
let a = document.createElement("a");  
let event = new MouseEvent("click");  
a.download = "echarts.png";  
a.href = dataURL;  
a.dispatchEvent(event);  
a.remove();  
}  
  
const reset = () => {  
echartsWidth.value=''  
echartsHeight.value=''  
console.log(echartsHeight.value,echartsWidth.value)  
draw()  
}  
  
const roundedUp=(num)=>{  
if (typeof num !== 'number') {  
num = parseFloat(num);  
}  
if(num<100){  
return 100  
}else{  
let a  
a=(num/100).toFixed(0)  
let b=Number(a)+1  
return (b)*100;  
}  
}  
  
function normsinv(p) {  
  //计算公式 
}  
  
  
onMounted(() => {  
nextTick(() => {  
// initChart()  
})  
})  
  
  
</script>  
<style scoped lang="less">  
.curve {  
width: 100%;  
height: 100%;  
background-color: #fff;  
}  
  
.curve__header {  
width: 100%;  
height: 60px;  
background-color: #fff;  
border-bottom: 1px solid #e8e8e8;  
display: flex;  
align-items: center;  
justify-content: space-between;  
padding: 0 20px;  
box-sizing: border-box;  
}  
  
.curve__header__title {  
font-size: 20px;  
font-weight: 500;  
color: #333;  
display: flex;  
align-items: center;  
.fillIn{  
margin-left: 20px;  
display: flex;  
width: 500px;  
align-items: center;  
justify-content: space-between;  
font-size: 14px;  
>div{  
width: 40%;  
display: flex;  
align-items: center;  
}  
}  
}  
  
.curve__body {  
width: 100%;  
height: calc(100% - 60px);  
background-color: #fff;  
padding: 20px;  
box-sizing: border-box;  
}  
  
.curve__body__chart {  
width: 100%;  
height: 100%;  
background-color: #fff;  
}  
</style>