使用antv 配置区间柱形图
需求: 来源与产品的一个想法,想在 X 轴 每一行输出多个区间柱形,以时间为分段,X轴 底线显示时间, 找了一下 echarts 的实现, 可以使用配置函数的方式 实现,但只实现了一行,而且函数的配置项其API 文档也晦涩难懂, 最后使用 antv 的 区间柱形图来实现, 但是 antv 无法像 echarts 一样配置每一个柱形的颜色, 因为他的 color 配置回调函数只接受一个 type 字符串类型, 最后使用了数组队列匹配的方式来实现
使用的是 antv 的 g2plot 官方分组柱形图效果如下: 定位链接: g2plot.antv.vision/zh/examples…
实现之后的效果
分享思路
- 文件引入 这里是 html 文件, 直接可以复制, 下面的 js 文件我我们通过引入 CDN 的方式,这样在使用 demo 的时候更加方便
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<style>
.root {
padding: 50px;
width: 1600px;
height: 500px;
}
</style>
<body>
<div id="container" class="root"></div>
</body>
</html>
js文件
<script
type="text/javascript"
src="https://unpkg.com/@antv/g2plot@latest/dist/g2plot.min.js"
></script>
引入了 g2 以后
上面引入了 g2 以后 , 我们开始分享业务逻辑, 里面包含一些功能函数, 会拆开 首先是功能函数, 会在 我们的业务当中使用到的
// 时间处理
// 小时转分钟
function ChangeStrToMinutes(str) {
var arrminutes = str.split(":");
if (arrminutes.length == 2) {
var minutes = parseInt(arrminutes[0]) * 60 + parseInt(arrminutes[1]);
return minutes;
} else {
return 0;
}
}
// 分钟转小时
function ChangeHourMinutestr(str) {
if (str !== "0" && str !== "" && str !== null) {
return (
(Math.floor(str / 60).toString().length < 2
? "0" + Math.floor(str / 60).toString()
: Math.floor(str / 60).toString()) +
":" +
((str % 60).toString().length < 2
? "0" + (str % 60).toString()
: (str % 60).toString())
);
} else {
return "";
}
}
// 样式处理
const setStyles = (container, styles) => {
for (const key in styles) {
container.style[key] = styles[key];
}
};
// 动态设置画布高度
function setHeigh(data, name, height = 100) {
const dom = document.getElementsByClassName(name)[0];
const count = data.length;
dom.style["height"] = count * height + "px";
}
业务逻辑处理
注意点:
- 数据使用的是假数据, 这里我们可以根据自己的业务需求进行修改和扩展 因为区间柱形图使用的数据 data 是一个数组, 所以在使用我们的数据的时候需要进行一下改造
- 在使用 color 回调函数进行配置颜色的时候,不知道里面的循环为什么会进入两次,如果有大佬可以解答或有其他解决方案欢迎交流, 这里我使用了一个闭包的方式来记录次数,因为这里的数据我们业务上还没有和后端对接,所以暂时无法判定哪一条是第一个数据,而且 color 这回调函数也不提供 其他参数, 只提供一个 type 是字符串 作为参数, 所以我在上面数据处理的方法里面自己加入了一个 空字符的 type,用来区分循环的进入。
- 因为 color 方法的参数只有 type, 所以我也无法区分当前应该显示哪一种颜色, 数据里面的 way 就是颜色, 这里我使用了一个临时队列 arr 也是以闭包的形式存储, 然后从我处理好的数据中 过滤出当前 type 类型组成的一个数组, 通过下标的方式 取到当前对应的数据
- tooltip 如果想要自定义的话 需要使用 customContent API
- 由于我们这柱形一行有多个, 默认是鼠标悬浮到当前行,没有到我们的柱上,就会有 tooltip 提示, 可以设置shared 来匹配鼠标悬浮到柱形上才显示 tooltip
const { Bar } = G2Plot;
// 假数据
var busDataInfo = [
{
module: "BJ6123C7BTD",
line: "8",
wayLine: [
{
time: ["05:50", "06:30"],
way: "E",
},
{
time: ["06:42", "08:32"],
way: "S",
},
{
time: ["08:46", "10:39"],
way: "E",
},
{
time: ["14:06", "15:46"],
way: "S",
},
],
},
{
module: "BJ6123C7BTD",
line: "7",
wayLine: [
{
time: ["05:00", "06:30"],
way: "S",
},
{
time: ["06:42", "08:32"],
way: "E",
},
{
time: ["08:46", "10:39"],
way: "S",
},
{
time: ["14:06", "15:46"],
way: "E",
},
],
},
{
module: "BJ6123C7BTD",
line: "6",
wayLine: [
{
time: ["05:00", "06:00"],
way: "S",
},
{
time: ["06:12", "08:42"],
way: "E",
},
{
time: ["08:46", "09:09"],
way: "S",
},
{
time: ["14:06", "15:46"],
way: "E",
},
{
time: ["16:10", "18:00"],
way: "S",
},
{
time: ["18:34", "20:07"],
way: "E",
},
],
},
];
// 数据改造 将上面的数据改造成我需要的数组格式
function changeData(data) {
const outPutData = [];
data.forEach((item) => {
item.wayLine.forEach((every) => {
outPutData.push({
type: item.line,
module: item.module,
way: every.way,
values: [
ChangeStrToMinutes(every.time[0]),
ChangeStrToMinutes(every.time[1]),
],
});
});
});
//TODO 这里是为了解决 颜色 处理部分循环进入两次的问题, 这里写在 上面的数据处理之前和之后 会有分别,分别在于 后面是否使用 reverse 反转数组
outPutData.push({});
return outPutData;
}
// 样式
const divStyles = {
position: "absolute",
background: "rgba(255,255,255,0.95)",
boxShadow: "rgb(174, 174, 174) 0px 0px 10px",
borderRadius: "4px",
padding: "10px",
};
// 画布高度设置, 是根据数组数据长度,挂载点,以及高度 三个参数来进行设置
setHeigh(busDataInfo, "root", 60);
const data = changeData(busDataInfo);
// 画布实例化
const barPlot = new Bar("container", {
barWidthRatio: 0.7, // 条形图宽度占比
data: data,
xField: "values",
yField: "type",
colorField: "type", // 部分图表使用 seriesField
color: ((arg) => {
var count = 0;
var arr = [];
return (arg) => {
const { type = "" } = arg;
if (type === "") {
count = count + 1;
}
// 解决循环会进入两次的问题
if (count !== 1) return;
arr.push(type);
let currentArr = data.filter((item) => item.type === type);
let filterArr = arr.filter((item) => item === type);
// 获取当前往返类型
const wayType = currentArr[filterArr.length - 1]?.way;
console.log("type", type, wayType, currentArr);
if (wayType === "E") {
return "#FF5CA2";
}
return "#6C3E00";
};
})(),
xAxis: {
// x轴文本标签配置项
label: {
formatter: (value) => {
return ChangeHourMinutestr(value);
},
},
// 坐标轴网格线的配置项
grid: {
// alignTick:false,
},
// 坐标轴线样式
// line:
// {
// style:
// {
// stroke: 'black',
// lineWidth: 1,
// strokeOpacity: 0.7,
// shadowColor: 'black',
// shadowBlur: 10,
// shadowOffsetX: 5,
// shadowOffsetY: 5,
// cursor: 'pointer'
// }
// },
// 坐标轴刻度线样式
tickLine: {
length: 1,
style: (item, index, items) => {
return {
stroke: "black",
lineWidth: 2,
lineDash: [4, 5],
strokeOpacity: 0.7,
shadowColor: "black",
shadowBlur: 10,
shadowOffsetX: 5,
shadowOffsetY: 5,
cursor: "pointer",
};
},
},
min: 270, // 坐标轴最小值 这里指分钟数
tickCount: 20, // 坐标轴刻度数量 如果写了下面的刻度间隔, 则数量优先级变低
tickInterval: 30, // 坐标轴刻度间隔
},
isRange: true,
// 柱形上面的文字
label: {
content: "",
},
// barBackground: {
// style: {
// fill: '#000',
// fillOpacity: 0.01,
// }
// },
tooltip: {
fields: ["type", "way", "module", "values"],
// formatter:(data)=>{
// const { type,module,way,values} = data
// console.log('data',data);
// return {
// name:module,
// values:way
// }
// },
shared: false, // 只在鼠标悬浮到块上再展示
showCrosshairs: false,
customContent: (value, item) => {
console.log("customContent", value, item[0]);
if (!value || !item) return;
const { data } = item[0];
const container = document.createElement("div");
setStyles(container, divStyles);
container.innerHTML = `<div>车辆号码${data.type}</div><div>往返:${data?.way}</div>`;
return container;
},
},
});
// 官方颜色主题
barPlot.update({
theme: {
styleSheet: {
brandColor: "#FF4500",
paletteQualitative10: [
"#FF4500",
"#1AAF8B",
"#406C85",
"#F6BD16",
"#B40F0F",
"#2FB8FC",
"#4435FF",
"#FF5CA2",
"#BBE800",
"#FE8A26",
],
paletteQualitative20: [
"#FF4500",
"#1AAF8B",
"#406C85",
"#F6BD16",
"#B40F0F",
"#2FB8FC",
"#4435FF",
"#FF5CA2",
"#BBE800",
"#FE8A26",
"#946DFF",
"#6C3E00",
"#6193FF",
"#FF988E",
"#36BCCB",
"#004988",
"#FFCF9D",
"#CCDC8A",
"#8D00A1",
"#1CC25E",
],
},
},
});
挂载
barPlot.render();
- 如果想查看本 demo 的效果, 可以把以上代码直接复制到 自己的 HTML 文件中, 运行即可
- 参考 antv g2plot
以上就是antv完成区间柱形图一列多柱配置实现详解的详细内容,更多关于antv 区间柱形图一列多柱配置的资料请关注编程网其它相关文章!