let icon = `data:image/png;base64,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` const data = [1700, 2800, 3700, 3600]; let barWidth = 30; const offsetX = 20; const offsetY = 10; let domImg = document.createElement('img'); let imgHeight = 60; let imgWidth = 60; domImg.style.height = imgHeight + 'px'; domImg.style.width = imgWidth + 'px'; domImg.height = imgHeight; domImg.width = imgWidth; domImg.src = icon; // 绘制左侧面 const CubeLeft = echarts.graphic.extendShape({ shape: { x: 0, y: 0, }, buildPath: function (ctx, shape) { // 会canvas的应该都能看得懂,shape是从custom传入的 const xAxisPoint = shape.xAxisPoint; // console.log(shape); const c0 = [shape.x, shape.y]; const c1 = [shape.x - offsetX, shape.y - offsetY]; const c2 = [xAxisPoint[0] - offsetX, xAxisPoint[1] - offsetY]; const c3 = [xAxisPoint[0], xAxisPoint[1]]; ctx.moveTo(c0[0], c0[1]).lineTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).closePath(); }, }); // 绘制右侧面 const CubeRight = echarts.graphic.extendShape({ shape: { x: 0, y: 0, }, buildPath: function (ctx, shape) { const xAxisPoint = shape.xAxisPoint; const c1 = [shape.x, shape.y]; const c2 = [xAxisPoint[0], xAxisPoint[1]]; const c3 = [xAxisPoint[0] + offsetX, xAxisPoint[1] - offsetY]; const c4 = [shape.x + offsetX, shape.y - offsetY]; ctx.moveTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).lineTo(c4[0], c4[1]).closePath(); }, }); // 绘制顶面 const CubeTop = echarts.graphic.extendShape({ shape: { x: 0, y: 0, }, buildPath: function (ctx, shape) { const c1 = [shape.x, shape.y]; const c2 = [shape.x + offsetX, shape.y - offsetY]; //右点 const c3 = [shape.x, shape.y - offsetX]; const c4 = [shape.x - offsetX, shape.y - offsetY]; ctx.moveTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).lineTo(c4[0], c4[1]).closePath(); }, }); // 注册三个面图形 echarts.graphic.registerShape('CubeLeft', CubeLeft); echarts.graphic.registerShape('CubeRight', CubeRight); echarts.graphic.registerShape('CubeTop', CubeTop); let option = { backgroundColor: '#012366', tooltip: { trigger: 'axis', formatter: function (params) { let str = params[0].name + ":"; params.filter(function (item) { if (item.componentSubType == "bar") { str += "<br/>" + item.seriesName + ":" + item.value; } }); return str; }, }, legend: { show: true, bottom: '0', itemWidth: 30, itemHeight: 11, itemStyle: { color: 'rgb(12,160,254)' }, textStyle: { fontSize: 22, color: 'rgb(233,240,255)' }, data: ['进港货量'], right: "center", //组件离容器左侧的距离,可以是left,center,right,也可以是像素px和百分比10% bottom: "15px" }, //图表大小位置限制 grid: { x: '13%', x2: '14%', y: '20%', y2: '20%', }, xAxis: [ { // data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月'], data: ['非洲', '欧洲', '日韩', '中东'], offset: 20, //坐标轴 axisLine: { show: false, lineStyle: { width: 1, color: '#214776' }, textStyle: { color: '#fff', fontSize: 20 } }, type: 'category', axisTick: { textStyle: { color: '#fff', fontSize: '16' }, show: false, }, axisLine: { //坐标轴轴线相关设置。数学上的x轴 show: false, lineStyle: { type: 'dashed',//线的类型 虚线 color: '#DEDEDE', }, }, }, { data: ['非洲', '欧洲', '日韩', '中东'], position: 'bottom', offset: -40, // offset: 40, zlevel: 100, //坐标轴 axisLine: { show: false, lineStyle: { width: 1, color: '#214776' }, textStyle: { color: '#fff', fontSize: 20 } }, type: 'category', axisLabel: { formatter: function (a, index) { return `{b|}` }, rich: { b: { widht: imgWidth, height: imgHeight, backgroundColor: { image: domImg } } }, }, axisTick: { textStyle: { color: '#fff', fontSize: '16' }, show: false, }, axisLine: { //坐标轴轴线相关设置。数学上的x轴 show: false, lineStyle: { type: 'dashed',//线的类型 虚线 color: '#DEDEDE', }, }, } ], yAxis: [ { name: '%', nameTextStyle: { color: 'rgb(233,240,255)', fontSize: 22, padding: 10, }, min: 0,//最小 type: 'value', splitLine: { show: false, }, axisTick: { show: true, inside: true, length: 7 }, axisLine: { show: true, lineStyle: { color: 'rgb(195,213,248)' } }, //坐标值标注 axisLabel: { show: true, textStyle: { color: 'rgba(195, 213, 248, 1)', fontSize: 22 } }, } ], series: [ { name: "时长", type: 'custom', renderItem: (params, api) => { const location = api.coord([api.value(0), api.value(1)]); return { type: 'group', children: [ { type: 'CubeLeft', shape: { api, xValue: api.value(0), yValue: api.value(1), x: location[0], y: location[1], xAxisPoint: api.coord([api.value(0), 0]), }, style: { fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: 'rgba(60, 122, 185, 1)' }, { offset: 1, color: 'rgba(51, 152, 188, 1)', }, ]), }, }, { type: 'CubeRight', shape: { api, xValue: api.value(0), yValue: api.value(1), x: location[0], y: location[1], xAxisPoint: api.coord([api.value(0), 0]), }, style: { fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: 'rgba(77, 172, 255, 1)', }, { offset: 1, color: 'rgba(68, 217, 252, 1)', }, ]), }, }, { type: 'CubeTop', shape: { api, xValue: api.value(0), yValue: api.value(1), x: location[0], y: location[1], xAxisPoint: api.coord([api.value(0), 0]), }, style: { fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: 'rgba(56, 227, 255, 1)', }, { offset: 1, color: 'rgba(56, 227, 255, 1)', }, ]), }, }, ], }; }, xAxisIndex: [0, 1], zlevel: 100, //层级 icon是100 data: data } ] } domImg.onload = () => { myChart.setOption(option); }