g-chart-component
Version:
自定义图表插件
823 lines (778 loc) • 24.5 kB
JavaScript
import * as d3 from "d3";
const TreeList = (data, loadAPiData, setMsg, waterText) => {
const target = document.getElementById("treeListBox");
const svgId = 'treeListBox';
var width = target ? target.clientWidth : '100%';
const height = target ? target.clientHeight : '100%';
var guquanTupu;
var rootData;
var barHeight = 50;
var barWidth = width;
var nodes;
var _rootD;
getDataTupu();
function getDataTupu() {
rootData = {
name: data.rootName,
children: data.children
};
addFlag(rootData);
guquanTupu = new drawGuquanTupu(rootData);
}
function drawGuquanTupu(rootData) {
var i = 0;
var duration = 400;
var container;
var isExtent = false;
var scale = 1;
var diagonal,tree, treeRoot;
d3.select("#" + svgId).selectAll("*").remove();
var svg = d3.select("#" + svgId).append("svg").attr("xmlns", "http://www.w3.org/2000/svg");
initSvg();
update(rootData);
function dragmove() {
var x = parseInt(container.attr("transform").split(',')[0].split('(')[1]);
var y = parseInt(container.attr("transform").split(',')[1].split(')')[0]);
var transform = d3.zoomTransform(event.target);
container.attr("transform", "translate(" + (x + transform.x) + "," + (y + transform.y) + ") scale(" + scale + ")");
}
function initSvg() {
svg.selectAll("*").remove();
svg.attr("width", width);
svg.attr("height", height);
svg.attr("class", "svgBox");
container = svg.append("g");
var zoom = d3.drag().on("drag", dragmove);
svg.call(zoom);
container.attr("transform", "translate(5,60)");
container.attr("id", "gbox");
}
function update(source) {
rootData.x0 = 0;
rootData.y0 = 0;
tree = d3.tree().nodeSize([0, 20]);
diagonal = function (d) {
return "M" + d.source.y + "," + d.source.x
+ "C" + (d.source.y + d.target.y) / 2 + "," + d.source.x
+ " " + (d.source.y + d.target.y) / 2 + "," + d.target.x
+ " " + d.target.y + "," + d.target.x;
}
treeRoot = d3.hierarchy(rootData);
tree(treeRoot);
nodes = treeRoot.descendants();
var nodeX = 0;
nodes.forEach(function (n, i) {
n.x = nodeX;
nodeX += n.data.height + 5;
});
svg.attr("height", Math.max(590, nodeX + 160));
var height = Math.max(500, nodeX);
d3.select("svg").transition()
.duration(duration);
d3.select(self.frameElement).transition()
.duration(duration)
.style("height", height + "px");
// Update the nodes…
var node = container.selectAll("g.node")
.data(nodes, function (d) {
return d.id || (d.id = ++i);
});
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.style("opacity", 1);
// Enter any new nodes at the parent's previous position.
nodeEnter.append("rect")
.attr("y", function (d) {
if (d.depth == 0) {
return -d.data.height / 2
} else {
return -15;
}
})
.attr("height", function (d) {
return d.data.height
})
.attr("width", function(d){
if(d.depth == 0){
return barWidth-20
}else{
return barWidth-30
}
})
.style("stroke", "#999999")
.attr("fill", "#ffffff")
.attr('fill-opacity', 0)
.attr("stroke-width", 0.5)
.on("click", click);
nodeEnter.append("rect")
.attr("y", function (d) {
if (d.depth == 0) {
return -d.data.height / 2
} else {
return -15;
}
})
.attr("height", function (d) {
return d.data.height
})
.attr("width", 5)
.style("fill", color)
.style("fill-opacity", 1)
.on("click", click);
nodeEnter.append("text")
.attr("dy", 3.5)
.attr("dx", 30.5)
.text(function (d) {
if (d.data.name && d.data.name.length > 24) {
return d.data.name.substr(0, 23) + '…';
} else {
return d.data.name;
}
})
.attr("fill", "#333333")
.style("font-size", "12px")
.style("font-weight", "bold")
.on("click", click);
nodeEnter.each(function (d) {
if (d.data.sign1) {
d3.select(this).append("rect")
.attr("x", 30)
.attr("y", 13)
.attr("rx", 2)
.attr("ry", 2)
.attr("height", 20)
.attr("width", 44)
.attr("fill", "#FE485E")
.attr('fill-opacity', 0.08)
.attr("stroke-width", 0.5);
d3.select(this).append("text")
.attr("dx", 35)
.attr("dy", 27)
.attr("fill", "#fe485e")
.style("font-size", "11px")
.text(d=> d.data.sign1);
if (d.data.sign2) {
d3.select(this).append("rect")
.attr("x", 84)
.attr("y", 13)
.attr("rx", 2)
.attr("ry", 2)
.attr("height", 20)
.attr("width", 66)
.attr("fill", "#EEA324")
.attr('fill-opacity', 0.08)
.attr("stroke-width", 0.5);
d3.select(this).append("text")
.attr("dx", 89)
.attr("dy", 27)
.attr("fill", "#EEA324")
.style("font-size", "11px")
.text(d => d.data.sign2);
if (d.data.sign3) {
d3.select(this).append("rect")
.attr("x", 160)
.attr("y", 13)
.attr("rx", 2)
.attr("ry", 2)
.attr("height", 20)
.attr("width", 66)
.attr("fill", "#128BED")
.attr('fill-opacity', 0.08)
.attr("stroke-width", 0.5);
d3.select(this).append("text")
.attr("dx", 165)
.attr("dy", 27)
.attr("fill", "#128BED")
.style("font-size", "11px")
.text(d => d.data.sign3);
}
}
} else {
if (d.data.sign2) {
d3.select(this).append("rect")
.attr("x", 30)
.attr("y", 13)
.attr("rx", 2)
.attr("ry", 2)
.attr("height", 20)
.attr("width", 66)
.attr("fill", "#EEA324")
.attr('fill-opacity', 0.08)
.attr("stroke-width", 0.5);
d3.select(this).append("text")
.attr("dx", 35)
.attr("dy", 27)
.attr("fill", "#EEA324")
.style("font-size", "11px")
.text(d => d.data.sign2);
if (d.data.sign3) {
d3.select(this).append("rect")
.attr("x", 106)
.attr("y", 13)
.attr("rx", 2)
.attr("ry", 2)
.attr("height", 20)
.attr("width", 66)
.attr("fill", "#128BED")
.attr('fill-opacity', 0.08)
.attr("stroke-width", 0.5);
d3.select(this).append("text")
.attr("dx", 111)
.attr("dy", 27)
.attr("fill", "#128BED")
.style("font-size", "11px")
.text(d => d.data.sign3);
}
} else {
if (d.data.sign3) {
d3.select(this).append("rect")
.attr("x", 30)
.attr("y", 13)
.attr("rx", 2)
.attr("ry", 2)
.attr("height", 20)
.attr("width", 66)
.attr("fill", "#128BED")
.attr('fill-opacity', 0.08)
.attr("stroke-width", 0.5);
d3.select(this).append("text")
.attr("dx", 35)
.attr("dy", 27)
.attr("fill", "#128BED")
.style("font-size", "11px")
.text(d => d.data.sign3);
}
}
}
})
nodeEnter.append("text")
.attr("dy", function (d) {
if (d.data.sign2 || d.data.sign3 || d.data.sign1) {
return 50.5;
}
return 20.5;
})
.attr("dx", 30.5)
.style("font", "11px sans-serif")
.attr("fill", "#666666")
.text(function (d) {
if (d.depth == 0) {
return "";
} else {
return d.data.key1 + ':';
}
});
nodeEnter.append("text")
.attr("dy", function (d) {
if (d.data.sign2 || d.data.sign3 || d.data.sign1) {
return 50.5;
}
return 20.5;
})
.attr("dx", 85.5)
.style("font", "11px sans-serif")
.attr("fill", "#ff7e00")
.text(function (d) {
if (d.depth == 0) {
return "";
} else {
if (d.data.value1) {
return d.data.value1;
}
return '-';
}
});
nodeEnter.append("text")
.attr("dy", function (d) {
if (d.data.sign2 || d.data.sign3 || d.data.sign1) {
return 50.5;
}
return 20.5;
})
.attr("dx", 150.5)
.style("font", "11px sans-serif")
.attr("fill", "#666666")
.text(function (d) {
if (d.depth == 0) {
return "";
} else {
return d.data.key2 + ':'
}
});
nodeEnter.append("text")
.attr("dy", function (d) {
if (d.data.sign2 || d.data.sign3 || d.data.sign1) {
return 50.5;
}
return 20.5;
})
.attr("dx", 205.5)
.style("font", "11px sans-serif")
.attr("fill", "#ff7e00")
.text(function (d) {
if (d.depth == 0) {
return "";
} else {
if (d.data.value2) {
return d.data.value2;
}
return "-";
}
});
nodeEnter.append("path")
.attr("d", function (d) {
if (d.depth == 0) {
_rootD = d;
if (d.data._children && d.data._children.length > 0) {
return "M7 -2 H11 V-6 H13 V-2 H17 V0 H13 V4 H11 V0 H7 Z"
} else if (d.children && d.children.length > 0) {
return "M7 -2 H17 V0 H7 Z"
}
} else {
if (d.data._children && d.data._children.length > 0) {
return "M7 6 H11 V2 H13 V6 H17 V8 H13 V12 H11 V8 H7 Z"
} else if ((d.data.children && d.data.children.length > 0)) {
return "M7 6 H17 V8 H7 Z"
}
if(d.data.isSearch==='Y')return "M7 6 H11 V2 H13 V6 H17 V8 H13 V12 H11 V8 H7 Z"
}
})
.attr("fill", "#bbbbbb")
.on("click", function (d) {
if (d.depth > 0 || true) {
click(d);
}
});
nodeEnter.append("circle")
.attr("cx", 12)
.attr("cy", function (d) {
if (d.depth == 0) {
return -1;
}
return 7;
})
.attr("r", function (d) {
if ((d._children && d._children.length > 0) || (d.data._children && d.data._children.length > 0) ||d.data.isSearch==='Y') {
return "6"
} else if ((d.children && d.children.length > 0)|| (d.data.children && d.data.children.length > 0) || d.data.isSearch==='Y') {
return "6"
}
})
.attr("fill", "none")
.attr("stroke", "#999999")
.attr("stroke-width", "0.5")
.on("click", function (d) {
if (d.depth > 0) {
click(d);
}
});
// Transition nodes to their new position.
nodeEnter.transition()
.duration(duration)
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
})
.style("opacity", 1);
node.transition()
.duration(duration)
.attr("transform", function (d) {
const y = d.y || d.y0;
const x = d.x || d.x0;
return "translate(" + y + "," + x + ")";
})
.style("opacity", 1)
.select("rect")
.style("stroke", "#999999");
node.transition()
.duration(duration)
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
})
.style("opacity", 1)
.select("path")
.attr("d", function (d) {
if (d.depth == 0) {
if (d.data._children && d.data._children.length > 0) {
return "M7 -2 H11 V-6 H13 V-2 H17 V0 H13 V4 H11 V0 H7 Z"
} else if (d.data.children && d.data.children.length > 0) {
return "M7 -2 H17 V0 H7 Z"
}
} else {
if (d.data._children && d.data._children.length > 0) {
return "M7 6 H11 V2 H13 V6 H17 V8 H13 V12 H11 V8 H7 Z"
} else if (d.data.children && d.data.children.length > 0) {
return "M7 6 H17 V8 H7 Z"
}
if(d.data.isSearch==='Y')return "M7 6 H11 V2 H13 V6 H17 V8 H13 V12 H11 V8 H7 Z"
}
});
// Transition exiting nodes to the parent's new position.
node.exit().transition()
.duration(duration)
.attr("transform", function (d) {
const y = source.y || source.y0;
const x = source.x || source.x0;
return "translate(" + y + "," + x + ")";
})
.style("opacity", 1e-6)
.remove();
// Update the links…
var link = container.selectAll("path.link")
.data(treeRoot.links(), function (d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("fill", "none")
.attr("stroke-width", "0.5px")
.attr("stroke", function (d) {
if (d.target.data.sign1) {
return "#fe485e";
} else if (d.target.data.type == 1) {
return "#7985f3";
} else if(d.target.data.type == 2) {
return "#4aceb1";
}else{
return "#FB813D";
}
})
.attr("d", function (d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
})
.style("stroke", function (d) {
if (d.target.data.sign1) {
return "#fe5151";
}
})
.transition()
.duration(duration)
.attr("d", function (d) {
return diagonal(d)
})
.style("stroke", function (d) {
if (d.target.data.sign1) {
return "#fe5151";
}
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", function (d) {
return diagonal(d)
});
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function (d) {
var o = {
x: source.x || source.x0,
y: source.y || source.y0
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function (d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function click(e) {
var d = e.target.__data__;
if(d.data.children === undefined){
const param = {
key: d.name,
id: d.id
}
loadAPiData(param, ({code, data}) => {
d.children = data.children.map((item)=>{
if(item.sign1){
item.height = barHeight+30
}else{
item.height = barHeight
}
return item
})
update(rootData);
},()=>{
setMsg('暂无下探数据');
d.data.children = undefined
update(rootData);
})
return
}
const children = d.children || d.data.children;
if (children) {
for(let i = 0; i< children.length; i++) {
if(children[i].data) {
children[i] = {
...children[i],
...children[i].data
}
}
}
d.data._children = children;
d._children = children;
d.data.children = null;
d.children = null;
d.data.isClose = true;
} else {
const _children = d._children || d.data._children;
if(_children){
for(let i = 0; i< _children.length; i++) {
if(_children[i].data) {
_children[i] = {
..._children[i],
..._children[i].data
}
}
}
}
d.children = _children;
d.data.children = _children;
d.data._children = null;
d._children = null;
d.data.isClose = false;
}
update(rootData);
}
function color(d) {
if (d.depth == 0) {
return "#128bed";
} else {
if (d.data.sign1) {
return "#fe5151";
}
if (d.data.type == 1) {
return "#7985f3";
}
if (d.data.type == 2) {
return "#4aceb1";
}
if(d.data.type == 3){
return "#FB813D" //其它类型左侧边边的颜色
}
}
}
function traverseTree(node) {
if (node._children) {
node.children = node._children;
node._children = null;
}
if (node.children && node.children.length > 0) {
for (var i = 0; i < node.children.length; i++) {
traverseTree(node.children[i]);
}
}
}
function post(URL, PARAMS) {
var temp = document.createElement("form");
temp.action = URL;
temp.enctype = "multipart/form-data";
temp.method = "post";
temp.style.display = "none";
for (var x in PARAMS) {
var opt = document.createElement("textarea");
opt.name = x;
opt.value = PARAMS[x];
// alert(opt.name)
temp.appendChild(opt);
}
document.body.appendChild(temp);
temp.submit();
return temp;
}
// 展开收缩
d3.select("#guquanExtent").on('click', () => {
if (!isExtent) {
traverseTree(rootData);
update(rootData);
d3.select("#guquanExtent").html(`
<i class="iconfont iconTab_icon_Putaway ft24"></i>
<span>收起</span>
`);
isExtent = true;
} else {
nodes.forEach(function (d) {
if (d.depth > 0) {
if (d.data.children) {
d.data._children = d.data.children;
d.data.children = null;
}
}
});
update(rootData);
d3.select("#guquanExtent").html(`<i class="iconfont iconTab_icon_Expand ft24"></i>
<span>展开</span>`)
isExtent = false;
}
})
// 一键展开
d3.select("#open").on("click", ()=>{
traverseTree(rootData);
update(rootData);
isExtent = true;
});
// 一键收起
d3.select("#close").on("click", ()=>{
if (!_rootD.data.isClose) {
click(_rootD);
}
});
// 还原
d3.select("#reduction").on("click", () => {
nodes.forEach(function (d) {
if (d.depth > 0) {
if (d.data.children) {
d.data._children = d.data.children;
d.data.children = null;
}
}
});
update(rootData);
isExtent = false;
});
// 刷新
d3.select("#guquanRefresh").on('click', () => {
d3.select("#guquanExtent").html(`
<i class="iconfont iconTab_icon_Expand ft24"></i>
<span>展开</span>
`);
traverseTree(rootData);
initSvg();
update(rootData);
isExtent = false;
scrollTo(0, 0);
})
//放大
d3.select("#scaleLar").on('click', () => {
var arr = container.attr("transform").split(',');
var x = arr[0].split('(')[1]
var y = arr[1].split(')')[0]
if (scale < 4) {
scale += 0.2;
}
container.transition()
.duration(500)
.attr("transform", "translate(" + (x) + "," + (y) + ") scale(" + scale + ")");
})
// 缩小
d3.select("#scaleSml").on('click', () => {
var arr = container.attr("transform").split(',');
var x = arr[0].split('(')[1]
var y = arr[1].split(')')[0]
if (scale > 0.2) {
scale -= 0.2;
}
container.transition()
.duration(500)
.attr("transform", "translate(" + (x) + "," + (y) + ") scale(" + scale + ")");
})
// 保存图片
d3.select("#save").on('click', () => {
var gNode = target.querySelector('#gbox');
var _gData = gNode.getBoundingClientRect();
var saveMain = document.getElementById('saveMain'); // 需要保存的内容的暂存处理空间
var d3Svg = d3.select('#' + svgId + ' svg');
var _svgWidth = d3Svg.attr('width');
var _svgHeight = d3Svg.attr('height');
var maxW = Math.max(_svgWidth, _gData.width)+10;
var maxH = Math.max(_svgHeight, _gData.height);
var svgXml = target.innerHTML;
// 将所需保存的内容放到暂存空间
saveMain.innerHTML = svgXml;
var saveMainSvg = saveMain.querySelector('.svgBox');
var saveMainG = saveMain.querySelector('#gbox');
saveMainSvg.setAttribute('width', maxW);
saveMainSvg.setAttribute('height', maxH);
saveMainG.setAttribute('transform', `translate(5,60) scale(1)`)
var newSvgXml = saveMain.innerHTML;
var image = new Image();
image.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(newSvgXml)));
setTimeout(function () {
var canvas = document.createElement('canvas'); //准备空画布
canvas.width = maxW;
canvas.height = maxH;
var context = canvas.getContext('2d'); //取得画布的2d绘图上下文
if (waterText) {
var shuiyinCvs = shuiyin().shuiyinCvs;
var pat = context.createPattern(shuiyinCvs, "repeat");
context.fillStyle = pat;
} else {
context.fillStyle = "#fff";
}
context.fillRect(0, 0, maxW, maxH);
context.drawImage(image, 0, 0);
downloadimg(canvas);
}, 100);
})
}
function downloadimg(canvas) {
var qual = 1;
if (canvas.width > 3000) {
qual = 0.8;
} else if (canvas.width > 5000) {
qual = 0.6;
}
//设置保存图片的类型
var downUrl = canvas.toDataURL('image/jpg', qual);
var filename = `${rootData.name}${new Date().toLocaleDateString()}结构图.jpg`;
var a = document.createElement("a");
a.style.display = "none";
a.href = downUrl;
a.download = filename;
a.click();
}
// 设置水印
function shuiyin() {
var cvs = document.createElement('canvas');
var ctx = cvs.getContext('2d');
cvs.width = 180;
cvs.height = 160;
ctx.fillStyle = "rgba(255, 255, 255, 1)";
ctx.fillRect(0, 0, 180, 160);
ctx.fill();
ctx.rotate(-30*Math.PI/180);
ctx.font = "19px 微软雅黑";
ctx.textAlign = 'left';
ctx.textBaseline = 'Middle';
// ctx.strokeStyle = '#c0c0c0';
// ctx.strokeText(waterText, -30, 80);
ctx.fillStyle = '#ddd';
ctx.fillText(waterText, -30, 125);
ctx.rotate(30*Math.PI/180);
const shuiyinUrl = cvs.toDataURL('image/jpeg', 1);
// new Image().src = shuiyinUrl;
return {
shuiyinImg: shuiyinUrl,
shuiyinCvs: cvs
};
}
function addFlag(node) {
if (node.sign2 || node.sign3 || node.sign1) {
node.height = barHeight + 30;
} else {
node.height = barHeight;
}
if (node.children) {
for (var i = 0; i < node.children.length; i++) {
addFlag(node.children[i]);
}
}
}
}
export default TreeList;