前言:
Highcharts自由绘图官网看到demo,明白了是svg矢量图形。
然后就想,根据数据动态画图,这画图又不是html的div一大堆标签无脑堆,折行啥的还得计算。。。
一番折腾,写了下,但是已知么有解决的问题就是字符串过多折行的问题,个人觉得有点麻烦,所以只写了个demo。
废话不多说,放代码。(ps:可直接复制粘贴,如有不对之处,望指出,共同进步)
确实觉得有点麻烦,可以看我另一篇用js写的,点我跳转
html部分:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.hcharts.cn/highcharts/highcharts.js"></script>
</head>
<body>
<div id="container" style="width: 800px; margin: 0 auto"></div>
</body>
</html>
js部分:
<script>
let data = {
root: [
{title: '根节点1', color: 'red'},
{title: '根节点2', color: 'yellow'},
{title: '根节点3', color: 'skyblue'},
],
child: [
{title: '节点', color: '#ccc'},
],
child2: [
{title: '子节点1'},
{title: '子节点2阿诗丹顿'},
{title: '子节点3'},
{title: '子节点4'},
{title: '子节点5'},
{title: '子节点6'},
{title: '子节点7'},
{title: '子节点8'},
]
};
console.log("数据源", data);
let myChart = Highcharts.chart('container', {
chart: {
backgroundColor: 'white',//背景颜色
events: {
click: function (e) {//点击事件
//console.log(e);
//console.log(e.target.getAttribute('data'));
if (e.target.getAttribute('data') || e.target.innerHTML) {//兼容处理
alert(e.target.getAttribute('data') || e.target.innerHTML)
}
},
load: function () {
const X = 5;//开始画图的位置
const Y = 40;//矩形高度&&刻度尺 (控制高度)
let startX;
let startY = Y;
//开始画图
drawPicture('container', this.renderer, data.root);
drawPicture('container', this.renderer, data.child);
drawPicture('container', this.renderer, data.child2, true);
/**
* 画图
* @param domName id名称
* @param renderer highchart自带的属性
* @param data 源数据
* @param isEnd 画图是否结束 true=>是|false=>否
*/
function drawPicture(domName, renderer, data, isEnd) {
let container = document.getElementById(domName);
let containerW = container.clientWidth;
let d = 1;//初始行数
//数据渲染
for (let i in data) {
//console.log(data[i].title);
let num = data.length;
let w = (containerW - 4 * 10) / 4;//宽度
num = num > 4 ? 4 : num;
switch (num) {
case 1:
startX = w * 1.5 + 15;//如果只有一个子代,默认居中
break;
case 2:
startX = (w + 10) * (Number(i) + 1);//如果只有两个子代,默认居中
break;
case 3:
startX = (w / 2 + 10) + (w + 10) * (Number(i));//如果只有两个子代,默认居中
break;
default:
break;
}
let c = Math.ceil((Number(i) + 1) / num); //第几排
if (d !== c) {//判断是否换行
d = c;
startX = X
}
//console.log(c);
setRect(renderer, {
x: startX,
y: (c === 1) ? (startY + 10) : (startY + 10 * c + Y * (c - 1)),
w: w,
h: Y,
attr: {
data: data[i].title,
fill: data[i].color ? data[i].color : 'pink'
}
});
setTitle(renderer, {
title: data[i].title,
x: startX,
y: (c === 1) ? (startY + 10) : (startY + 10 * c + Y * (c - 1)),
attr: {
data: data[i].title,
}
});
startX += w + 10;
}
startY += 10 * (d + 1) + Y * d;//该层循环完的高度
if (!isEnd) {
//箭头
setArrow(renderer, {
w: containerW / 2,
distance: startY,
h: Y * 2
});
startY += 80;
startX = X;//startX复位
} else {
container.style.height = startY + "px";
}
}
}
}
},
title: {
text: '×××图',
style: {
color: 'black'
}
},
credits: {
enabled: false
}
});
myChart.reflow();//高度
//描绘title
function setTitle(renderer, opt) {
renderer.label(opt.title, opt.x, opt.y)
.attr(opt.attr)
.css({
fontSize: '16px',
color: 'black',
width: opt.x + 'px',
height: opt.y + 'px',
lineHeight: opt.y + 'px',
minHeight: opt.y + 'px',
textAlign: 'center'
}).add();
}
//描绘矩形
function setRect(renderer, opt) {
let defaultOpt = {
fill: 'pink',
stroke: 'black',
'stroke-width': 1
};
let newObj = Object.assign(defaultOpt, opt.attr);
renderer.rect(opt.x, opt.y, opt.w, opt.h, 5).attr(newObj).add();
}
//描绘箭头
//arrowW,arrowH均为起点
function setArrow(renderer, opt) {
let arrowW = opt.w;
let arrowD = opt.distance;
let arrowH = opt.h;
let arrow = ['M', arrowW, arrowD, 'L', arrowW, arrowD + arrowH, 'L', (arrowW - 10), arrowD + (arrowH - 10), 'M', arrowW, arrowD + arrowH, 'L', (arrowW + 10), arrowD + (arrowH - 10)];
renderer.path(arrow)
.attr({
'stroke-width': 2,
stroke: opt.color || "red"
}).add();
}
</script>
效果图: