这篇文章主要为大家介绍了antv完成区间柱形图一列多柱配置实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
使用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
发表评论 取消回复