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.
539 lines
12 KiB
539 lines
12 KiB
<template>
|
|
<div v-if="dialogVisible">
|
|
<div id="ztEcharts" style="width: 80vw; height: 300px"></div>
|
|
</div>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import * as echarts from 'echarts'
|
|
import { number } from 'vue-types'
|
|
import * as math from './ztmath'
|
|
|
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
|
|
|
/** 打开弹窗 */
|
|
const open = (ztData) => {
|
|
if(ztData.length<=0){
|
|
dialogVisible.value = false
|
|
}else{
|
|
console.info(JSON.stringify(ztData))
|
|
initData(ztData)
|
|
dialogVisible.value = true
|
|
}
|
|
}
|
|
|
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
|
|
|
|
function func(x, u, a) {
|
|
return (
|
|
(1 / Math.sqrt(2 * Math.PI)) *
|
|
a *
|
|
Math.exp((-1 * ((x - u) * (x - u))) / (2 * a * a))
|
|
);
|
|
}
|
|
|
|
function pdf(x, mu, sigma) {
|
|
return (1 / (Math.sqrt(2 * Math.PI) * sigma)) * Math.exp(-0.5 * ((x - mu) / sigma) ** 2);
|
|
}
|
|
const initData = async (ztData) => {
|
|
let data = ztData.ztMap.datas;
|
|
let xMax = ztData.ztMap.upLimit;
|
|
let xMin = ztData.ztMap.downLimit;
|
|
let sigma = ztData.ztMap.sigma;
|
|
let stdev = ztData.ztMap.stdev;
|
|
let avgX = ztData.ztMap.avgX;
|
|
let max = ztData.ztMap.max;//这个是范围内柱状图最大数值用于绑定频率曲线与柱状图的高度
|
|
//let mean = math.mean(data) //平均值 计算方法来自math.js
|
|
var threeSigUp = Number(avgX) + (3 * sigma)
|
|
var threeSigLow = Number(avgX) - (3 * sigma)
|
|
|
|
var threeSigUp1 = Number(avgX) + (2 * sigma)
|
|
var threeSigLow1 = Number(avgX) - (2 * sigma)
|
|
|
|
var threeSigUp2 = Number(avgX) + (1 * sigma)
|
|
var threeSigLow2 = Number(avgX) - (1 * sigma)
|
|
let maxX = xMax;
|
|
if(Number(threeSigUp)>Number(xMax)){
|
|
maxX = threeSigUp;
|
|
}
|
|
|
|
const resNum = await getResNum(data)//取出相同的数
|
|
const xArr = await getXArr(resNum)//取出横坐标X的值
|
|
//const fArr = await getFArr(xArr , resNum)//分布数量Y值
|
|
let fArr = ztData.ztMap.fArr
|
|
|
|
let pingjun = func(avgX, avgX, stdev);//平均点的频率用来强制绑定与柱状图的关系
|
|
const yArr = await getYArr(maxX,xMax , xMin , avgX , stdev,pingjun,max)
|
|
console.info("resNum",JSON.stringify(resNum));
|
|
console.info("xArr",JSON.stringify(xArr));
|
|
console.info("fArr",JSON.stringify(fArr));
|
|
console.info("yArr",JSON.stringify(yArr));
|
|
|
|
setEchartData(xMin , xMax , yArr , fArr,threeSigLow , threeSigUp,threeSigUp1,threeSigLow1,threeSigUp2,threeSigLow2,avgX)
|
|
}
|
|
//获取每个区间出现的数量
|
|
const getResNum = async (datas) => {
|
|
var resNum = {}
|
|
const dataSec = datas.sort((a, b) => {//排序
|
|
return a - b;
|
|
})
|
|
console.info("dataSec",JSON.stringify(dataSec));
|
|
for (var m = 0; m < dataSec.length; m++) {
|
|
var key = parseFloat(dataSec[m]);
|
|
if (parseFloat(key + '') === 0) continue;
|
|
if (resNum[key]) resNum[key] += 1
|
|
else resNum[key] = 1
|
|
}
|
|
|
|
return resNum
|
|
}
|
|
//获取横坐标
|
|
const getXArr = async (resNum) => {
|
|
var xArr = [] //横坐标值
|
|
for (var k in resNum) {
|
|
xArr.push(parseFloat(k))
|
|
}
|
|
xArr = xArr.sort((a, b) => {
|
|
return a - b;
|
|
})
|
|
return xArr
|
|
}
|
|
//拼装数组[[0.99, 109]]
|
|
const getFArr = async (xArr , resNum) => {
|
|
var fArr = [] //频数
|
|
//计算x值对应的频数
|
|
for (var i = 0; i < xArr.length; i++) {
|
|
var xNy = [xArr[i], resNum[xArr[i]]]
|
|
//var xNy = resNum[xArr[i]]
|
|
fArr.push(xNy)
|
|
}
|
|
return fArr
|
|
}
|
|
|
|
const getYArr = async (maxX,xMax , xMin , mean , stdev,pingjun,max:number) => {
|
|
debugger
|
|
var yArr = [] //正态值
|
|
let jj = 0.01;//描频率分布点的步长
|
|
let jian = maxX-xMin;
|
|
//计算x值对应的正态分布值
|
|
if(jian>0){
|
|
jj = 0.01;
|
|
}
|
|
else if(jian>=2){
|
|
jj = 0.02
|
|
}else if(jian>=5){
|
|
jj = 0.05
|
|
}else if(jian>=10){
|
|
jj = 0.1
|
|
}else if(jian>=20){
|
|
jj = 0.5
|
|
}else{
|
|
jj = 1
|
|
}
|
|
let beishu =Math.floor((max+25)/(Number(pingjun)));//为了更好看把曲线出现频率与范围内有多少数的柱状图强行绑定在一起,(最大柱状图数+42)/平均值时的正态分布频率 当做每个正态分布的倍数,这样能保证曲线总是在柱状图的最上面
|
|
var distance = xMax - xMin //为了更好看,设置正态曲线起止位置
|
|
for (var j = xMin + distance / 4; j < maxX-distance / 4; j += jj) {
|
|
//for (var j = xMin + distance / 4; j < xMax-distance / 4; j += 0.01) {
|
|
var xy = [j, func(j, mean, stdev)*beishu]
|
|
//var xy = [j, pdf(j, mean, stdev)]
|
|
yArr.push(xy)
|
|
}
|
|
return yArr
|
|
}
|
|
|
|
// 渲染echarts图表
|
|
function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp,threeSigUp1,threeSigLow1,threeSigUp2,threeSigLow2,avgX) {
|
|
let avgXs = avgX;
|
|
let maxX = xMax;
|
|
let minX = xMin;
|
|
if(Number(threeSigUp)>Number(maxX)){
|
|
maxX = threeSigUp;
|
|
}
|
|
|
|
if(Number(threeSigLow)<Number(minX)){
|
|
minX = threeSigLow;
|
|
}
|
|
var dom = document.getElementById("ztEcharts")
|
|
var myChart = echarts.init(dom, null, {
|
|
renderer: "canvas",
|
|
useDirtyRect: false
|
|
})
|
|
var option = {
|
|
//backgroundColor: "#12141e",
|
|
tooltip: {
|
|
trigger: "axis",
|
|
axisPointer: {
|
|
type: "shadow"
|
|
}
|
|
},
|
|
legend: {
|
|
// orient: "vertical",
|
|
x: "right",
|
|
y: "top",
|
|
top: "5px",
|
|
data: [ "正态分布","频数"],
|
|
textStyle: {
|
|
color: "green",
|
|
fontSize: "12"
|
|
}
|
|
},
|
|
grid: {
|
|
left: "2%",
|
|
top: "45px",
|
|
right: "2%",
|
|
bottom: "2%",
|
|
containLabel: true
|
|
},
|
|
xAxis: [
|
|
{
|
|
type: "value",
|
|
min: minX.toFixed(2),
|
|
max: maxX.toFixed(2),
|
|
axisLabel: {
|
|
textStyle: {
|
|
color: '#000000',
|
|
fontSize: 10
|
|
}
|
|
},
|
|
axisLine: {
|
|
show: true,
|
|
lineStyle: {
|
|
color: "#000000"
|
|
}
|
|
},
|
|
splitLine: {
|
|
show: false
|
|
}
|
|
}
|
|
],
|
|
yAxis: [
|
|
{
|
|
type: "value", //数值轴
|
|
name: "正态分布",
|
|
position: "right",
|
|
axisTick: { show: true },
|
|
axisLine: {
|
|
show: false,
|
|
lineStyle: {
|
|
color: "#000000"
|
|
}
|
|
},
|
|
axisLabel: {
|
|
show: true,
|
|
textStyle: {
|
|
color: " #6B8E23",
|
|
fontSize: 10
|
|
}
|
|
},
|
|
splitLine: {
|
|
show: false
|
|
}
|
|
},
|
|
{
|
|
type: "value",
|
|
name: "频数",
|
|
position: "left",
|
|
axisLabel: {
|
|
//formatter: '{value} %'
|
|
show: true,
|
|
textStyle: {
|
|
color: "rgba(255,255,255,1)",
|
|
fontSize: "12"
|
|
}
|
|
},
|
|
axisTick: {
|
|
show: true
|
|
},
|
|
axisLine: {
|
|
show: true,
|
|
lineStyle: {
|
|
color: "rgba(0,0,0,.1)",
|
|
width: 1,
|
|
type: "solid"
|
|
}
|
|
},
|
|
splitLine: {
|
|
lineStyle: {
|
|
color: "rgba(255,255,255,.3)"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
series: [
|
|
{
|
|
name: "正态分布",
|
|
type: "line",
|
|
smooth: true,
|
|
yAxisIndex: 0,
|
|
symbol: "circle",
|
|
symbolSize: 5,
|
|
showSymbol: false,
|
|
lineStyle: {
|
|
normal: {
|
|
color: "#ceb664",
|
|
width: 2
|
|
}
|
|
},
|
|
|
|
itemStyle: {
|
|
normal: {
|
|
color: "#ceb664",
|
|
borderColor: "rgba(221, 220, 107, .1)",
|
|
borderWidth: 10
|
|
}
|
|
},
|
|
data: yArr,
|
|
markLine: {
|
|
symbol: ["none"],
|
|
lineStyle: {
|
|
type: "solid",
|
|
color: "yellow"
|
|
},
|
|
itemStyle: {
|
|
normal: {
|
|
show: true,
|
|
color: "black"
|
|
}
|
|
},
|
|
label: {
|
|
show: true,
|
|
position: "end"
|
|
},
|
|
data: [
|
|
{
|
|
name: "3S",
|
|
xAxis: threeSigLow.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: "-3S"
|
|
}
|
|
},
|
|
{
|
|
name: "3S",
|
|
xAxis: threeSigUp.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: "+3S"
|
|
}
|
|
},
|
|
{
|
|
name: "2S",
|
|
xAxis: threeSigLow1.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: "-2S"
|
|
}
|
|
},
|
|
{
|
|
name: "2S",
|
|
xAxis: threeSigUp1.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: "+2S"
|
|
}
|
|
},
|
|
{
|
|
name: "1S",
|
|
xAxis: threeSigLow2.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: "-1S"
|
|
}
|
|
},
|
|
{
|
|
name: "1S",
|
|
xAxis: threeSigUp2.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: "+1S"
|
|
}
|
|
}
|
|
,
|
|
{
|
|
name: "1S",
|
|
xAxis: avgXs,
|
|
label: {
|
|
show: true,
|
|
formatter: "平均:"+avgXs
|
|
}
|
|
}
|
|
|
|
]
|
|
}
|
|
},
|
|
{
|
|
name: "频数",
|
|
type: "bar",
|
|
yAxisIndex: 0,
|
|
xAxisIndex: 0,
|
|
barWidth: 24,
|
|
barGap: 1,
|
|
symbol: "solid",
|
|
symbolSize: 5,
|
|
showSymbol: true,
|
|
itemStyle: {
|
|
normal: {
|
|
color: "#0184d5",
|
|
opacity: 1,
|
|
barBorderRadius: 3
|
|
}
|
|
},
|
|
data: fArr,
|
|
markLine: {
|
|
symbol: ["circle","arrow"],
|
|
lineStyle: {
|
|
type: "dotted",
|
|
color: "red"
|
|
},
|
|
itemStyle: {
|
|
normal: {
|
|
show: true,
|
|
color: "black"
|
|
}
|
|
},
|
|
label: {
|
|
show: true,
|
|
position: "middle"
|
|
},
|
|
data: [
|
|
{
|
|
name: "LowLimit",
|
|
xAxis: xMin.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: '下限'+xMin.toFixed(2)
|
|
}
|
|
},
|
|
{
|
|
name: "High",
|
|
xAxis: xMax.toFixed(2),
|
|
label: {
|
|
show: true,
|
|
formatter: '上限:'+xMax.toFixed(2)
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
if (option && typeof option === "object") {
|
|
myChart.setOption(option)
|
|
}
|
|
|
|
window.onresize = function () {
|
|
//自适应大小
|
|
myChart.resize()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染echarts图表
|
|
function setEchartData1(xMin , xMax , yArr , fArr,xArr , threeSigLow , threeSigUp) {
|
|
var dom = document.getElementById("ztEcharts")
|
|
var myChart = echarts.init(dom, null, {
|
|
renderer: "canvas",
|
|
useDirtyRect: false
|
|
})
|
|
var option = {
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
axisPointer: {
|
|
type: 'cross',
|
|
crossStyle: {
|
|
color: '#999'
|
|
}
|
|
}
|
|
},
|
|
toolbox: {
|
|
feature: {
|
|
dataView: { show: true, readOnly: false },
|
|
magicType: { show: true, type: ['line', 'bar'] },
|
|
restore: { show: true },
|
|
saveAsImage: { show: true }
|
|
}
|
|
},
|
|
legend: {
|
|
data: ['Evaporation', 'Precipitation', 'Temperature']
|
|
},
|
|
xAxis: [
|
|
{
|
|
type: 'category',
|
|
data: xArr,
|
|
axisPointer: {
|
|
type: 'shadow'
|
|
}
|
|
}
|
|
],
|
|
yAxis: [
|
|
{
|
|
type: 'value',
|
|
name: 'Precipitation',
|
|
min: 0,
|
|
max: 250,
|
|
interval: 50,
|
|
axisLabel: {
|
|
formatter: '{value} ml'
|
|
}
|
|
},
|
|
{
|
|
type: 'value',
|
|
name: 'Temperature',
|
|
min: 0,
|
|
max: 25,
|
|
interval: 5,
|
|
axisLabel: {
|
|
formatter: '{value} °C'
|
|
}
|
|
}
|
|
],
|
|
series: [
|
|
{
|
|
name: 'Evaporation',
|
|
type: 'bar',
|
|
tooltip: {
|
|
valueFormatter: function (value) {
|
|
return value + ' ml';
|
|
}
|
|
},
|
|
data: fArr
|
|
},
|
|
{
|
|
name: 'Temperature',
|
|
type: 'line',
|
|
yAxisIndex: 1,
|
|
tooltip: {
|
|
valueFormatter: function (value) {
|
|
return value + ' °C';
|
|
}
|
|
},
|
|
data: yArr
|
|
}
|
|
]
|
|
};
|
|
|
|
if (option && typeof option === "object") {
|
|
myChart.setOption(option)
|
|
}
|
|
|
|
window.onresize = function () {
|
|
//自适应大小
|
|
myChart.resize()
|
|
}
|
|
}
|
|
|
|
|
|
onMounted(() => {
|
|
// const script = document.createElement('script');
|
|
// script.setAttribute('src', math);
|
|
// document.head.appendChild(script);
|
|
})
|
|
</script>
|