vue引用antv/g6树图(左右分布)
antv/g6左右分布树图
·
创作背景:要做到自定义左右分布的树图,并且添加删除按钮,echarts已经不能满足条件,因此选择antV/g6树图,在此记录
成品展示:
完整代码如下:
1、首先在index.html引入资源
<script src="https://gw.alipayobjects.com/os/lib/antv/g6/4.3.2/dist/g6.min.js">
2、g6Tree.vue组件代码
<template>
<div>
<div id="container" :style="{ height: '400px', width: '100%' }" />
</div>
</template>
<script>
export default {
data() {
return {
graph: undefined,
};
},
props:{
treedata:{
type:Object
}
},
watch:{
"treedata":{
handler:function(cur,old){
if(cur != old){
this.refresh();
}
},
deep:true, //对象内部的属性监听,也叫深度监听
// immediate:true
}
},
mounted() {
this.$nextTick(()=>{
if(this.treedata.downstreamName){
this.showChart(this.treedata);
this.$forceUpdate()
}
})
},
methods: {
refresh() {
if (this.graph){
//销毁方法
this.graph.destroy();
}
//重新实例化
this.showChart();
this.$forceUpdate()
},
showChart() {
//为了更明显的展示颜色 配色不好看 别介意哈
const that = this
G6.registerNode(
"tree-node",
{
drawShape: function drawShape(cfg, group) {
const rect = group.addShape("rect", {
// 节点框样式
attrs: {
fill: "blue",//节点框蓝色背景色
// stroke: "red",
x: 0,
y: 0,
width: 1,
height: 1,
radius: [12],
},
name: "rect-shape",
});
//upriverName代表节点上游,downstreamName代表节点下游(后端的数据就是这样,所以我 这样写)其实不分上下游直接用name也是可以的
const content = cfg.downstreamName||cfg.upriverName;
const text = group.addShape("text", {
// 节点文字样式
attrs: {
text: content,
x: 0,
y: 0,
textAlign: "left",
textBaseline: "middle",
fill: "white",//节点框内白色文字
},
name: "text-shape",
});
const bbox = text.getBBox();
const hasChildren = cfg.children && cfg.children.length > 0;
rect.attr({
x:-20,
y:-15,
width:170, //节点框的宽度
height:27,
textAlign:"left"
});
// 文字的位置
text.attr({
// x: -bbox.width / 2 + 15,
// y: 2,
x: 0,
y:0,
});
// 展开折叠图标样式
if (hasChildren) {
group.addShape("marker", {
attrs: {
// x: bbox.width / 2 + 24,
// y: 0,
x: 150,
y: 0,
r: 6,
symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
stroke: "#fff",
fill: "green",//绿色删除按钮
lineWidth: 1,
},
name: "collapse-icon",
});
}
// 加一个删除按钮
const deleImage = group.addShape('image', {
attrs: {
x: -15,
y: bbox.height / 2 -13,
img: cfg.fixed?'':require('@/assets/image/dele.jpeg'),
width: bbox.height,
height: bbox.height,
cursor: 'pointer'
},
name: 'deleteItem'
})
return rect;
},
update: (cfg, item) => {
const group = item.getContainer();
const icon = group.find((e) => e.get("name") === "collapse-icon");
icon.attr(
"symbol",
cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse
);
},
},
"single-node"
);
const container = document.getElementById("container");
const width = container.scrollWidth;
const height = container.scrollHeight || 500;
const graph = new G6.TreeGraph({
container: "container",
width,
height,
modes: {
default: [
{
type: "collapse-expand",
onChange: function onChange(item, collapsed) {
const data = item.get("model");
graph.updateItem(item, {
collapsed,
});
data.collapsed = collapsed;
return true;
},
},
"drag-canvas",
"zoom-canvas",
],
},
defaultNode: {
type: "tree-node",
anchorPoints: [
[0, 0.5],
[1, 0.5],
],
},
// 节点连接线样式
defaultEdge: {
type: "cubic-horizontal",
style: {
stroke: "#9fb1f8",
},
},
layout: {
type: "compactBox",
direction: "H",
// 判断节点向左展开还是向右展开
getSide: (d) => {
if (d.data.direction == 'right') {
return 'right';
}
return 'left';
},
getId: function getId(d) {
return d.id+"";
},
getHeight: function getHeight() {
return 16;
},
// 节点框和线的宽度
getWidth: function getWidth() {
return 70;
},
getVGap: function getVGap() {
return 20;
},
getHGap: function getHGap() {
return 60;
},
},
});
this.graph = graph
graph.on('deleteItem:click',(ev)=>{
const node = ev.item
const data= node.getModel()
that.$confirm('是否确认删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if(data.downstreamTable){
this.$emit("deleteBlood",data.id)
}else{
this.$emit("deleteBlood",data.id)
}
}).catch(() => {
that.$message({
type: 'info',
message: '已取消删除'
});
});
})
graph.data(this.treedata);
graph.render();
graph.fitCenter();
// graph.fitView();
if (typeof window !== "undefined")
window.onresize = () => {
if (!graph || graph.get("destroyed")) return;
if (!container || !container.scrollWidth || !container.scrollHeight)
return;
graph.changeSize(container.scrollWidth, container.scrollHeight);
};
},
},
};
</script>
<style scoped>
#nodeDetails {
list-style: none;
background-color: blue;
}
#nodeDetails > li {
padding: 5px 0;
text-align: left;
background-color: #ebeefd;
}
::v-deep .g6-component-tooltip {
background-color: #ccc;
}
.nodeClass {
padding: 10px;
}
</style>
3、父组件引用
<template>
<div>
<G6Tree v-if="treedata.downstreamName" :treedata="treedata" @deleteBlood='deleteBlood'></G6Tree>
</div>
</template>
<script>
import G6Tree from "@/components/antV/G6Tree.vue";
export default {
components: {
G6Tree,
},
data() {
return {
treedata: {},
};
},
mounted(){
this.getTree()
},
methods: {
// 获取树节点
getTree() {
//调用获取节点的接口
//数据中id必须为字符串类型,
this.treedata={
downstreamName: "中心节点",
upriverName: "中心节点",
fixed: true, //是否固定 (固定则不显示删除按钮)
children: [
{
id: "1",
upriverName: "节点1",
direction: "right",//展示在中心节点的左边或者右边
children: [
{
id: "2",
upriverName: "节点1-1",
direction: "right",
children:[]
},
{
id: "3",
upriverName: "节点1-2",
direction: "right",
children:[]
},
],
},
{
id: "4",
upriverName: "节点2",
direction: "right",
children: [
{
id: "5",
upriverName: "节点2-1",
direction: "right",
children:[]
},
{
id: "6",
upriverName: "节点2-2",
direction: "right",
children:[]
},
],
},
{
id: "7",
downstreamName: "节点3",
direction: "left",
children: [
{
id: "8",
downstreamName: "节点3-1",
direction: "left",
children:[]
},
{
id: "9",
downstreamName: "节点3-2",
direction: "left",
children:[]
},
],
},
{
id: "10",
downstreamName: "节点4",
direction: "left",
children: [
{
id: "11",
downstreamName: "节点4-1",
direction: "left",
children: [
{
id: "12",
downstreamName: "节点4-1-1",
direction: "left",
children:[]
},
{
id: "13",
downstreamName: "节点4-1-2",
direction: "left",
children:[]
},
],
},
],
},
],
}
},
// 删除节点
deleteTreeNode(id) {
const param = { id:id }
//调用删除接口
api.deleteTreeNode(param)
.then((res) => {
if (res.data && res.data.code == 200) {
this.msgSuccess("删除节点成功");
}
})
.catch((err) => {
this.$message.error(err);
console.log(err);
});
},
},
};
</script>
更多推荐
已为社区贡献2条内容
所有评论(0)