简介
用柱状图显示排名,y轴需要表明排名、头像、名字,如下图
查看echarts文档,可是使用如下属性设置图片:
backgroundColor: {
image: 'xxx/xxx.png'
// 这里可以是图片的 URL,
// 或者图片的 dataURI,
// 或者 HTMLImageElement 对象,
// 或者 HTMLCanvasElement 对象。
}
注意
|使用 HTMLImageElement 对象时,只能使用标签
|并且
在dom元素中是真实存在的,所以使用时需要将其隐藏,并且使用的border-radius: 50%不会生效
<div class="echarts-bar">
<div ref="barChart" class="bar-box"></div>
<img ref="imgRef" src="/@/assets/images/header.jpg" class="avatar-img" />
</div>
.avatar-img {
display: block;
border-radius: 50%;
width: 20px;
height: 20px;
opacity: 0;
}
formatter: function (value, index) {
imgSrc.value = imgs.value[value];
if (index + 1 == 1) {
return `{index1|${index + 1}} {a|} ${value}`;
} else if (index + 1 == 2) {
return `{index2|${index + 1}} {a|} ${value}`;
} else if (index + 1 == 3) {
return `{index3|${index + 1}} {a|} ${value}`;
} else {
return `{index|${index + 1}} {a|} ${value}`;
}
},
rich: {
index1: {
fontSize: 20,
color: 'rgb(242, 165, 11)',
fontWeight: 500,
},
index2: {
fontSize: 20,
color: '#ccc',
fontWeight: 500,
},
index3: {
fontSize: 20,
color: 'rgb(242, 111, 11)',
fontWeight: 500,
},
index: {
fontSize: 20,
color: 'rgb(121, 120, 120)',
fontWeight: 500,
},
a: {
backgroundColor: {
image: imgSrc.value, //将图片替换成每个人的头像,并未成功
// image:'https://xxx/xxx.png', //使用固定的图片地址 可行
// image: imgRef.value, //使用<img>元素 可行
},
height: 20,
width: 20,
borderRadius: 10,
overflow: 'hidden',
},
}
以上方法,使用固定的图片地址可行,img元素也可行,但是图片并未根据设置的borderRadius: 10而显示为圆形头像
根据杨帆起航_200的方法,对图片进行处理
function getImgData(imgSrc) {
var fun = function (resolve) {
const canvas = document.createElement('canvas');
const contex = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = '';
console.log('contex', contex);
if (!contex) return;
img.onload = function () {
let center = {
x: img.width / 2,
y: img.height / 2,
};
var diameter = img.width;
canvas.width = diameter;
canvas.height = diameter;
contex.clearRect(0, 0, diameter, diameter);
contex.save();
contex.beginPath();
let radius = img.width / 2;
contex.arc(radius, radius, radius, 0, 2 * Math.PI); //画出圆
contex.clip(); //裁剪上面的圆形
contex.drawImage(
img,
center.x - radius,
center.y - radius,
diameter,
diameter,
0,
0,
diameter,
diameter,
); // 在刚刚裁剪的园上画图
contex.restore(); // 还原状态
resolve(canvas.toDataURL('image/png', 1));
};
img.src = imgSrc;
// console.log('img.src', img.src);
};
var promise = new Promise(fun);
return promise;
}
但是此时,图片依旧为只能同一张图片,并不能显示每个人的图像,如果有大佬有可行方法,辛苦留言一下 以下为完整代码:
<template>
<div class="echarts-bar">
<div ref="barChart" class="bar-box"></div>
<img
ref="imgRef"
src="/@/assets/images/header.jpg"
class="avatar-img" />
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch, onMounted, onBeforeMount, defineComponent, nextTick } from 'vue';
import * as echarts from 'echarts';
import { Item } from './data';
import headerImg from '/@/assets/images/header.jpg';
const props = defineProps<{
title: String;
subtext: String;
barData: Item[];
barColor: String;
gridX: String;
}>();
const refData = ref();
let barChart = ref();
let xData = ref<any>([]);
let yData = ref<any>([]);
let imgs = ref<any>([]);
let imgSrc = ref<any>();
let imgRef = ref();
function dataHandle() {
xData.value = [];
yData.value = [];
props.barData.forEach((item) => {
yData.value.push(item.name);
xData.value.push(Number(item.gmv).toFixed(2));
// imgs.value[item.name] = item.avatarUrl;
imgs.value.push({ [item.name]: item.avatarUrl });
});
getImgsSrc();
theEcharse();
}
async function getImgsSrc() {
for (let key in imgs.value) {
imgs.value[key] = await getImgData(imgs.value[key]);
console.log('hahah', imgs.value[key]);
}
// theEcharse();
console.log('imgs', imgs.value);
}
function getImgData(imgSrc) {
var fun = function (resolve) {
const canvas = document.createElement('canvas');
const contex = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = '';
console.log('contex', contex);
if (!contex) return;
img.onload = function () {
let center = {
x: img.width / 2,
y: img.height / 2,
};
var diameter = img.width;
canvas.width = diameter;
canvas.height = diameter;
contex.clearRect(0, 0, diameter, diameter);
contex.save();
contex.beginPath();
let radius = img.width / 2;
contex.arc(radius, radius, radius, 0, 2 * Math.PI); //画出圆
contex.clip(); //裁剪上面的圆形
contex.drawImage(
img,
center.x - radius,
center.y - radius,
diameter,
diameter,
0,
0,
diameter,
diameter,
); // 在刚刚裁剪的园上画图
contex.restore(); // 还原状态
resolve(canvas.toDataURL('image/png', 1));
};
img.src = imgSrc;
};
var promise = new Promise(fun);
return promise;
}
async function theEcharse() {
let chart = barChart.value;
let myChart;
nextTick(() => {
myChart = echarts.init(chart);
myChart.clear(); // 清除画布
myChart.setOption(
(option = {
tooltip: {},
legend: {},
title: {
text: [`${props.title} {a|(${props.subtext})}`],
// subtext: props.subtext,
top: -5,
textStyle: {
rich: {
a: {
color: '#bbb',
fontSize: 16,
},
},
},
subtextStyle: {
fontSize: 16,
},
},
grid: {
x: props.gridX, //靠左
},
yAxis: {
type: 'category',
inverse: true, //排序
data: yData.value,
z: 4,
axisLabel: {
show: true,
fontSize: 14,
textStyle: {
align: 'left', //**
},
margin: 70, //刻度标签与轴线之间的距离。
formatter: function (value, index) {
imgSrc.value = imgs.value[value];
console.log('imgSrc.value', imgSrc.value);
if (index + 1 == 1) {
return `{index1|${index + 1}} {a|} ${value}`;
} else if (index + 1 == 2) {
return `{index2|${index + 1}} {a|} ${value}`;
} else if (index + 1 == 3) {
return `{index3|${index + 1}} {a|} ${value}`;
} else {
return `{index|${index + 1}} {a|} ${value}`;
}
},
rich: {
index1: {
fontSize: 20,
color: 'rgb(242, 165, 11)',
fontWeight: 500,
},
index2: {
fontSize: 20,
color: '#ccc',
fontWeight: 500,
},
index3: {
fontSize: 20,
color: 'rgb(242, 111, 11)',
fontWeight: 500,
},
index: {
fontSize: 20,
color: 'rgb(121, 120, 120)',
fontWeight: 500,
},
a: {
backgroundColor: {
image: imgSrc.value,
// image:
// 'https://xxx/xxx.png',
// image: imgRef.value,
},
height: 20,
width: 20,
borderRadius: 10,
overflow: 'hidden',
},
},
},
},
xAxis: {
axisLabel: {
// X 坐标轴标签相关设置,写在xAxis里面
interval: 0, //全部标签显示
rotate: '45', //标签倾斜度数
},
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
},
},
},
series: [
{
realtimeSort: true,
name: '',
type: 'bar',
data: xData.value,
color: props.barColor,
barCategoryGap: '60%',
// barWidth: '30px',
label: {
show: true,
position: 'right',
valueAnimation: true,
},
itemStyle: {
color: props.barColor,
},
},
],
legend: {
show: false,
},
}),
);
});
var option;
option && myChart.setOption(option);
// flag 阻止重复添加事件
// if (this.flag) return;
window.addEventListener('resize', () => {
myChart.resize();
});
// this.flag = true;
}
onBeforeMount(() => {});
onMounted(() => {
dataHandle();
});
</script>
<style lang="less" scoped>
.echarts-bar {
width: 100%;
height: 100%;
padding: 0.1rem;
box-sizing: border-box;
display: flex;
align-items: center;
.bar-box {
width: 100%;
height: 100%;
}
}
</style>
如果想让y轴文字有背景颜色,使用pading给文字增加内边距,如果想要分割线,使用borderWidth和width,如果想换行,使用\n
代码如下
axisLabel: {
show: true,
fontSize: 14,
textStyle: {
align: 'right', //**
},
margin: 70, //刻度标签与轴线之间的距离。
formatter: function (value, index) {
// return `{index|${index + 1}} ${value}`;
return '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ';
},
rich: {
index: {
fontSize: 16,
color: '#fff',
fontWeight: 600,
padding: [3, 6, 3, 6], //文字块内边距,[3,4,3,4]
borderRadius: 16,
backgroundColor: '#1F54D1',
},
a: {
//标题名的样式
color: '#6E7079',
lineHeight: 22, //标签的表格的上高度
align: 'center', //文字水平对齐方式
},
hr: {
//分割线
borderColor: '#8C8D8E',
width: '100%',
borderWidth: 1,
height: 0,
},
b: {
//数据名的样式
color: '#4C5058',
fontSize: 14,
fontWeight: 'bold',
lineHeight: 33, //表格高度,行高
},
per: {
//自定义百分比的样式
color: '#fff',
backgroundColor: '#4C5058',
padding: [3, 4], //文字块内边距,[3,4,3,4]
borderRadius: 4,
},
},
},
效果图如下:
需求变更:排名需要加一个蓝色背景圆 如果使用上面方法给文字加内边距,由于文字字体大小不一样(不是指font-size),例如:大小不明显的1和6,明显的1和10,所以每个数字的背景并不是都是标准圆,所以采用背景图片的方法
代码如下:直接使用地址时,本地可以正常显示,但是打包到显示时,背景图片不显示,且显示请求背景图片资源报错
猜测原因:打包之后,image: '/@/assets/images/echarts-circle.png'被认为是线上图片,所以会到https://xxxx.cn/assets/images/echarts-circle.png请求图片
rich: {
index: {
fontSize: 16,
color: '#fff',
align: 'center',
fontWeight: 600,
// padding: [3, 6.5, 3, 6.5], //文字块内边距,[3,4,3,4]
borderRadius: 16,
// backgroundColor: '#1F54D1',
backgroundColor: {
image: '/@/assets/images/echarts-circle.png',
},
height: 25,
width: 25,
overflow: 'hidden',
},
},
改为如下代码即可
import bgImg from '/@/assets/images/echarts-circle.png';
......
rich: {
index: {
fontSize: 16,
color: '#fff',
align: 'center',
fontWeight: 600,
// padding: [3, 6.5, 3, 6.5], //文字块内边距,[3,4,3,4]
borderRadius: 16,
// backgroundColor: '#1F54D1',
backgroundColor: {
image: bgImg,
},
height: 25,
width: 25,
overflow: 'hidden',
},
},