123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- <template>
- <div class="blastDelta">
- <div style="text-align: center; margin-top: -20px"> 平均值 </div>
- <div ref="coord" class="coords">
- <div class="coord-lineY">
- <div :style="{ width: '5px', height: `${lengY}px`, 'border-top': '1px solid #0079ff' }" v-for="item in 10" :key="item"></div>
- </div>
- <div class="coord-labelY">
- <div :style="{ width: '20px', height: `${lengY}px`, color: '#fff' }" v-for="(ite, ind) in 10" :key="ind">{{ ind == 0 ? maxY : '' }}</div>
- </div>
- <div class="coord-lineX">
- <div :style="{ height: '5px', width: `${lengY}px`, 'border-right': '1px solid #0079ff' }" v-for="item in 15" :key="item"></div>
- </div>
- <div class="coord-labelX">
- <div :style="{ height: '20px', width: `${lengY}px`, color: '#fff' }" v-for="(ite, ind) in 15" :key="ind">{{ ind == 14 ? maxX : '' }}</div>
- </div>
- <div class="line-AB" :style="{ width: 'calc(100% - 10px)', height: 'calc(100% - 10px)' }">
- <canvas id="myCanvas" :width="canvasSize.width" :height="canvasSize.height"></canvas>
- </div>
- <!-- <div class="line-legend">
- <div class="legend-ite" v-for="ite in 4" :key="ite"></div>
- </div>
- <div class="legend-name">
- <div class="item-name" v-for="item in legendList" :key="item">{{ item.name }}</div>
- </div> -->
- </div>
- <div class="line-legend">
- <div class="legend-box" v-for="(item, index) in legendList" :key="index">
- <span class="legend-icon"></span>
- <span class="legend-label">{{ item.name }}</span>
- </div>
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import { ref, reactive, onMounted, watch, nextTick } from 'vue';
- let props = defineProps({
- posMonitor: {
- type: Object,
- default: () => {
- return {};
- },
- },
- canvasSize: {
- type: Object,
- default: () => {
- return { width: 380, height: 245 };
- },
- },
- });
- let coord = ref(null);
- let lengY = ref(0);
- //与x,y轴相交最大值坐标
- let maxY = ref(0);
- let maxX = ref(0);
- let maxY1 = ref(0);
- let maxX1 = ref(0);
- //A点坐标
- let coordinateA = reactive({
- x: 0,
- y: 0,
- });
- //B点坐标
- let coordinateB = reactive({
- x: 0,
- y: 0,
- });
- //E点坐标
- let coordinateE = reactive({
- x: 0,
- y: 0,
- });
- //F点坐标
- let coordinateF = reactive({
- x: 0,
- y: 0,
- });
- //G点坐标
- let coordinateG = reactive({
- x: 0,
- y: 0,
- });
- let legendList = ref<any[]>([{ name: '不爆炸' }, { name: '可燃气体不足' }, { name: '可爆炸' }, { name: '氧气不足' }]);
- function getAreas() {
- if (coord.value) {
- let width = coord.value.offsetWidth;
- let height = coord.value.offsetHeight;
- lengY.value = Math.ceil((height - 10) / 10);
- }
- }
- //根据A,B,E,G等点坐标绘制爆炸三角形
- function getBlast() {
- maxY.value = getCoordABY(0);
- // 获取canvas元素
- let canvas = document.getElementById('myCanvas');
- let ctx = canvas.getContext('2d');
- let scalcY, scalcX;
- if (coordinateB.x < 50) {
- maxX.value = 50;
- scalcY = canvas.height / maxY.value;
- scalcX = canvas.width / maxX.value;
- } else {
- maxX.value = parseInt(coordinateB.x + 10);
- scalcY = canvas.height / maxY.value;
- scalcX = canvas.width / maxX.value;
- }
- //绘制AB点线条
- ctx.beginPath();
- ctx.moveTo(coordinateA.x * scalcX, canvas.height - coordinateA.y * scalcY); // 开始绘制的点
- ctx.lineTo(coordinateB.x * scalcX, canvas.height - coordinateB.y * scalcY); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- //绘制AE线条
- ctx.beginPath();
- ctx.moveTo(coordinateA.x * scalcX, canvas.height - coordinateA.y * scalcY); // 开始绘制的点
- ctx.lineTo(coordinateE.x * scalcX, canvas.height - coordinateE.y * scalcY); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- //绘制BE线条
- ctx.beginPath();
- ctx.moveTo(coordinateB.x * scalcX, canvas.height - coordinateB.y * scalcY); // 开始绘制的点
- ctx.lineTo(coordinateE.x * scalcX, canvas.height - coordinateE.y * scalcY); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- //绘制A点与坐标轴连线
- ctx.beginPath();
- ctx.moveTo(0, canvas.height - maxY.value * scalcY); // 开始绘制的点
- ctx.lineTo(coordinateA.x * scalcX, canvas.height - coordinateA.y * scalcY); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- //绘制B点c连线
- ctx.beginPath();
- ctx.moveTo(coordinateB.x * scalcX, canvas.height - coordinateB.y * scalcY); // 开始绘制的点
- ctx.lineTo(maxX.value * scalcX, canvas.height - getCoordABY(maxX.value) * scalcY); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- //绘制c点与坐标轴连线
- ctx.beginPath();
- ctx.moveTo(maxX.value * scalcX, canvas.height - getCoordABY(maxX.value) * scalcY); // 开始绘制的点
- ctx.lineTo(maxX.value * scalcX, canvas.height); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- //绘制E,F线条
- ctx.beginPath();
- ctx.moveTo(coordinateE.x * scalcX, canvas.height - coordinateE.y * scalcY); // 开始绘制的点
- ctx.lineTo(coordinateF.x * scalcX, canvas.height - coordinateF.y * scalcY); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- //绘制GE线条
- ctx.beginPath();
- ctx.moveTo(coordinateG.x * scalcX, canvas.height - coordinateG.y * scalcY); // 开始绘制的点
- ctx.lineTo(coordinateE.x * scalcX, canvas.height - coordinateE.y * scalcY); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- let pointData = [
- {
- arr: [
- { x: coordinateG.x * scalcX, y: canvas.height - coordinateG.y * scalcY }, //G
- { x: coordinateE.x * scalcX, y: canvas.height - coordinateE.y * scalcY }, //E
- { x: coordinateA.x * scalcX, y: canvas.height - coordinateA.y * scalcY }, //A
- { x: 0, y: canvas.height - maxY.value * scalcY },
- ],
- color: 'rgb(1, 127, 2, .9)',
- },
- {
- arr: [
- { x: 0, y: canvas.height }, //原点
- { x: coordinateF.x * scalcX, y: canvas.height - coordinateF.y * scalcY }, //F
- { x: coordinateE.x * scalcX, y: canvas.height - coordinateE.y * scalcY }, //E
- { x: coordinateG.x * scalcX, y: canvas.height - coordinateG.y * scalcY }, //G
- ],
- color: 'rgb(127, 254, 2, .9)',
- },
- {
- arr: [
- { x: coordinateF.x * scalcX, y: canvas.height - coordinateF.y * scalcY }, //F
- { x: maxX.value * scalcX, y: canvas.height },
- { x: maxX.value * scalcX, y: canvas.height - getCoordABY(maxX.value) * scalcY },
- { x: coordinateB.x * scalcX, y: canvas.height - coordinateB.y * scalcY }, //B
- { x: coordinateE.x * scalcX, y: canvas.height - coordinateE.y * scalcY }, //E
- ],
- color: 'rgb(255, 255, 0, .9)',
- },
- {
- arr: [
- { x: coordinateE.x * scalcX, y: canvas.height - coordinateE.y * scalcY }, //E
- { x: coordinateB.x * scalcX, y: canvas.height - coordinateB.y * scalcY }, //B
- { x: coordinateA.x * scalcX, y: canvas.height - coordinateA.y * scalcY }, //A
- ],
- color: 'rgb(255, 0, 0, .9)',
- },
- ];
- pointData.forEach((item, index) => {
- ctx.beginPath();
- ctx.moveTo(item.arr[0].x, item.arr[0].y);
- item.arr.forEach((items, ind) => {
- if (ind != 0) {
- ctx.lineTo(item.arr[ind].x, item.arr[ind].y);
- }
- });
- ctx.closePath();
- ctx.fillStyle = item.color;
- ctx.fill();
- ctx.strokeStyle = 'transparent';
- ctx.lineWidth = 1;
- ctx.stroke();
- });
- // 标记点A
- ctx.beginPath();
- ctx.arc(coordinateA.x * scalcX, canvas.height - coordinateA.y * scalcY, 1, 0, 2 * Math.PI);
- ctx.fillStyle = '#eee';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('A', coordinateA.x * scalcX + 10, canvas.height - coordinateA.y * scalcY); // 文字位置略微偏上,以便于文字与点对齐
- //标记点B
- ctx.beginPath();
- ctx.arc(coordinateB.x * scalcX, canvas.height - coordinateB.y * scalcY, 1, 0, 2 * Math.PI);
- ctx.fillStyle = '#eee';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('B', coordinateB.x * scalcX + 10, canvas.height - coordinateB.y * scalcY); // 文字位置略微偏上,以便于文字与点对齐
- //标记点E
- ctx.beginPath();
- ctx.arc(coordinateE.x * scalcX, canvas.height - coordinateE.y * scalcY, 1, 0, 2 * Math.PI);
- ctx.fillStyle = '#eee';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('E', coordinateE.x * scalcX + 5, canvas.height - coordinateE.y * scalcY + 10); // 文字位置略微偏上,以便于文字与点对齐
- //标记点G
- ctx.beginPath();
- ctx.arc(coordinateG.x * scalcX, canvas.height - coordinateG.y * scalcY, 1, 0, 2 * Math.PI);
- ctx.fillStyle = '#eee';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('G', coordinateG.x * scalcX + 5, canvas.height - coordinateG.y * scalcY); // 文字位置略微偏上,以便于文字与点对齐
- //标记点F
- ctx.beginPath();
- ctx.arc(coordinateF.x * scalcX, canvas.height - coordinateF.y * scalcY, 1, 0, 2 * Math.PI);
- ctx.fillStyle = '#eee';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('F', coordinateF.x * scalcX + 10, canvas.height - coordinateF.y * scalcY - 10); // 文字位置略微偏上,以便于文字与点对齐
- //标记点
- ctx.beginPath();
- ctx.arc(maxX1.value * scalcX, canvas.height - maxY1.value * scalcY, 5, 0, 2 * Math.PI);
- ctx.fillStyle = 'blue';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('', maxX1.value * scalcX + 10, canvas.height - maxY1.value * scalcY - 10); // 文字位置略微偏上,以便于文字与点对齐
- }
- //绘制不爆炸三角形
- function getUnblast() {
- maxY.value = 21;
- maxX.value = 50;
- // 获取canvas元素
- let canvas = document.getElementById('myCanvas');
- let ctx = canvas.getContext('2d');
- let scalcY = canvas.height / maxY.value;
- let scalcX = canvas.width / maxX.value;
- //绘制AB点线条
- ctx.beginPath();
- ctx.moveTo(0, canvas.height - maxY.value * scalcY); // 开始绘制的点
- ctx.lineTo(maxX.value * scalcX, canvas.height); // 结束绘制的点
- ctx.strokeStyle = '#000';
- ctx.stroke(); // 进行绘制
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- let pointData = [
- {
- arr: [
- { x: 0, y: canvas.height }, //原点
- { x: 0, y: canvas.height - maxY.value * scalcY }, //A
- { x: maxX.value * scalcX, y: canvas.height }, //B
- ],
- color: 'rgb(127, 254, 2, .9)',
- },
- ];
- pointData.forEach((item, index) => {
- ctx.beginPath();
- ctx.moveTo(item.arr[0].x, item.arr[0].y);
- item.arr.forEach((items, ind) => {
- if (ind != 0) {
- ctx.lineTo(item.arr[ind].x, item.arr[ind].y);
- }
- });
- ctx.closePath();
- ctx.fillStyle = item.color;
- ctx.fill();
- ctx.strokeStyle = 'transparent';
- ctx.lineWidth = 1;
- ctx.stroke();
- });
- // 标记点A
- ctx.beginPath();
- ctx.arc(0, canvas.height - maxY.value * scalcY, 1, 0, 2 * Math.PI);
- ctx.fillStyle = '#eee';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('A', 10, canvas.height - maxY.value * scalcY + 10); // 文字位置略微偏上,以便于文字与点对齐
- // 标记点B
- ctx.beginPath();
- ctx.arc(maxX.value * scalcX, canvas.height, 1, 0, 2 * Math.PI);
- ctx.fillStyle = '#eee';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('B', maxX.value * scalcX - 10, canvas.height - 10); // 文字位置略微偏上,以便于文字与点对齐
- //标记点
- ctx.beginPath();
- ctx.arc(maxX1.value * scalcX, canvas.height - maxY1.value * scalcY, 5, 0, 2 * Math.PI);
- ctx.fillStyle = 'blue';
- ctx.fill();
- // 在点附近添加文字
- ctx.font = '12px Arial';
- ctx.fillStyle = '#fff';
- ctx.fillText('', maxX1.value * scalcX + 10, canvas.height - maxY1.value * scalcY - 10); // 文字位置略微偏上,以便于文字与点对齐
- }
- //根据横坐标获取直线AB纵坐标
- function getCoordABY(params) {
- return Math.ceil(
- ((parseFloat(coordinateB.y) - parseFloat(coordinateA.y)) * params -
- parseFloat(coordinateA.x) * parseFloat(coordinateB.y) +
- parseFloat(coordinateB.x) * parseFloat(coordinateA.y)) /
- (parseFloat(coordinateB.x) - parseFloat(coordinateA.x))
- );
- }
- //根据纵坐标获取直线AB横坐标
- function getCoordABX(params1) {
- return Math.floor(
- ((parseFloat(coordinateB.x) - parseFloat(coordinateA.x)) * params1 +
- parseFloat(coordinateA.x) * parseFloat(coordinateB.y) -
- parseFloat(coordinateB.x) * parseFloat(coordinateA.y)) /
- (parseFloat(coordinateB.y) - parseFloat(coordinateA.y))
- );
- }
- watch(
- () => props.posMonitor,
- (newV, oldV) => {
- if (newV.btTriBlast) {
- maxY1.value = parseFloat(newV.o2_ave);
- maxX1.value =
- parseFloat(newV.co_ave) * 0.0001 + parseFloat(newV.ch4_ave) + parseFloat(newV.c2h2_ave) * 0.0001 + parseFloat(newV.c4h4_ave) * 0.0001;
- console.log(maxX1.value, 'maxX1');
- let btTriBlasts = newV.btTriBlast;
- coordinateA.x = btTriBlasts.A_x;
- coordinateA.y = btTriBlasts.A_y;
- coordinateB.x = btTriBlasts.B_x;
- coordinateB.y = btTriBlasts.B_y;
- coordinateE.x = btTriBlasts.E_x;
- coordinateE.y = btTriBlasts.E_y;
- coordinateF.x = btTriBlasts.F_x;
- coordinateF.y = btTriBlasts.F_y;
- coordinateG.x = btTriBlasts.G_x;
- coordinateG.y = btTriBlasts.G_y;
- if (
- !((coordinateA.y - coordinateB.y) / (coordinateA.x - coordinateB.x)) ||
- (coordinateA.y - coordinateB.y) / (coordinateA.x - coordinateB.x) == 1
- ) {
- // 使用 nextTick 为了让 immediate watch 触发时等待组件挂载后执行绘制
- nextTick(getUnblast);
- } else {
- nextTick(getBlast);
- }
- }
- },
- { deep: true, immediate: true }
- );
- onMounted(() => {
- getAreas();
- });
- </script>
- <style lang="less" scoped>
- .blastDelta {
- position: relative;
- width: 100%;
- height: 320px;
- .line-legend {
- position: absolute;
- left: 50%;
- top: 20px;
- width: 75%;
- height: 20px;
- transform: translate(-50%, 0);
- display: flex;
- justify-content: space-around;
- .legend-box {
- display: flex;
- height: 100%;
- justify-content: center;
- align-items: center;
- font-size: 12px;
- &:nth-child(1) {
- flex: 1;
- .legend-icon {
- width: 10px;
- height: 10px;
- background-color: #7ffe02;
- margin-right: 5px;
- }
- }
- &:nth-child(2) {
- flex: 1.5;
- .legend-icon {
- width: 10px;
- height: 10px;
- background-color: #017f02;
- margin-right: 5px;
- }
- }
- &:nth-child(3) {
- flex: 1;
- .legend-icon {
- width: 10px;
- height: 10px;
- background-color: #ff0000;
- margin-right: 5px;
- }
- }
- &:nth-child(4) {
- flex: 1;
- .legend-icon {
- width: 10px;
- height: 10px;
- background-color: #ffff00;
- margin-right: 5px;
- }
- }
- }
- }
- .coords {
- position: absolute;
- left: 50%;
- top: 50%;
- width: 90%;
- height: 80%;
- border-left: 1px solid #006c9d;
- border-bottom: 1px solid #006c9d;
- transform: translate(-45%, -46%);
- .coord-lineY {
- position: absolute;
- left: -5px;
- top: 10px;
- width: 5px;
- height: calc(100% - 10px);
- }
- .coord-labelY {
- position: absolute;
- left: -25px;
- top: -5px;
- width: 20px;
- height: 100%;
- }
- .coord-lineX {
- display: flex;
- position: absolute;
- bottom: -5px;
- right: 10px;
- width: calc(100% - 10px);
- height: 5px;
- }
- .coord-labelX {
- display: flex;
- justify-content: flex-end;
- position: absolute;
- bottom: -25px;
- left: -5px;
- width: 100%;
- height: 20px;
- }
- .line-AB {
- position: absolute;
- left: 0;
- top: 10px;
- }
- // .legend-name {
- // position: absolute;
- // right: 0;
- // top: 20px;
- // height: 80px;
- // .item-name {
- // height: 20px;
- // line-height: 20px;
- // font-size: 10px;
- // color: #fff;
- // letter-spacing: 2px;
- // }
- // }
- }
- }
- </style>
|