因為公司的業(yè)務(wù)需要,highcharts&echarts這些圖表庫的樣式不符合設(shè)計的要求锉罐,所以在考慮了不用考慮ie8等瀏覽器的情況下驻粟,選擇canvas封裝了一個支持個性化配置的柱狀圖瘾晃。希望有需要類似圖的前端伙伴较性,可以有用撵割。
因為個性化弄诲,需要各種自定義大小顏色的參數(shù)菱鸥,所以我把參數(shù)分為了4類——基礎(chǔ)參數(shù)、坐標(biāo)軸抚垄、柱子數(shù)據(jù)蜕窿、增強(qiáng)屬性。
-
先看個效果圖
-
接入方式
- html中放置一個canvas
<canvas id="canvas"></canvas>
引入下面的function drawHistogram
執(zhí)行方法
drawHistogram(chartsConfigObj);
-
參數(shù)解釋
- 第一層參數(shù)解釋
/** * 第一層參數(shù) * @param {basicData} 必傳呆馁,基礎(chǔ)參數(shù) * @param {axisData} 必傳桐经,坐標(biāo)軸參數(shù) * @param {columnData} 必傳,柱子數(shù)據(jù) * @param {enhancementAttr} 非必傳浙滤,一些增強(qiáng)屬性 */
- 第二層參數(shù)
let { basicData: { wrapEleId, width, height }, axisData: { basic: { axislineWidth, axisColor, axisTextColor, axisTextFont, }, axisX: { axisXStart, axisXWidth, axisXTextDistance }, axisY: { axisYStart, axisYWidth, axisYIntervalNum, axisYTextDistance, axisYMaxNum } }, columnData: { eachColumnWidth, spaceDistance, columnMaxHeight, columnColor, firstColumnStartX, firstColumnStartY }, graphs } = chartsConfigObj; const {enhancementAttr} = chartsConfigObj; let { isColumnNeedRadius, columnGradientData, isRemoveAxisArrow, horizontalLineObj } = enhancementAttr || {}; let { gradientStartColor, gradientEndColor } = columnGradientData || {}; let { horizontalLineColor, horizontalLineDistance } = horizontalLineObj || {}; /** * 具體的每個柱狀圖參數(shù) * @param {wrapEleId} canvas畫布id * @param {width} 畫布寬 * @param {height} 畫布高 * @param {eachColumnWidth} 一個柱子的寬度 * @param {spaceDistance} 柱子間的間距 * @param {firstColumnStartX} 第一個柱子左下角的X軸坐標(biāo) * @param {firstColumnStartY} 第一個柱子左下角的Y軸坐標(biāo) * @param {columnMaxHeight} 柱子最大高度 * @param {axislineWidth} 坐標(biāo)軸的線的寬度 * @param {axisXStart} 坐標(biāo)軸X軸起點坐標(biāo) * @param {axisYStart} 坐標(biāo)軸Y軸起點坐標(biāo) * @param {axisXWidth} 坐標(biāo)軸X軸長度 * @param {axisYWidth} 坐標(biāo)軸Y軸長度 * @param {axisXTextDistance} 坐標(biāo)軸X軸文字距離X軸垂直方向的偏移量 * @param {axisYTextDistance} 坐標(biāo)軸Y軸水平方向的偏移量 * @param {axisYIntervalNum} 左邊軸y軸間隔 * @param {axisYMaxNum} 左邊軸y軸標(biāo)尺最大值 * @param {axisColor} 坐標(biāo)軸線顏色 * @param {axisTextColor} 坐標(biāo)軸文本顏色 * @param {axisTextFont} 坐標(biāo)軸文本fontSize阴挣、fontFamily * @param {columnColor} 柱狀圖顏色 * @param {graphs} 圖表數(shù)據(jù)-數(shù)組,[{x:纺腊,y:},...] * @param {columnGradientData} 柱子漸變色信息畔咧,不需要漸變就不傳此參數(shù) * @param {gradientStartColor} 漸變開始色(靠近x軸) * @param {gradientEndColor} 漸變結(jié)束色 * @param {isColumnNeedRadius} 柱子是否需要圓角 * @param {gradientEndColor} 漸變結(jié)束色 * @param {gradientEndColor} 漸變結(jié)束色 * @param {gradientEndColor} 漸變結(jié)束色 * @param {horizontalLineObj} 水平虛線背景參數(shù),不需要則不傳{color,space} */
功能實現(xiàn)代碼
export default function drawHistogram(chartsConfigObj) {
let {
basicData: {
wrapEleId,
width,
height
},
axisData: {
basic: {
axislineWidth,
axisColor,
axisTextColor,
axisTextFont,
},
axisX: {
axisXStart,
axisXWidth,
axisXTextDistance
},
axisY: {
axisYStart,
axisYWidth,
axisYIntervalNum,
axisYTextDistance,
axisYMaxNum
}
},
columnData: {
eachColumnWidth,
spaceDistance,
columnMaxHeight,
columnColor,
firstColumnStartX,
firstColumnStartY
},
graphs
} = chartsConfigObj;
const {enhancementAttr} = chartsConfigObj;
let {
isColumnNeedRadius,
columnGradientData,
isRemoveAxisArrow,
horizontalLineObj
} = enhancementAttr || {};
let {
gradientStartColor,
gradientEndColor
} = columnGradientData || {};
let {
horizontalLineColor,
horizontalLineDistance
} = horizontalLineObj || {};
horizontalLineColor = horizontalLineColor ? horizontalLineColor : '#eee';
horizontalLineDistance = horizontalLineDistance ? horizontalLineDistance: 5;
isRemoveAxisArrow = isRemoveAxisArrow ? isRemoveAxisArrow : false;
var canvas = document.getElementById(wrapEleId);
var context = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
context.beginPath();
//畫x軸
context.beginPath();
context.moveTo(axisXStart, axisYStart);
context.lineTo(axisXStart + axisXWidth, axisYStart);
context.strokeStyle = axisColor;
context.lineWidth = axislineWidth;
context.stroke();
context.beginPath();
if (!isRemoveAxisArrow) {
context.moveTo(axisXStart + axisXWidth - 6, axisYStart-6);
context.lineTo(axisXStart + axisXWidth, axisYStart);
context.lineTo(axisXStart + axisXWidth - 6, axisYStart+6);
context.strokeStyle = axisColor;
context.lineWidth = axislineWidth;
context.stroke();
}
//畫y軸
context.beginPath();
var axisYEnd = height - (height - axisYStart + axisYWidth);
context.moveTo(axisXStart, axisYStart);
context.lineTo(axisXStart, axisYEnd);
context.strokeStyle = axisColor;
context.lineWidth = axislineWidth;
context.stroke();
context.beginPath();
if (!isRemoveAxisArrow) {
context.moveTo(axisXStart - 6, axisYEnd + 6);
context.lineTo(axisXStart, axisYEnd);
context.lineTo(axisXStart + 6, axisYEnd + 6);
context.strokeStyle = axisColor;
context.lineWidth = axislineWidth;
context.stroke();
}
//畫y軸上的數(shù)字
var axisYNum = axisYMaxNum / axisYIntervalNum;
var axisYLength = columnMaxHeight / axisYNum;
for (var j = 0; j <= axisYNum; j++) {
context.beginPath();
context.moveTo(axisXStart, axisYStart);
context.font = axisTextFont;
context.textAlign = "center";
context.fillStyle = axisTextColor;
context.fillText(j*axisYIntervalNum,axisXStart - 15, axisYStart - j * axisYLength + axisYTextDistance);
context.beginPath();
context.moveTo(axisXStart, axisYStart - j * axisYLength);
context.lineTo(axisXStart+5, axisYStart - j * axisYLength);
context.strokeStyle = axisColor;
context.lineWidth = axislineWidth;
context.stroke();
if (horizontalLineObj && j !== 0) {
context.beginPath();
context.moveTo(axisXStart, axisYStart - j * axisYLength);
context.lineTo(axisXStart+axisXWidth, axisYStart - j * axisYLength);
context.setLineDash([horizontalLineObj.space || 10]);
context.strokeStyle = horizontalLineObj.color || '#eee';
context.stroke();
}
}
context.beginPath();
//畫柱狀圖
var columnLength = graphs.length;
for (var i = 0; i < columnLength; i++) {
var colData = graphs[i];
var colStratX = firstColumnStartX+(i*spaceDistance)+(i*eachColumnWidth);
var colStratY = height - (height - firstColumnStartY + (colData.y/100) * columnMaxHeight);
if(isColumnNeedRadius) {
const r = eachColumnWidth / 2;
const w = eachColumnWidth;
const h = -((colData.y/100) * columnMaxHeight);
const x = colStratX;
const y = firstColumnStartY;
context.beginPath();
context.moveTo(x + r, y);
context.arcTo(x + w, y, x + w, y + h, r);
context.arcTo(x + w, y + h, x, y + h, r);
context.arcTo(x, y + h, x, y, r);
context.arcTo(x, y, x + w, y, r);
context.closePath();
} else {
context.beginPath();
context.moveTo(colStratX, firstColumnStartY);
context.lineTo(colStratX, colStratY);
context.lineTo(colStratX+eachColumnWidth, colStratY);
context.lineTo(colStratX+eachColumnWidth, firstColumnStartY);
context.closePath();
}
//需要漸變
if (columnGradientData) {
var grad = context.createLinearGradient(0, firstColumnStartY, 0,colStratY);
grad.addColorStop(0, gradientStartColor); // 綠
grad.addColorStop(1, gradientEndColor); // 紫
context.fillStyle = grad;
} else {
context.fillStyle = columnColor;
}
context.fill();
context.font = axisTextFont;
context.textAlign="center";
context.fillStyle = axisTextColor;
context.fillText(colData.x, colStratX+eachColumnWidth/2, firstColumnStartY + axisXTextDistance);
}
}
- 例子數(shù)據(jù)
const chartsConfigObj = {
basicData: {
wrapEleId: 'canvas',
width: 860,
height: 400
},
axisData: {
basic: {
axislineWidth: 1,
axisColor: '#999',
axisTextColor: '#666',
axisTextFont: '12px PingFangSC-Regular',
},
axisX: {
axisXStart: 26,
axisXWidth: 850,
},
axisY: {
axisYStart: 365,
axisYWidth: 190,
axisYIntervalNum: 20,
axisYTextDistance: 2,
axisYMaxNum: 100
}
},
columnData: {
eachColumnWidth: 14,
spaceDistance: 30,
columnMaxHeight: 156,
columnColor: '#f00',
firstColumnStartX: 50,
firstColumnStartY: 365
},
enhancementAttr: {
isColumnNeedRadius: true,
columnGradientData: {
gradientStartColor: '#35E1A0',
gradientEndColor: '#29CDC0'
},
horizontalLineObj: {
horizontalLineColor: '#999',
horizontalLineDistance: 5
},
isRemoveAxisArrow: true
},
graphs: [
{
'x': '2011',
'y': '100'
}, {
'x': '2012',
'y': '90'
}, {
'x': '2013',
'y': '60'
}, {
'x': '2014',
'y': '90'
}, {
'x': '2015',
'y': '70'
}, {
'x': '2016',
'y': '10'
}, {
'x': '2011',
'y': '100'
}, {
'x': '2012',
'y': '90'
}, {
'x': '2013',
'y': '60'
}, {
'x': '2014',
'y': '90'
}, {
'x': '2015',
'y': '70'
}, {
'x': '2016',
'y': '10'
}, {
'x': '2011',
'y': '100'
}, {
'x': '2012',
'y': '90'
}, {
'x': '2013',
'y': '60'
}, {
'x': '2014',
'y': '30'
}, {
'x': '2015',
'y': '10'
}, {
'x': '2016',
'y': '95'
}
]
};