济菏高速业务端
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.
 
 
 
 
 

396 lines
11 KiB

<template>
<div class="bg" ref="ThumbnailRef"></div>
</template>
<script>
import { onceObserver } from "@screen/utils/resizeObserver";
import Vue from "vue";
import { Graph, Shape } from '@antv/x6'
import { debounce } from "lodash";
import { actualLocationList, canvasList } from "./data.js";
const mouseenterDebounceFunc = debounce(({ node }) => {
if (["singleNode-html", "multiNode-html"].indexOf(node.shape) >= 0) {
node.setZIndex(100);
console.log(node);
}
}, 0);
const mouseleaveDebounceFunc = debounce(({ node }) => {
if (["singleNode-html", "multiNode-html"].indexOf(node.shape) >= 0) {
node.setZIndex(1);
}
}, 0);
const clickDebounceFunc = debounce(({ node }) => {
const mapIns = Vue.prototype.mapIns;
if (["singleNode-html", "multiNode-html"].indexOf(node.shape) >= 0) {
const extData = node.getData()?.extData;
if (extData) {
mapIns.setZoomAndCenter(18, [extData.longitude, extData.latitude]);
}
}
}, 0);
function setFont(size, bold = "normal", family = "微软雅黑") {
return `${bold} ${size}px ${family}`;
}
let width, height;
const allActualDis = actualLocationList.reduce(
(count, item) => count + item.intervalDistance,
0
);
const rect = {
shape: "rect",
width: 0.1,
attrs: {
"body": {
stroke: "#37B5D4",
strokeWidth: 2,
strokeDasharray: '4, 7',
}
}
}
export default {
name: "Thumbnail",
data() {
return {
list: canvasList, //计算真实距离与画布距离的比例 *节点真实距离作为canvasItem.distance的值
translateX: 0,
translateY: 50,
allInstance: 0
};
},
mounted() {
this.mapInit();
// onceObserver.call(this, this.$refs.ThumbnailRef, () => {
// this.$refs.ThumbnailRef.innerHTML = null;
// this.translateX = 0,
// this.translateY = 50,
// this.allInstance = 0
// this.mapInit();
// });
},
methods: {
async mapInit() {
const content = this.$refs.ThumbnailRef;
width = content.clientWidth;
height = content.clientHeight;
const baseData = {
nodes: [
{
type: "text",
label: "G2001济南绕城高速",
x: 66,
y: height / 2 - 21,
attrs: {
text: {
fontSize: 12,
fill: "#ffffff",
}
}
},
{
type: "text",
label: "G3021德上高速",
x: width - 50,
y: height / 2 - 21,
attrs: {
text: {
fontSize: 12,
fill: "#ffffff",
}
}
},
{
type: "text",
label: "项目起点",
x: 270,
y: height / 2 - 50,
attrs: {
text: {
fontSize: 12,
fontFamily: "Arial Black",
fontWeight: 900,
fontStyle: "italic",
fill: "#ddc85a",
}
}
},
{
type: "text",
label: "K55+378.7",
x: 270,
y: height / 2 - 33,
attrs: {
text: {
fontSize: 12,
fontFamily: "Arial Black",
fontWeight: 900,
fontStyle: "italic",
fill: "#ddc85a",
}
}
},
{
type: "text",
label: "项目终点",
x: width - 220,
y: height / 2 - 50,
attrs: {
text: {
fontSize: 12,
fontFamily: "Arial Black",
fontWeight: 900,
fontStyle: "italic",
fill: "#ddc85a",
}
}
},
{
type: "text",
label: "K208+153.4",
x: width - 220,
y: height / 2 - 33,
attrs: {
text: {
fontSize: 12,
fontFamily: "Arial Black",
fontWeight: 900,
fontStyle: "italic",
fill: "#ddc85a",
}
}
},
],
};
const graph = new Graph({
container: content,
width,
height,
background: {
image: require("./images/bg.png"),
size: "100% 100%"
},
interacting: function (cellView) {
if (true) return { nodeMovable: false }
// return true;
},
});
graph.on('node:mouseenter', mouseenterDebounceFunc);
graph.on('node:mouseleave', mouseleaveDebounceFunc);
graph.on('node:click', clickDebounceFunc);
Shape.HTML.register({
shape: 'singleNode-html',
width: 160,
height: 80,
html(node) {
const data = node.getData();
const { height, width } = node.prop().size;
const div = document.createElement('div')
div.innerHTML = `
<div style="
background-image: url(${data.nowBg});
background-size: 100% 100%;
background-repeat: no-repeat;
width: ${width * 1.2}px;
height: ${height * 1.2}px;
display: flex;
justify-content: center;
">
<img style="
width: ${width * 0.8}px;
height: ${height * 0.8}px;
margin-top: ${height * 0.1}px;
" src='${data.src}'
>
</div>
`;
return div
},
})
Shape.HTML.register({
shape: 'multiNode-html',
width: 160,
height: 80,
html(node) {
const data = node.getData();
const { height, width } = node.prop().size;
const div = document.createElement('div')
div.innerHTML = `
<div style="
background-image: url(${data.nowBg});
background-size: 100% 100%;
background-repeat: no-repeat;
display: flex;
justify-content: center;
align-items: center;
padding-bottom: ${height * 0.1}px;
">
${data.length}
</div>
`;
return div
},
})
window.graphInstance = graph;
baseData.nodes.forEach(node => {
graph.addNode(node)
});
this.drawCongestionAreas(graph, 1404, 80);
const ratio = ((width - width * 0.08 * 2) / allActualDis); //减去俩侧空白区域 才是画布要计算的比例
window.canvasRatio = ratio;
window.canvasWidth = width;
this.list.forEach(item => this.allInstance += item.distance);
for (let index in this.list) {
const info = this.list[index];
info.distance = actualLocationList[index].intervalDistance * ratio;
await this.drawTag(info, graph);
}
//文字覆盖问题修复
graph.getCellById("K79+010").translate(-10, 0)
graph.getCellById("K83+885").translate(-10, 0);
graph.getCellById("K86+499").translate(10, 0);
graph.getCellById("K114+405").translate(-10, 0);
graph.getCellById("K117+878").translate(10, 0);
graph.getCellById("K159+156").translate(8, 0);
graph.getCellById("K155+652").translate(-10, 0);
graph.getCellById("K190+495").translate(10, 0);
},
async drayLine(text, graph, isFoot = false) {
const x = this.translateX + 141;
if (isFoot) {
graph.addNode({
...rect, x: x, y: 30, height: 161
});
} else {
graph.addNode({ ...rect, x: x, y: 30, height: 135, zIndex: 1 });
}
const textNode = {
label: text,
attrs: {
label: {
fontSize: 12,
fill: "#37B5D4",
fontWeight: 600
}
}
}
if (isFoot) {
graph.addNode({ ...textNode, x: x, y: 22 })
// graph.fillText(text, 0, 54);
// graph.translate(0, 226);
graph.addNode({ ...textNode, x: x, y: 195 });
} else {
graph.addNode({ ...textNode, x: x, y: 22 });
}
},
async drawTag(info, graph) {
this.translateX += info.distance;
let type = "3";
if (info.name.indexOf("枢纽") !== -1) {
type = "0";
} else if (info.name.indexOf("服务区") !== -1) {
type = "2";
} else if (info.name.indexOf("停车区") !== -1) {
type = "1";
}
if (type === "0") {
await this.drayLine(info.line, graph, info.isFoot);
if (info.name === "东平湖枢纽") {
const r = -150;
const nodeLine = graph.addNode({ ...rect, shape: 'rect', x: 1205, y: 2, height: 85, zIndex: 1 });
nodeLine.rotate((r * Math.PI));
graph.addNode({
label: "S33济徐高速", x: 1275, y: 22, attrs: {
label: {
fontSize: 12,
fill: "#37B5D4",
fontWeight: 600
}
}
});
}
}
let y = 42 - (info.name.length - 5) * 10;
const imageNode = graph.addNode({
shape: 'image', imageUrl: require(`./images/${info.icon || `tag${type}`}.png`), x: this.translateX, y: this.translateY, width: 21, height: 117
});
imageNode.translate(width * 0.07, 0);
for (var i = 0; i < info.name.length; i++) {
const imageLabelNode = graph.addNode({ label: info.name[i], x: this.translateX, y: i * 15, attrs: { text: { fill: "#ffffff", fontSize: 12 } } });
imageLabelNode.translate(width * 0.0755, 50 + y);
}
// 修改文字位置
const buttomLabelNode = graph.addNode({ label: info.code, x: this.translateX, y: 175, attrs: { text: { fill: "#ffffff", fontSize: 10.5 } }, id: info.code });
buttomLabelNode.translate(width * 0.0755, 0);
},
loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.setAttribute("crossOrigin", "anonymous");
img.src = url;
img.onload = () => {
// 当图像加载完成后进行resolve
resolve(img);
};
img.onerror = () => {
reject(new Error("图像加载失败"));
};
});
},
drawCongestionAreas(graph, x, y) {
// x = translateX * -1 + x;
// y = translateY * -1 + y;
const rectWidth = 160;
const rectHeight = 8;
graph.addNode({
...rect, x: x - 50, y: y, width: rectWidth, height: rectHeight, attrs: {
body: {
fill: {
type: 'linearGradient',
stops: [
{ offset: '0%', color: 'rgba(217,50,8,0)' },
{ offset: '27%', color: '#D73208' },
{ offset: '42%', color: '#D93208' },
{ offset: '81%', color: '#F5FF83' },
{ offset: '100%', color: 'rgba(215,50,8,0)' },
],
},
strokeWidth: 0
}
}
});
}
},
};
</script>
<style scoped lang="less">
.bg {
height: 100%;
width: 100%;
}
</style>