翻页及轮播的条形图
需要注意当柱形颜色需要渐变时(new echarts.graphic.LinearGradient),需降低echarts版本,4.9即可
比较满意的是左侧可以设置为数字排行还是图片样式排行,为图片时可设置自定义数字,图片只作为背景,也可设置图片带上数字进行排行;下方分页能点击时则是高亮,不可点击为灰色。
下面把代码分享出来了,其中有的参数是动态设置可配置的记得修改啊!!!!
/* eslint-disable */
import React from 'react';
import ReactEcharts from 'echarts-for-react';
import echarts from 'echarts/lib/echarts';
import setting from './setting';
import styles from './index.less';
import { Pagination } from 'antd';
class LoopRankBar extends React.Component {
constructor(props) {
super(props)
this.state = {
myPage: 1,
total: 0,
myData: [],
}
}
leftTriangle() {
return {
'border-right': '5px solid rgba(255, 255, 255, 0.45)',
'border-top': '5px solid rgba(255, 255, 255, 0.45)',
height: '10px',
width: '10px',
transform: 'rotate(-135deg)',
'-webkit-transform': 'rotate(-135deg)',
'border-left': ' 5px solid transparent',
'border-bottom': '5px solid transparent',
display: 'inline-block',
'-moz-transform': 'rotate(-135deg)',
'-ms-transform': 'rotate(-135deg)',
'-o-transform': 'rotate(-135deg)',
}
}
onLeft() {
return {
'border-right': '5px solid #01FCC5',
'border-top': '5px solid #01FCC5',
height: '10px',
width: '10px',
transform: 'rotate(-135deg)',
'-webkit-transform': 'rotate(-135deg)',
'border-left': ' 5px solid transparent',
'border-bottom': '5px solid transparent',
display: 'inline-block',
'-moz-transform': 'rotate(-135deg)',
'-ms-transform': 'rotate(-135deg)',
'-o-transform': 'rotate(-135deg)',
}
}
rightTriangle() {
return {
'border-right': '5px solid rgba(255, 255, 255, 0.45)',
'border-top': '5px solid rgba(255, 255, 255, 0.45)',
height: '10px',
width: '10px',
transform: 'rotate(45deg)',
'-webkit-transform': 'rotate(45deg)',
'border-left': ' 5px solid transparent',
'border-bottom': '5px solid transparent',
display: 'inline-block',
'-moz-transform': 'rotate(45deg)',
'-ms-transform': 'rotate(45deg)',
'-o-transform': 'rotate(45deg)',
}
}
onRight() {
return {
'border-right': '5px solid #01FCC5',
'border-top': '5px solid #01FCC5',
height: '10px',
width: '10px',
transform: 'rotate(45deg)',
'-webkit-transform': 'rotate(45deg)',
'border-left': ' 5px solid transparent',
'border-bottom': '5px solid transparent',
display: 'inline-block',
'-moz-transform': 'rotate(45deg)',
'-ms-transform': 'rotate(45deg)',
'-o-transform': 'rotate(45deg)',
}
}
itemRender = (current, type, originalElement) => {
if (type === 'prev') {
return <div style={current === 0 ? this.leftTriangle() : this.onLeft()}></div>;
}
if (type === 'next') {
return <div
style={
this.state.myPage !== Math.ceil(this.state.total)
? this.onRight()
: this.rightTriangle()
}
></div>;
}
return originalElement;
}
onChange = (page, pageSize) => {//存储改变后的页码
const { data, config: { pagingNum } } = this.props;
this.setState((state) => ({ myPage: page }));
}
static getDerivedStateFromProps = (props, state) => {//进行分页处理,数据量少,前端处理了
const { data, config: { pagingNum, isNeedLoop } } = props;
if (!data) return;
const newArr = data.slice((state.myPage - 1) * pagingNum, pagingNum * state.myPage);
return { myData: newArr, total: data.length / pagingNum };
}
componentDidMount() {
const { config: { isNeedLoop, loopNum } } = this.props;
if (isNeedLoop) {
this.timer = setInterval(() => {
this.myLoop()
}, loopNum * 1000);
return function () {
clearInterval(this.timer);
};
}
}
componentWillUnmount() {
clearInterval(this.timer);
}
myLoop() {
const { config: { pagingNum } } = this.props;
const { myPage, total } = this.state;
this.setState((state) => ({ myPage: myPage + 1 }));
if (myPage === Math.ceil(total)) {
this.setState((state) => ({ myPage: 1 }));
}
}
get option() {
const { config, config: { pagingNum }, data = [] } = this.props;
const { myData, myPage } = this.state;
const { bgColor } = config.bgStyle;
const { tooltipBgColor, barWidth, barBgColor, rankColor, tooltipFontSize, tooltipName } = config.barStyle;
const {
rankNumStyle: { rankNumFontSize, judgeImgTxt, imgNumFontSize: { fontSize, color, fontWeight, fontFamily }, rankNumColor, imgWidth, imgHeight, judgeImg, imgValueUnit },
nameStyle: { nameFontSize },
valueStyle: { valueFontSize, valueUnit },
} = config.textStyle;
const numArr = rankNumColor.split('-');
const rankStyColor = rankColor.split('-');
const richObj = {};
if (judgeImg) {
data.forEach((item, idx) => {//遍历出图片渲染样式
richObj[`backImg${idx}`] = {
backgroundColor: {
image: item.url,
},
width: imgWidth,//图片宽高设置需放在外层,不可放至backgroundColor中
height: imgHeight,
fontSize,
color,
fontWeight: 500,//此处不可加字重动态变
fontFamily
}
});
} else {
numArr.forEach((item, idx) => {//遍历出文字样式
richObj[`color${idx}`] = {
fontSize: rankNumFontSize,
color: item,
fontWeight: 500,
fontStyle: 'italic',
}
});
}
const sortArr = myData.sort((a, b) => Number(b.value) - Number(a.value)) || [];
const maxValue = sortArr.length ? sortArr[0].value : '';
return {
backgroundColor: bgColor,
title: {
show: false
},
tooltip: {
trigger: 'item',
// hover 到背景柱时 不展示
formatter: (p) => {
if (p.seriesName === 'bar') {
return `${p.name}:${p.value}${tooltipName}`;
}
return '';
},
padding: 10,
backgroundColor: tooltipBgColor,
textStyle: {
fontSize: tooltipFontSize.fontSize,
color: tooltipFontSize.color,
fontFamily: tooltipFontSize.fontFamily,
fontWeight: tooltipFontSize.fontWeight,
align: 'left'
}
},
grid: {
borderWidth: 0,
top: '8%',
right: '5%',
bottom: '1%',
left: '5%'
},
// 右侧y轴 - 用双y坐标轴实现,左侧y轴隐藏 右侧展示
yAxis: [
{
type: 'category',
inverse: true,
axisLine: {
show: false
},
axisLabel: {
show: false,
},
axisTick: {
show: false
},
},
{
type: 'category',
inverse: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
// 右侧值样式设置
axisLabel: {
show: true,
lineHeight: 32,
verticalAlign: 'bottom',
padding: [0, 0, 0, -56],
textStyle: {
fontSize: valueFontSize.fontSize,
color: valueFontSize.color,
fontFamily: valueFontSize.fontFamily,
fontWeight: valueFontSize.fontWeight
}
},
splitArea: {
show: false
},
splitLine: {
show: false
},
data: myData.map(d => `${d.value}${valueUnit}`)
}
],
xAxis: {
type: 'value',
axisTick: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
show: false
}
},
series:
[
// 背景柱
{
name: '',
type: 'bar',
zlevel: 1,
barGap: '-100%',
barWidth: `${barWidth}px`,
label: {
show: false
},
data: myData.map(() => ({
value: maxValue ? maxValue * 2 : '',
itemStyle: { color: barBgColor, barBorderRadius: 10 }
}))
},
// 彩色柱 给柱形添加渐变色,注意需降低echarts版本4.9.0即可
{
name: 'bar',
type: 'bar',
zlevel: 2,
barWidth: `${barWidth}px`,
data: myData.map(d => ({
...d,
itemStyle: {
normal: {
show: true,
color: new echarts.graphic.LinearGradient(
0, 0, 1, 0,
[
{ offset: 0, color: rankStyColor[0] },// 0% 处的颜色
{ offset: 1, color: rankStyColor[1] } // 100% 处的颜色
]
),
barBorderRadius: 10,
}
},
})),
label: {
normal: {
show: true,
position: [0, '-24px'],
// 排名右边文本样式
textStyle: {
fontSize: nameFontSize.fontSize,
color: nameFontSize.color,
fontFamily: nameFontSize.fontFamily,
fontWeight: nameFontSize.fontWeight
},
formatter: function (a) {
const newNum = a.dataIndex + 1 + pagingNum * (myPage - 1);
const num = newNum < 10 ? '0' + newNum : newNum;
// 拼接成下面的rich 参数 判断左上角排名是图片还是数字进行的处理渲染,要保证分页后图片展示不同且为数字时也需要展示不同
const str = `{${judgeImg ? 'backImg' : 'color'}${judgeImg ? newNum - 1 : (newNum - 1 < 3 ? newNum - 1 : 'Normal')}|${judgeImg ? judgeImgTxt ? `${imgValueUnit}${newNum}` : '' : num}} ${a.name}`
return str;
},
// rich 排名数字 样式
rich: {
...richObj,
colorNormal: {
fontSize: rankNumFontSize,
color: '#fff',
fontWeight: 500,
fontStyle: 'italic'
},
},
}
}
}
]
};
}
render() {
const { width, height, data, config: { pagingNum } } = this.props;
const { myData, myPage } = this.state;
return (
<div className={styles.rankBarSty}>
{myData && myData.length && <ReactEcharts
option={this.option}
style={{ width, height }}
/>}
<div className={styles.paginationSty}>
<Pagination simple itemRender={this.itemRender} current={myPage} defaultPageSize={pagingNum} total={data && data.length} onChange={this.onChange} />
</div>
</div>
);
}
}
export default LoopRankBar;