|
|
@ -5,16 +5,18 @@ |
|
|
|
</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 = (_data , _lowLimit , _upLimit) => { |
|
|
|
if(_data.length<=0){ |
|
|
|
const open = (ztData) => { |
|
|
|
if(ztData.length<=0){ |
|
|
|
dialogVisible.value = false |
|
|
|
}else{ |
|
|
|
initData(_data , _lowLimit , _upLimit) |
|
|
|
console.info(JSON.stringify(ztData)) |
|
|
|
initData(ztData) |
|
|
|
dialogVisible.value = true |
|
|
|
} |
|
|
|
} |
|
|
@ -30,26 +32,52 @@ function func(x, u, a) { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
const initData = async (data , xMin , xMax) => { |
|
|
|
var mean = math.mean(data) //平均值 计算方法来自math.js |
|
|
|
var stdev = math.std(data) //方差 |
|
|
|
var threeSigUp = mean + 3 * stdev |
|
|
|
var threeSigLow = mean - 3 * stdev |
|
|
|
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) |
|
|
|
|
|
|
|
const resNum = await getResNum(data) |
|
|
|
const xArr = await getXArr(resNum) |
|
|
|
const fArr = await getFArr(xArr , resNum) |
|
|
|
const yArr = await getYArr(xMax , xMin , mean , stdev) |
|
|
|
var threeSigUp1 = Number(avgX) + (2 * sigma) |
|
|
|
var threeSigLow1 = Number(avgX) - (2 * sigma) |
|
|
|
|
|
|
|
setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) |
|
|
|
} |
|
|
|
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) => { |
|
|
|
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; |
|
|
@ -59,7 +87,7 @@ const getResNum = async (datas) => { |
|
|
|
|
|
|
|
return resNum |
|
|
|
} |
|
|
|
|
|
|
|
//获取横坐标 |
|
|
|
const getXArr = async (resNum) => { |
|
|
|
var xArr = [] //横坐标值 |
|
|
|
for (var k in resNum) { |
|
|
@ -70,30 +98,61 @@ const getXArr = async (resNum) => { |
|
|
|
}) |
|
|
|
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 (xMax , xMin , mean , stdev) => { |
|
|
|
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 < xMax - distance / 4; j += 0.01) { |
|
|
|
var xy = [j, func(j, mean, stdev)] |
|
|
|
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) { |
|
|
|
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", |
|
|
@ -108,19 +167,19 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
} |
|
|
|
}, |
|
|
|
legend: { |
|
|
|
orient: "vertical", |
|
|
|
// orient: "vertical", |
|
|
|
x: "right", |
|
|
|
y: "top", |
|
|
|
top: "5px", |
|
|
|
data: ["频数", "正态分布"], |
|
|
|
data: [ "正态分布","频数"], |
|
|
|
textStyle: { |
|
|
|
color: "rgba(255,255,255,1)", |
|
|
|
color: "green", |
|
|
|
fontSize: "12" |
|
|
|
} |
|
|
|
}, |
|
|
|
grid: { |
|
|
|
left: "2%", |
|
|
|
top: "18px", |
|
|
|
top: "45px", |
|
|
|
right: "2%", |
|
|
|
bottom: "2%", |
|
|
|
containLabel: true |
|
|
@ -128,8 +187,8 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
xAxis: [ |
|
|
|
{ |
|
|
|
type: "value", |
|
|
|
min: xMin, |
|
|
|
max: xMax, |
|
|
|
min: minX.toFixed(2), |
|
|
|
max: maxX.toFixed(2), |
|
|
|
axisLabel: { |
|
|
|
textStyle: { |
|
|
|
color: '#000000', |
|
|
@ -150,7 +209,7 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
yAxis: [ |
|
|
|
{ |
|
|
|
type: "value", //数值轴 |
|
|
|
name: "正态曲线", |
|
|
|
name: "正态分布", |
|
|
|
position: "right", |
|
|
|
axisTick: { show: true }, |
|
|
|
axisLine: { |
|
|
@ -227,7 +286,7 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
markLine: { |
|
|
|
symbol: ["none"], |
|
|
|
lineStyle: { |
|
|
|
type: "dotted", |
|
|
|
type: "solid", |
|
|
|
color: "yellow" |
|
|
|
}, |
|
|
|
itemStyle: { |
|
|
@ -242,30 +301,72 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
}, |
|
|
|
data: [ |
|
|
|
{ |
|
|
|
name: "3σ", |
|
|
|
name: "3S", |
|
|
|
xAxis: threeSigLow.toFixed(2), |
|
|
|
label: { |
|
|
|
show: true, |
|
|
|
formatter: "3σ" |
|
|
|
formatter: "-3S" |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "3σ", |
|
|
|
name: "3S", |
|
|
|
xAxis: threeSigUp.toFixed(2), |
|
|
|
label: { |
|
|
|
show: true, |
|
|
|
formatter: "3σ" |
|
|
|
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: 1, |
|
|
|
yAxisIndex: 0, |
|
|
|
xAxisIndex: 0, |
|
|
|
barWidth: 8, |
|
|
|
barWidth: 24, |
|
|
|
barGap: 1, |
|
|
|
symbol: "solid", |
|
|
|
symbolSize: 5, |
|
|
@ -279,7 +380,7 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
}, |
|
|
|
data: fArr, |
|
|
|
markLine: { |
|
|
|
symbol: ["none"], |
|
|
|
symbol: ["circle","arrow"], |
|
|
|
lineStyle: { |
|
|
|
type: "dotted", |
|
|
|
color: "red" |
|
|
@ -300,7 +401,7 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
xAxis: xMin.toFixed(2), |
|
|
|
label: { |
|
|
|
show: true, |
|
|
|
formatter: "Low" |
|
|
|
formatter: '下限'+xMin.toFixed(2) |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
@ -308,7 +409,7 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
xAxis: xMax.toFixed(2), |
|
|
|
label: { |
|
|
|
show: true, |
|
|
|
formatter: "High" |
|
|
|
formatter: '上限:'+xMax.toFixed(2) |
|
|
|
} |
|
|
|
} |
|
|
|
] |
|
|
@ -327,6 +428,109 @@ function setEchartData(xMin , xMax , yArr , fArr , threeSigLow , threeSigUp) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染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); |
|
|
|