|
|
@@ -1,18 +1,506 @@
|
|
|
<template>
|
|
|
-<div>{{msg}}</div>
|
|
|
+ <el-container>
|
|
|
+ <el-header>
|
|
|
+ <el-row>
|
|
|
+ startVertex:
|
|
|
+ <el-select v-model="startVertex" placeholder="">
|
|
|
+ <el-option
|
|
|
+ v-for="item in startVertexOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ <el-button
|
|
|
+ @click="run"
|
|
|
+ type="primary"
|
|
|
+ >
|
|
|
+ run
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ @click="newGraph"
|
|
|
+ type="primary"
|
|
|
+ >
|
|
|
+ new Graph
|
|
|
+ </el-button>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <p>access sequence:{{sequence}}</p>
|
|
|
+ </el-row>
|
|
|
+ </el-header>
|
|
|
+
|
|
|
+ <div id="echarts1"></div>
|
|
|
+
|
|
|
+ </el-container>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import * as echarts from 'echarts';
|
|
|
+import {newUDUWGraph,graphDepthFirstTraversal} from '../api.js';
|
|
|
+import qs from 'qs'
|
|
|
export default {
|
|
|
name: 'graphDepthFirstTraversal',
|
|
|
data () {
|
|
|
return {
|
|
|
- msg: 'Welcome to Your graphDepthFirstTraversal'
|
|
|
+ msg: 'Welcome to Your graphDepthFirstTraversal',
|
|
|
+ sequence:"",
|
|
|
+ startVertex:"",
|
|
|
+ startVertexOptions:[
|
|
|
+ {
|
|
|
+ value:0,
|
|
|
+ label:0
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value:1,
|
|
|
+ label:1
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value:2,
|
|
|
+ label:2
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value:3,
|
|
|
+ label:3
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value:4,
|
|
|
+ label:4
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value:5,
|
|
|
+ value:5
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value:6,
|
|
|
+ label:6
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ timer:null,
|
|
|
+ //echarts配置项
|
|
|
+ links: [], //边的属性设置
|
|
|
+ nodeData:[
|
|
|
+ {
|
|
|
+ name: "0",
|
|
|
+ x: 600,
|
|
|
+ y: -600,
|
|
|
+ fixed:true,
|
|
|
+ // itemStyle:{ //设置节点样式
|
|
|
+ // borderColor:"black",
|
|
|
+ // borderWidth:4
|
|
|
+ // }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "1",
|
|
|
+ x: 1000,
|
|
|
+ y: 500,
|
|
|
+ //fixed:true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "2",
|
|
|
+ x: 500,
|
|
|
+ y: 500,
|
|
|
+ //fixed:true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "3",
|
|
|
+ x: 200,
|
|
|
+ y: 300,
|
|
|
+ //fixed:true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "4",
|
|
|
+ x: 400,
|
|
|
+ y: 300,
|
|
|
+ //fixed:true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "5",
|
|
|
+ x: 200,
|
|
|
+ y: 100,
|
|
|
+ //fixed:true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "6",
|
|
|
+ x: 400,
|
|
|
+ y: 100,
|
|
|
+ //fixed:true
|
|
|
+ },
|
|
|
+ ] //节点的属性设置
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ $route(n, o) {
|
|
|
+ clearInterval(this.timer);
|
|
|
+ this.newGraph();
|
|
|
+ },
|
|
|
+ },
|
|
|
+ computed:{
|
|
|
+ options(){
|
|
|
+ let that=this;
|
|
|
+ let option={
|
|
|
+ tooltip: {},
|
|
|
+ animationDurationUpdate: 1500,
|
|
|
+ animationEasingUpdate: "quinticInOut",
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: "graph",
|
|
|
+ layout: "circular",
|
|
|
+ symbolSize: 50,
|
|
|
+ roam: false,
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ },
|
|
|
+ edgeSymbol: ["circle"],
|
|
|
+ edgeSymbolSize: [4, 10],
|
|
|
+ edgeLabel: {
|
|
|
+ fontSize: 20,
|
|
|
+ },
|
|
|
+ data:that.nodeData, //节点配置
|
|
|
+ links: that.links, //边配置
|
|
|
+ lineStyle: {
|
|
|
+ opacity: 0.9,
|
|
|
+ width: 2,
|
|
|
+ curveness: 0,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ return option;
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.newGraph();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ methods:{
|
|
|
+ newGraph(){
|
|
|
+ //在下一次newGraph之前,将所有的节点和边的样式初始化一下。
|
|
|
+ //初始化访问序列
|
|
|
+ this.sequence="";
|
|
|
+ //初始化节点样式
|
|
|
+ for(var m=0;m<7;m++){
|
|
|
+ this.nodeData[m].itemStyle={};
|
|
|
+ }
|
|
|
+ newUDUWGraph().then((res) => {
|
|
|
+ console.log("changeGraph res: "+res.data.content);
|
|
|
+ this.links = [];
|
|
|
+ let arr = res.data.content.content;
|
|
|
+ this.content = res.data.content;//这是一个图
|
|
|
+ console.log("this.content:"+this.content.content[3][6]);
|
|
|
+ arr.forEach((v, index) => {
|
|
|
+ v.forEach((el, i) => { //一条边有两条连线
|
|
|
+ if (index != i) {
|
|
|
+ if (arr[index][i] == 1&&index<i) { //去掉重复边
|
|
|
+ //links配置项
|
|
|
+ this.links.push({
|
|
|
+ source: index,
|
|
|
+ target: i,
|
|
|
+ symbol:["circle"],
|
|
|
+ // label:{ //设置label
|
|
|
+ // normal:{
|
|
|
+ // show:true,
|
|
|
+ // formatter:"test"
|
|
|
+ // }
|
|
|
+ // },
|
|
|
+ // lineStyle:{ //边的颜色设置
|
|
|
+ // color:"green",
|
|
|
+ // }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // if (arr[i][index] == 1) {
|
|
|
+ // this.links.push({
|
|
|
+ // source: i,
|
|
|
+ // target: index,
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ this.initEcharts();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ run() {
|
|
|
+ if (this.startVertex === "") {
|
|
|
+ this.$notify.error({
|
|
|
+ title: "error",
|
|
|
+ message: "Please select start vertex.",
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //在下一次run之前,将所有的节点和边的样式初始化一下。
|
|
|
+ //初始化访问序列
|
|
|
+ this.sequence="";
|
|
|
+ //初始化节点样式
|
|
|
+ for(var m=0;m<7;m++){
|
|
|
+ this.nodeData[m].itemStyle={};
|
|
|
+ }
|
|
|
+ //初始化边样式
|
|
|
+ let refreshLinks=this.links.map(link=>{
|
|
|
+ var refreshlink=link;
|
|
|
+ refreshlink.lineStyle={};
|
|
|
+ return refreshlink;
|
|
|
+ })
|
|
|
+ this.links=refreshLinks;
|
|
|
+ //var graphStr=qs.stringify(...this.content, { arrayFormat: "indices" })
|
|
|
+ graphDepthFirstTraversal({
|
|
|
+ ...this.content,
|
|
|
+ startVertex: this.startVertex
|
|
|
+ }).then((res) => {
|
|
|
+ //console.log("breadth traversal response:"+res.data);
|
|
|
+ //clearInterval(this.timer);
|
|
|
+ let arr = res.data.content.content;
|
|
|
+ console.log("arr[0].start:"+arr[0].start);
|
|
|
+ let index = 0;
|
|
|
+ var formerVisitNode="";
|
|
|
+ var formerStyleLink={};
|
|
|
+ var visitedNum=0;
|
|
|
+ var tryFirst=true;
|
|
|
+ this.timer = setInterval(() => {
|
|
|
+ if (index != 0) {
|
|
|
+ // this.links.shift();
|
|
|
+ }
|
|
|
+ //每一步根据不同的类型和不同的结果设置不同的边和节点的样式
|
|
|
+ //var isReverse=false;
|
|
|
+ // var visitedNum=0;
|
|
|
+
|
|
|
+ var step=arr[index];//当前step
|
|
|
+ var isReverse=false;
|
|
|
+ var linkSource=step.start;
|
|
|
+ var linkTarget=step.end;
|
|
|
+ // var formerVisitNode=""; //前一个被访问的节点是哪一个?
|
|
|
+ if(step.start>step.end){
|
|
|
+ isReverse=true; //step的start end与边的source target是否一致
|
|
|
+ linkSource=step.end;
|
|
|
+ linkTarget=step.start;
|
|
|
+ }
|
|
|
+ //步骤类型如果为探路就设置边的样式,如果为访问就设置节点的样式
|
|
|
+ if(step.type=="tryRoad"){
|
|
|
+ console.log("======tryRoad====="+step.start+" "+step.end+"=========");
|
|
|
+ //第一次渲染
|
|
|
+ //遍历边,找到对应的边,设置,然后push
|
|
|
+ //第一次渲染
|
|
|
+ if(tryFirst==true){
|
|
|
+ console.log("************");
|
|
|
+ index--; //第二次渲染还访问这个数组
|
|
|
+ let newLinks=this.links.map(link=>{
|
|
|
+ if(link.source==linkSource&&link.target==linkTarget){ //如果是这条边
|
|
|
+ var newlink=link;
|
|
|
+ formerStyleLink=link; //将边原来的样式存起来,若探路失败,恢复成原来的状态。
|
|
|
+ //要对这条边做什么
|
|
|
+ //先尝试探路,将这条边设置为从起点指向终点的单箭头红色连线。
|
|
|
+ if(isReverse){ //如果起点终点反了
|
|
|
+ newlink={
|
|
|
+ source:link.source,
|
|
|
+ target:link.target,
|
|
|
+ symbol:["arrow","none"],
|
|
|
+ lineStyle:{
|
|
|
+ color:"red"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{//如果起点终点没有反
|
|
|
+ newlink={
|
|
|
+ source:link.source,
|
|
|
+ target:link.target,
|
|
|
+ symbol:["none","arrow"],
|
|
|
+ lineStyle:{
|
|
|
+ color:"red"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return newlink;
|
|
|
+ }
|
|
|
+ return link;
|
|
|
+ })
|
|
|
+ this.links=newLinks;
|
|
|
+ tryFirst=false;
|
|
|
+ }else{
|
|
|
+ tryFirst=true;//下面是下个数组的第一次访问
|
|
|
+ //第二次渲染
|
|
|
+ let relinks=this.links.map(link=>{
|
|
|
+ if(link.source==linkSource&&link.target==linkTarget){ //如果是这条边
|
|
|
+ var relink=link;
|
|
|
+ //要对这条边做什么
|
|
|
+ //先尝试探路,将这条边设置为从起点指向终点的单箭头红色连线。
|
|
|
+ if(step.success==true){ //探路成功
|
|
|
+ relink={
|
|
|
+ source:link.source,
|
|
|
+ target:link.target,
|
|
|
+ symbol:["none","none"],
|
|
|
+ lineStyle:{
|
|
|
+ color:"blue"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{//探路没成功
|
|
|
+ relink=formerStyleLink;
|
|
|
+ }
|
|
|
+ return relink;
|
|
|
+ }
|
|
|
+ return link;
|
|
|
+ })
|
|
|
+ this.links=relinks;
|
|
|
+ }
|
|
|
+
|
|
|
+ }else if(step.type=="visit"){
|
|
|
+ if(this.sequence===""){
|
|
|
+ this.sequence=step.end+"";
|
|
|
+ }else{
|
|
|
+ this.sequence=this.sequence+", "+step.end;
|
|
|
+ }
|
|
|
+ visitedNum++;
|
|
|
+ console.log("visitedNum"+visitedNum);
|
|
|
+ console.log("=========visit=========="+step.end+"=========");
|
|
|
+ if(formerVisitNode!==""){ //如果它不是第一个被访问的节点,那么它需要将前一个被访问的节点设置为已访问
|
|
|
+ this.nodeData[formerVisitNode].itemStyle={
|
|
|
+ color:"green" //已访问的节点为绿色
|
|
|
+ }
|
|
|
+ // itemStyle:{ //设置节点样式
|
|
|
+ // borderColor:"black",
|
|
|
+ // borderWidth:4
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ this.nodeData[step.end].itemStyle={
|
|
|
+ borderColor:"black",
|
|
|
+ borderWidth:4
|
|
|
+ }
|
|
|
+ formerVisitNode=step.end;
|
|
|
+ console.log("=======former visit node:"+step.end);
|
|
|
+ // if(visitedNum==7){ //如果所有的节点都访问过了,就不需要访问了。
|
|
|
+ // clearInterval(this.timer);
|
|
|
+ // this.nodeData[formerVisitNode].itemStyle={
|
|
|
+ // color:"green" //已访问的节点为绿色
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ }else if(step.type=="return"){
|
|
|
+ this.nodeData[formerVisitNode].itemStyle={
|
|
|
+ color:"green" //已访问的节点为绿色
|
|
|
+ }
|
|
|
+ this.nodeData[step.end].itemStyle={
|
|
|
+ borderColor:"black",
|
|
|
+ borderWidth:4,
|
|
|
+ color:"green"
|
|
|
+ }
|
|
|
+ formerVisitNode=step.end;
|
|
|
+ if(step.end==this.startVertex&&visitedNum==7){
|
|
|
+ clearInterval(this.timer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // this.links.unshift({
|
|
|
+ // source: arr[index].start,
|
|
|
+ // target: arr[index].end,
|
|
|
+ // symbolSize: [5, 20],
|
|
|
+ // lineStyle: {
|
|
|
+ // width: 2,
|
|
|
+ // curveness: 0.1,
|
|
|
+ // color: arr[index].success ? "green" : "red",
|
|
|
+ // },
|
|
|
+ // });
|
|
|
+ index++;
|
|
|
+ if(visitedNum<7&&index>=arr.length){
|
|
|
+ clearInterval(this.timer);
|
|
|
+ }
|
|
|
+ this.initEcharts();
|
|
|
+ }, 200);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ initEcharts() {
|
|
|
+ console.log("initEcharts");
|
|
|
+ var myChart = echarts.init(document.getElementById("echarts1"));
|
|
|
+ myChart.setOption(this.options);
|
|
|
+ // 绘制图表
|
|
|
+ // myChart.setOption({
|
|
|
+ // // title: {
|
|
|
+ // // text: "",
|
|
|
+ // // },
|
|
|
+ // tooltip: {},
|
|
|
+ // animationDurationUpdate: 1500,
|
|
|
+ // animationEasingUpdate: "quinticInOut",
|
|
|
+ // series: [
|
|
|
+ // {
|
|
|
+ // type: "graph",
|
|
|
+ // layout: "circular",
|
|
|
+ // symbolSize: 50,
|
|
|
+ // roam: false,
|
|
|
+ // label: {
|
|
|
+ // show: true,
|
|
|
+ // },
|
|
|
+ // edgeSymbol: ["circle"],
|
|
|
+ // edgeSymbolSize: [4, 10],
|
|
|
+ // edgeLabel: {
|
|
|
+ // fontSize: 20,
|
|
|
+ // },
|
|
|
+ // data: [
|
|
|
+ // {
|
|
|
+ // name: "0",
|
|
|
+ // x: 600,
|
|
|
+ // y: -600,
|
|
|
+ // fixed:true
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: "1",
|
|
|
+ // x: 1000,
|
|
|
+ // y: 500,
|
|
|
+ // //fixed:true
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: "2",
|
|
|
+ // x: 500,
|
|
|
+ // y: 500,
|
|
|
+ // //fixed:true
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: "3",
|
|
|
+ // x: 200,
|
|
|
+ // y: 300,
|
|
|
+ // //fixed:true
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: "4",
|
|
|
+ // x: 400,
|
|
|
+ // y: 300,
|
|
|
+ // //fixed:true
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: "5",
|
|
|
+ // x: 200,
|
|
|
+ // y: 100,
|
|
|
+ // //fixed:true
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // name: "6",
|
|
|
+ // x: 400,
|
|
|
+ // y: 100,
|
|
|
+ // //fixed:true
|
|
|
+ // },
|
|
|
+ // ],
|
|
|
+ // // links: [],
|
|
|
+ // links: this.links,
|
|
|
+ // lineStyle: {
|
|
|
+ // opacity: 0.9,
|
|
|
+ // width: 2,
|
|
|
+ // curveness: 0,
|
|
|
+ // },
|
|
|
+ // },
|
|
|
+ // ],
|
|
|
+ // });
|
|
|
+ },
|
|
|
+ },
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss">
|
|
|
-
|
|
|
+<style lang="scss" scoped>
|
|
|
+.p{
|
|
|
+ text-align: left;
|
|
|
+}
|
|
|
+#echarts1 {
|
|
|
+ position:relative;
|
|
|
+ left:10%;
|
|
|
+ width: 500px;
|
|
|
+ height: 500px;
|
|
|
+}
|
|
|
</style>
|