长沙大的建网站公司,南昌网站建设收费,网站提交做外链有什么作用,淄博专业网站建设哪家专业前言#xff1a;折腾了一个星期#xff0c;在最后一天中午#xff0c;都快要放弃了#xff0c;后来坚持下来#xff0c;才有下面结果。
这个效果就相当是复合表头#xff0c;第一行是子级#xff0c;第二行是父级。 子级是奇数个时#xff0c;父级label居中很简单折腾了一个星期在最后一天中午都快要放弃了后来坚持下来才有下面结果。
这个效果就相当是复合表头第一行是子级第二行是父级。 子级是奇数个时父级label居中很简单但是当子级是偶数个的时候父级就很难居中
如图
直接把以下源码复制到这个链接去打开看效果 链接https://echarts.apache.org/examples/zh/editor.html?cbar-simple 查看效果注意设置宽度boxW
const boxW 547;
const boxH 803;
const grid { left: 10%, right: 10%, bottom: 40%, top: 10% }// canvas的宽高
const canvasW boxW * (1 - parseInt(grid.left) / 100 - parseInt(grid.right) / 100)
const canvasH boxH * (1 - parseInt(grid.top) / 100 - parseInt(grid.bottom) / 100)const seriesData [{data: [120, 200, 150, 80, 70, 110, 130, 120, 200, 150, 80, 70, 110, 130],type: bar},{data: [120, 200, 150, 80, 70, 110, 130, 120, 200, 150, 80, 70, 110, 130],type: bar},{data: [120, 200, 150, 80, 70, 110, 130, 120, 200, 150, 80, 70, 110, 130],type: line}
]const textStr1 第一组123456
const textStr2 第二组第二组第二组第二组1
const textStr3 第三组哈
const textStr4 第四组第四组第四组第四组123456
const textStr5 第五组
const chartGroups [{grouplabel: textStr1,xAxis_datas: [textStr1, textStr1]},{grouplabel: textStr2,xAxis_datas: [textStr2, textStr2, textStr2]},{grouplabel: textStr3,xAxis_datas: [textStr3, textStr3]},{grouplabel: textStr4,xAxis_datas: [textStr4, textStr4, textStr4, textStr4, textStr4]},{grouplabel: textStr5,xAxis_datas: [textStr5, textStr5]},
]
const xAxisData [Mon, Tue, Wed, Thu, Fri, Sat, 日, Mon1, Tue1, Wed1, Thu1, Fri1, Sat1, 日1]
let item2DataArr [] // x轴的第二行数据
const isShowLabelArr [] // x轴的第二行 label的显示与隐藏规则
const axisTickArr [] // 刻度线的显示与隐藏规则
const isExistObj []
const isExistObj1 []
const xObj {}// 计算x轴的第二行单元格label的显示与隐藏
chartGroups.forEach(gItem {const datas gItem.xAxis_datas || []const grouplabel gItem.grouplabelconst len datas.lengthdatas.forEach((o, i) {const isEsist isExistObj1.some(v v grouplabel)// debugger// 是否显示的设置if (!isEsist) {if (len % 2 0) { // 当前分组有偶数个子级const index len / 2 - 1if (index i) {// debuggerisExistObj1.push(grouplabel)isShowLabelArr.push(1) // 1显示0不显示标签文字刻度线} else {isShowLabelArr.push(0) // 1显示0不显示标签文字刻度线}} else { // 当前分组有奇数个子级let index Math.ceil(len / 2) - 1if (index i) {isExistObj1.push(grouplabel)isShowLabelArr.push(1) // 1显示0不显示标签文字刻度线} else {isShowLabelArr.push(0) // 1显示0不显示标签文字刻度线}}} else {isShowLabelArr.push(0) // 1显示0不显示标签文字刻度线}})})// 计算x轴的第二行单元格刻度线的显示与隐藏
chartGroups.forEach(gItem {const datas gItem.xAxis_datas || []const grouplabel gItem.grouplabeldatas.forEach((o, i) {item2DataArr.push(grouplabel)const isEsist isExistObj.some(v v grouplabel)// 是否显示的设置if (!isEsist) {isExistObj.push(grouplabel)axisTickArr.push(1) // 1显示0不显示标签文字刻度线} else {axisTickArr.push(0) // 1显示0不显示标签文字刻度线}})
})// 每一柱子的宽度
const itemW canvasW / item2DataArr.lengthchartGroups.forEach((item, i) {const len item.xAxis_datas.length// debuggerconst centerNum Math.floor(len / 2) // 当前组的中心const isOdd len % 2 0xObj[item.grouplabel] {canvasW: boxW,canvasH: boxH,itemW,text: item.grouplabel,isOdd: isOdd ? 奇数个 : 偶数个,count: len, // 子级个数x轴第一行个数tdCountW: (len * itemW).toFixed(2) // 合并单元格的总宽度}
})// console.log(itemW, itemW)
let richObj {}
let axisLabelFormat []
const spaceW 4 // 1个空格字符站4px
const perFontW 12 // 1个字符的宽度12px
let isExistArr []
let context null// 第二行的文字长度区分奇数和偶数并根据复合单元格宽度适配文字最大长度
item2DataArr.forEach((k, index) {const isTrue isShowLabelArr[index]const o xObj[k]let txt o.textif (isTrue) { // 显示的才处理const isEsist isExistArr.some(val1 val1 k)// 计算文字的总宽度const contextObj measureTextWidth({ cxt: context, text: k });if (!context) {context contextObj.context}o.txtW contextObj.strWidth; // 文字的总宽度// debuggerif (o.count % 2 0 !isEsist) { //偶数需要计算中心位置let txtAlign leftlet paddingArr [0, 0, 0, 0]isExistArr.push(k)o.halfW (o.tdCountW - o.txtW) / 2 // 文字在复合单元格中的中心点o.centerNum Math.abs(itemW / 2 - o.halfW) // 一个单元格相对文字中心的中心点o.spaceNum Math.floor(o.centerNum % spaceW) // 计算把字符从单元格中心移到复合表头中心需要多少个空字符const disAllItemW o.txtW - o.tdCountWconst disItemW o.txtW - itemW// debuggerif (disAllItemW 0) { // 字的长度大于整个复合单元格的宽度txtAlign centerpaddingArr [0, 0, 0, itemW]// debuggertxt fixTxtMaxWidth({ item: o, context, perFontW }) // 字数长度大于复合单元格宽度适配复合单元格的宽度最多能显示多少个字符// console.log(\n\n********, txt, paddingArr, paddingArr)} else if (disItemW 0) { // 字的长度大于1个单元格的宽度txtAlign centertxt k// debuggerpaddingArr [0, 0, 0, itemW]// console.log(\n\n----------, o.count, o.text, paddingArr, paddingArr)} else { // 字的长度小于1个单元格的宽度则需要通过添加空字符来占位txtAlign lefttxt fixTxtMinWidth({ item: o, context }) // 子级个数为偶数且父级字数长度过小通过给父级label加空格把label居中显示// debugger}axisLabelFormat.push({${index}|${txt}})richObj[index] {width: 0.5,height: 16,color: #f00,padding: paddingArr,// backgroundColor: #bbb,align: txtAlign}} else { // 奇数直接显示中间的即可// debuggerif (k) {txt fixTxtMaxWidth({ item: o, context, perFontW }) // 字数长度大于复合单元格宽度适配复合单元格的宽度最多能显示多少个字符}axisLabelFormat.push({${index}|${txt}})richObj[index] {height: 16}}} else {axisLabelFormat.push({${index}|${txt}})richObj[index] {height: 16}}})console.log( )
console.log(itemW, itemW)
console.log(item2DataArr, item2DataArr)
console.log(isShowLabelArr, isShowLabelArr)
console.log(axisTickArr, axisTickArr)// console.log(canvasW, canvasW)
// console.log(canvasH, canvasH)console.log(xObj, xObj)
console.log(axisLabelFormat, axisLabelFormat)
console.log(richObj, richObj)
console.log( )// 字数长度大于复合单元格宽度适配复合单元格的宽度最多能显示多少个字符
function fixTxtMaxWidth ({ item, context, perFontW }) {// console.log(\n\nfixTxtMaxWidth111);let txt item.textlet txtLen item.txtWconst countW item.tdCountW - perFontW // 超出最大宽度要裁剪然后添加省略号let symbol // debuggerwhile (txtLen countW) {txt txt.substring(0, txt.length - 1)// debuggerconst txtObj measureTextWidth({ cxt: context, text: txt }); // 文字的总宽度txtLen txtObj.strWidthconsole.log(\nwhile:, txt, txtLen, item.tdCountW)symbol ...}txt symbolreturn txt
}// 通过canvas计算文字宽度
function measureTextWidth ({ cxt, text, fontSize, fontFamily }) {fontSize fontSize || 12;fontFamily fontFamily || Arial;let context cxtif (!context) {// 创建一个canvas元素const canvas document.createElement(canvas);context canvas.getContext(2d);}// 设置文本样式context.font ${fontSize}px ${fontFamily};// 测量文本宽度const metrics context.measureText(text);// console.log(text, metrics.width);return {strWidth: metrics.width,context}
}// 子级个数为偶数且父级字数长度过小通过给父级label加空格把label居中显示
function fixTxtMinWidth ({ item, context, dividendNum 2 }) {let txt item.textlet txtLen item.txtWconst countW itemW / dividendNum// debuggerwhile (txtLen countW) {txt txtconst txtObj measureTextWidth({ cxt: context, text: txt }); // 文字的总宽度txtLen txtObj.strWidth.toFixed(2)// debuggerconsole.log(fixTxtMinWidth111:, item.txtW, txtLen, itemW, , tdCountW, item.tdCountW, txt)}return txt
}option {grid,// 组件离容器下侧的距离值可以是像 20 这样的具体像素值也可以是像 20% 这样相对于容器高宽的百分比xAxis: [{type: category,axisLabel: {interval: 0,rotate: 0// 倾斜角度},axisTick: {show: true,length: 30,},// 是否显示坐标轴刻度data: xAxisData},// ******************************************************************************************************************************// 这个是X轴第二行相当父级{type: category,axisLabel: { // 坐标轴文本标签align: center,formatter (value, index) {let val1 axisLabelFormat[index]return val1 // 返回真就会显示label},interval: function (index, value) {const val1 isShowLabelArr[index]// 根据子级个数动态调整间隔 false则不显示return val1;},rich: richObj},position: bottom,// 很重要如果没有这个设置默认第二个x轴就会在图表的顶部offset: 30,// X 轴相对于默认位置的偏移在相同的 position 上有多个 X 轴的时候有用axisTick: { // 刻度线show: true,length: 30,interval: function (index, value) {const val1 axisTickArr[index]// 根据子级个数动态调整间隔return val1;}},// 是否显示坐标轴刻度axisLine: { // 是否显示坐标轴轴线show: true,onZeroAxisIndex: 2},data: item2DataArr},// ******************************************************************************************************************************// 这个设置只是在底部绘制一条线{type: category,position: bottom,// 很重要如果没有这个设置默认第二个x轴就会在图表的顶部offset: 60,// X 轴相对于默认位置的偏移在相同的 position 上有多个 X 轴的时候有用axisLine: { // 是否显示坐标轴轴线show: true,onZeroAxisIndex: 2},data: []}],yAxis: [{name: 人数,type: value},// {// name: 年龄,// type: value// }],series: seriesData
};
后记记录这一刻的不易同时希望能帮到有需要的人觉得不错可以收藏 文章转载自: http://www.morning.pghfy.cn.gov.cn.pghfy.cn http://www.morning.lcbt.cn.gov.cn.lcbt.cn http://www.morning.lnwdh.cn.gov.cn.lnwdh.cn http://www.morning.hgcz.cn.gov.cn.hgcz.cn http://www.morning.rbgqn.cn.gov.cn.rbgqn.cn http://www.morning.ktskc.cn.gov.cn.ktskc.cn http://www.morning.twpq.cn.gov.cn.twpq.cn http://www.morning.rbyz.cn.gov.cn.rbyz.cn http://www.morning.gbwfx.cn.gov.cn.gbwfx.cn http://www.morning.sbjbs.cn.gov.cn.sbjbs.cn http://www.morning.rjrlx.cn.gov.cn.rjrlx.cn http://www.morning.fswml.cn.gov.cn.fswml.cn http://www.morning.smcfk.cn.gov.cn.smcfk.cn http://www.morning.cjsrg.cn.gov.cn.cjsrg.cn http://www.morning.swkzk.cn.gov.cn.swkzk.cn http://www.morning.gcspr.cn.gov.cn.gcspr.cn http://www.morning.plqqn.cn.gov.cn.plqqn.cn http://www.morning.xgbq.cn.gov.cn.xgbq.cn http://www.morning.jjxnp.cn.gov.cn.jjxnp.cn http://www.morning.qrhh.cn.gov.cn.qrhh.cn http://www.morning.lqznq.cn.gov.cn.lqznq.cn http://www.morning.cwzzr.cn.gov.cn.cwzzr.cn http://www.morning.ppghc.cn.gov.cn.ppghc.cn http://www.morning.mcjyair.com.gov.cn.mcjyair.com http://www.morning.zkgpg.cn.gov.cn.zkgpg.cn http://www.morning.rdnjc.cn.gov.cn.rdnjc.cn http://www.morning.mhnd.cn.gov.cn.mhnd.cn http://www.morning.grfhd.cn.gov.cn.grfhd.cn http://www.morning.cbczs.cn.gov.cn.cbczs.cn http://www.morning.wmgjq.cn.gov.cn.wmgjq.cn http://www.morning.zyslyq.cn.gov.cn.zyslyq.cn http://www.morning.gwjnm.cn.gov.cn.gwjnm.cn http://www.morning.tpnch.cn.gov.cn.tpnch.cn http://www.morning.pmnn.cn.gov.cn.pmnn.cn http://www.morning.pwwjs.cn.gov.cn.pwwjs.cn http://www.morning.yqtry.cn.gov.cn.yqtry.cn http://www.morning.cyfsl.cn.gov.cn.cyfsl.cn http://www.morning.lzqdl.cn.gov.cn.lzqdl.cn http://www.morning.dyxlm.cn.gov.cn.dyxlm.cn http://www.morning.qqnp.cn.gov.cn.qqnp.cn http://www.morning.qxljc.cn.gov.cn.qxljc.cn http://www.morning.huarma.com.gov.cn.huarma.com http://www.morning.qxxj.cn.gov.cn.qxxj.cn http://www.morning.ghfrb.cn.gov.cn.ghfrb.cn http://www.morning.gdljq.cn.gov.cn.gdljq.cn http://www.morning.srrrz.cn.gov.cn.srrrz.cn http://www.morning.cgdyx.cn.gov.cn.cgdyx.cn http://www.morning.lbzgt.cn.gov.cn.lbzgt.cn http://www.morning.rywn.cn.gov.cn.rywn.cn http://www.morning.fkdts.cn.gov.cn.fkdts.cn http://www.morning.mcwgn.cn.gov.cn.mcwgn.cn http://www.morning.qbtkg.cn.gov.cn.qbtkg.cn http://www.morning.jhswp.cn.gov.cn.jhswp.cn http://www.morning.rkdzm.cn.gov.cn.rkdzm.cn http://www.morning.bqpg.cn.gov.cn.bqpg.cn http://www.morning.smpmn.cn.gov.cn.smpmn.cn http://www.morning.gjmll.cn.gov.cn.gjmll.cn http://www.morning.wbfly.cn.gov.cn.wbfly.cn http://www.morning.xpfwr.cn.gov.cn.xpfwr.cn http://www.morning.brkc.cn.gov.cn.brkc.cn http://www.morning.jnrry.cn.gov.cn.jnrry.cn http://www.morning.qkcyk.cn.gov.cn.qkcyk.cn http://www.morning.zzgtdz.cn.gov.cn.zzgtdz.cn http://www.morning.lgnbr.cn.gov.cn.lgnbr.cn http://www.morning.bnmrp.cn.gov.cn.bnmrp.cn http://www.morning.gcfg.cn.gov.cn.gcfg.cn http://www.morning.lblsx.cn.gov.cn.lblsx.cn http://www.morning.mlcwl.cn.gov.cn.mlcwl.cn http://www.morning.yxlpj.cn.gov.cn.yxlpj.cn http://www.morning.bfycr.cn.gov.cn.bfycr.cn http://www.morning.qkrz.cn.gov.cn.qkrz.cn http://www.morning.ghssm.cn.gov.cn.ghssm.cn http://www.morning.ngkgy.cn.gov.cn.ngkgy.cn http://www.morning.bzqnp.cn.gov.cn.bzqnp.cn http://www.morning.yrmpr.cn.gov.cn.yrmpr.cn http://www.morning.mjglk.cn.gov.cn.mjglk.cn http://www.morning.wyrkp.cn.gov.cn.wyrkp.cn http://www.morning.hxftm.cn.gov.cn.hxftm.cn http://www.morning.dpplr.cn.gov.cn.dpplr.cn http://www.morning.zlfxp.cn.gov.cn.zlfxp.cn