基于orgChart.js 实现横纵向排列的组织结构图
github:https://github.com/violectyc/javascript-orgchart
部分截图如下
基本代码如下入口函数在fetch
html
<div class="loading"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <div id="chart-container" > <button id="export">export</button> </div>
css
body {
font-family: "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
#chart-container {
display: block;
height: calc(100vh - 60px);
width: calc(100% - 24px);
border: 2px dashed #aaa;
border-radius: 5px;
overflow: auto;
text-align: center;
margin: 0 auto;
}
.orgchart{
cursor: pointer;
}
#export {
position: fixed;
top: 0;
right: 0;
z-index: 100;
display: none;
}
.loading{
display: none;
width: 80px;
height: 40px;
margin: 0 auto;
margin-top:100px;
position: absolute;
z-index: 100;
}
.loading span{
display: inline-block;
width: 8px;
height: 100%;
border-radius: 4px;
background: lightgreen;
-webkit-animation: load .8s ease infinite;
}
@-webkit-keyframes load{
0%,100%{
height: 40px;
background: lightgreen;
}
50%{
height: 70px;
margin: -15px 0;
background: lightblue;
}
}
.loading span:nth-child(2){
-webkit-animation-delay:0.0s;
}
.loading span:nth-child(3){
-webkit-animation-delay:0.2s;
}
.loading span:nth-child(4){
-webkit-animation-delay:0.4s;
}
.loading span:nth-child(5){
-webkit-animation-delay:0.6s;
}
javascript
let _scale = 0.3;
let w = null;
let _w = null;
let h = null;
let _h = null;
let _target = null;
// loading
const loading = visible => {
const chartWrapWidth = $(".loading").width();
const chartWrapHeight = $(".loading").height();
$('.loading').css({
'display': 'block',
'top': '50%',
'left': '50%',
'margin-top': - chartWrapWidth / 2 + 'px',
'margin-left': - chartWrapHeight / 2 + 'px',
'visibility': visible
});
};
// loading('visible');
const ENUMCOLOR = {
1: "rgb(236, 206, 152)",
2: "rgb(229, 131, 144)",
3: "rgb(196, 156, 206)",
4: "rgb(143, 209, 233)",
5: "rgb(156, 212, 149)",
6: "rgb(196, 198, 197)"
};
const templete = data => {
console.log(data.level);
if (data.level == 1) {
return `
<span data-level="${data.level}" style="display:inline-block;width:520px;height:60px;line-height:60px;
background: linear-gradient(rgb(207, 9, 0), rgb(244, 96, 0));
font-size: 22px;
color: #fff;
font-weight: 700;
box-shadow: 0px 2px 2px rgb(0,0,0);"><span
style="white-space:nowrap;font-size:24px;letter-spacing:2px;">${data.name}</span></span>
`;
} else if (data.level == 2) {
return `
<span data-level="${data.level}" style="display:inline-block;width:520px;height:60px;line-height:60px; box-shadow: 0px 2px 2px rgb(0,0,0);
background:linear-gradient(180deg, rgb(245, 191, 66), rgb(250, 216, 167));font-size: 20px;position:relative;">
<span style="display:block;position:absolute;left:50%;margin-left:-60px;top:-30px;text-align:center;line-height:30px;font-size:16px;width:60px;height:30px;">${data.value}</span>
<span style="white-space:nowrap;font-size:22px;font-weight:700;letter-spacing:1px;">${data.name}</span></span>
`;
}
else if (data.level >= 3) {
return `<span data-level="${data.level}" class="y-content" style="box-sizing:border-box;display:inline-block;border:1px solid rgb(115,115,115);border-radius:3px;
width:60px;height:520px;text-align:center;">
<span style="display:inline-block;width:100%;height:30px;color:rgb(8, 8, 8);font-weight:500;line-height:30px;text-align:center;background-color:${ENUMCOLOR[data.type]}">${data.value}</span>
<span style="letter-spacing:2px;writing-mode:tb-rl;padding-top:10px;font-size:18px;color:rgb(8,8,8);font-weight:700;">${data.name}</span>
</span>`;
}
};
const initCompleted = () => {
w = $("#chart-container").find(">div").width();
_w = $("#chart-container").width();
h = $("#chart-container").find(">div").height();
_h = $("#chart-container").height();
_target = $('#chart-container').find('.orgchart');
// 缩放原点
_target.css({
'transform-origin': (w / 2 - _w / 2, h / 2 - _h / 2, 0),
'-webkit-transform-origin': (w / 2 - _w / 2, h / 2 - _h / 2, 0),
'transform': 'scale(' + _scale + ')',
'-webkit-transform': 'scale(' + _scale + ')'
});
$('#chart-container').scrollLeft((w * _scale) / 2 - _w / 2);
$('#chart-container').scrollTop((h * _scale));
// loading('hidden');
}
const init = res => {
const options = {
'data': res.downward,
'nodeContent': 'value',
'pan': true,
'zoom': false,
'toggleSiblingsResp': true,
'nodeTemplate': templete,
'draggable': false,
'zoomoutLimit': .6,
'initCompleted': initCompleted
};
const chart = $('#chart-container').orgchart(options);
const dom = $('.y-content');
dom.each(function (index, item) {
$(item).closest('table').css({
'display': 'inline-block'
});
});
}
const _fixType = type => {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
let r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
};
const fileDownload = downloadUrl => {
let aLink = document.createElement('a');
aLink.style.display = 'none';
aLink.href = downloadUrl;
aLink.download = "下载文件名xxx.png";
document.body.appendChild(aLink);
aLink.click();
document.body.removeChild(aLink);
let oContainer = document.querySelector("#canvasContainer");
document.body.removeChild(oContainer);
controlScale(_scale);
}
const eportImg = () => {
controlScale(0.8);
const oContainer = document.createElement('div');
oContainer.setAttribute('id', 'canvasContainer');
document.body.append(oContainer);
html2canvas(_target.get(0)).then(function (canvas) {
oContainer.appendChild(canvas);
setTimeout(function () {
const type = 'png';
const oCanvas = document.querySelector('#canvasContainer').getElementsByTagName('canvas')[0];
let imgData = oCanvas.toDataURL(type);
imgData = imgData.replace(_fixType(type), 'image/octet-stream');
fileDownload(imgData);
}, 0);
});
}
fetch('./d3.json').then(res => res.json()).then(res => {
init(res);
});
// 入口函数
const controlScale = scale => {
if (_target != null) {
_target.css({
'transform': 'scale(' + scale + ')',
'-webkit-transform': 'scale(' + scale + ')'
});
}
}
const onMouseScroll = e => {
e.preventDefault();
let wheel = e.originalEvent.wheelDelta || -e.originalEvent.detail;
const delta = Math.max(-1, Math.min(1, wheel));
if (delta < 0) {//向下滚动 放大
if (_scale >= 0.9) {
return;
} else {
_scale += 0.1;
controlScale(_scale);
}
} else {//向上滚动 缩小
if (_scale <= 0.3) {
_scale = 0.3;
// $('#chart-container').scrollTop((h));
return;
} else {
_scale -= 0.1;
controlScale(_scale);
}
}
}
$(document).on('mousewheel DOMMouseScroll', onMouseScroll);
((function () {
setInterval(() => {
$('.orgchart').css({
'cursor': 'pointer'
})
}, 1);
})()) //取悦boss
部分数据格式如下
实现了缩放,脱拽,导出,如果要自定义其他节点层级或样式复写下templete这个函数即可。