Gitee地址:折线图源码:
初衷:2021-9-6;练练手,发散一下自己的思维;
结果:达到了练手目的;有时间还可以发散一下其他图表,哈哈;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#charts {
width: 500px;
height: 500px;
background-color: teal;
margin: 100px auto;
}
</style>
</head>
<body>
<div id="charts"></div>
<script type="text/javascript" src="./charts.js"></script>
<script type="text/javascript" src="./index.js"></script>
</body>
</html>
(function () {
function Charts(el) {
this.el = typeof el === 'string' ? document.querySelector(el) : el;
}
Charts.config = {
type: 'line',
drakMode: false,
font: '25px serif',
lineColor: 'orange',
lineWidth: 1,
XAxisColor: 'orange',
YAxisColor: 'orange',
gridColor: 'gray',
drawStartPoints: {
x: 30,
y: 30
},
drawCenter: 60,
textOffsetPoint: 15
}
Charts.prototype = {
init: function () {
var oCanvas = document.createElement('canvas'),
thisElWidth = this.el.clientWidth,
thisElHeight = this.el.clientHeight,
oController = document.createElement('div'),
oYLine = document.createElement('div'),
oXLine = document.createElement('div');
oCanvas.width = thisElWidth;
oCanvas.height = thisElHeight;
oController.width = thisElWidth;
oController.height = thisElHeight;
oController.className = 'chart_controller';
this.oCanvas = oCanvas;
this.oController = oController;
this.oYLine = oYLine;
this.oXLine = oXLine;
this.thisElWidth = thisElWidth;
this.thisElHeight = thisElHeight;
this.render();
this.oController.appendChild(this.oCanvas);
this.el.appendChild(this.oController);
this.bindEvent();
},
bindEvent: function () {
},
render: function () {
var ctx = this.oCanvas.getContext('2d');
switch (Charts.config.type) {
case 'line':
this.drawLine(ctx);
break;
case 'pie':
this.drawPie(ctx);
break;
default:
this.drawLine(ctx);
break;
}
},
drawLine: function (ctx) {
var parmes = this.getDrawParmes();
//绘制XY轴
ctx.lineWidth = 7;
ctx.strokeStyle = 'orange';
ctx.lineCap = 'square';
//X主轴
ctx.beginPath();
ctx.moveTo(parmes.XY_startPoints.x, parmes.XY_startPoints.y);
ctx.lineTo(parmes.X_endPoints.x, parmes.X_endPoints.y);
ctx.stroke();
//Y主轴
ctx.beginPath();
ctx.moveTo(parmes.XY_startPoints.x, parmes.XY_startPoints.y);
ctx.lineTo(parmes.Y_endPoints.x, parmes.Y_endPoints.y);
ctx.stroke();
//绘制X轴上面的步长标记点
this._drawStepAndText('X', ctx, parmes);
this._drawStepAndText('Y', ctx, parmes);
this._drawDataLine(ctx, parmes);
},
/**
* 绘制数据折线
*/
_drawDataLine: function (ctx, parmes) {
var xys = this._dataToTrueXY(parmes),
item,
_this = this,
textOffset = 10;
ctx.beginPath();
ctx.moveTo(xys[0].x, xys[0].y);
for (var i = 0; i < xys.length; i++) {
item = xys[i];
(function (i, item) {
setTimeout(() => {
ctx.lineTo(item.x, item.y);
ctx.fillText(_this.data.data[i].value, item.x + textOffset, item.y - textOffset);
ctx.stroke();
}, i * 200);
})(i, item)
}
},
/**
* 数据转换成真实的XY值
*/
_dataToTrueXY(parmes) {
var res = [],
item,
data = this.data.data,
XAxisindex,//拿到数据中和X轴数据中对应的下标
xstep = parmes.x_step,
ystep = parmes.y_step,
ytag = parmes.y_step_tag;
for (var i = 0; i < data.length; i++) {
item = data[i];
XAxisindex = this.data.xAxis.indexOf(item.xAxis) + 1;
var temp = {
x: XAxisindex * xstep,
y: (ystep * data.length) - ystep * (item.value / ytag) + ystep
}
res.push(temp);
}
return res;
},
/**
* 折线图绘制步长和文本
* @param {*} tag
* @param {*} ctx
* @param {*} len
* @param {*} parmes
*/
_drawStepAndText: function (tag, ctx, parmes) {
var YAxisMax = parmes.xAxisLength * parmes.y_step;
ctx.beginPath();
ctx.lineCap = 'square';
ctx.fillStyle = 'white';
for (var i = 1; i < parmes.xAxisLength + 1; i++) {
if (tag.toUpperCase() == 'X') {
ctx.beginPath();
ctx.lineWidth = Charts.config.lineWidth;
var tempX = i * parmes.x_step;
ctx.moveTo(tempX, parmes.X_endPoints.y);
ctx.strokeStyle = Charts.config.gridColor;
ctx.lineTo(tempX, Charts.config.drawStartPoints.y);
ctx.fillText(this.data.xAxis[i - 1], tempX - Charts.config.textOffsetPoint, (parmes.X_endPoints.y + parmes.stepWidth + Charts.config.textOffsetPoint));
ctx.stroke();
ctx.strokeStyle = Charts.config.XAxisColor;
} else if (tag.toUpperCase() == 'Y') {
ctx.beginPath();
ctx.lineWidth = Charts.config.lineWidth;
var tempY = (i + 1) * parmes.y_step;
ctx.strokeStyle = Charts.config.gridColor;
ctx.moveTo(parmes.xAxisLength * parmes.y_step, tempY);
ctx.lineTo(parmes.Y_endPoints.x, tempY);
ctx.fillText(Math.round(parmes.y_step_tag * parmes.yAxisLength - parmes.y_step_tag * i), 0, tempY);
ctx.stroke();
ctx.strokeStyle = Charts.config.YAxisColor;
}
}
ctx.fillStyle = '';
},
getMaxYaxis: function (data) {
if (!data) {
throw TypeError('data not is array');
}
var max = 0,
item;
for (var index in data) {
item = data[index];
max = max > item.value ? max : item.value;
}
return max;
},
/**
* 绘制参数
* 包括起始点、结束点、X轴步长、Y轴步长
*
* @returns object
*/
getDrawParmes: function () {
var fn = function (num, len) {
return num / len;
}
var xAxisLength = this.data.xAxis.length,//X轴数据长度
yAxisLength = this.data.data.length,
max_yAxis = this.getMaxYaxis(this.data.data) > this.thisElHeight ? this.getMaxYaxis(this.data.data) : this.thisElHeight,//从数据中找到最大的Y轴上数据点
XY_startPoints = { x: Charts.config.drawStartPoints.x, y: this.thisElHeight - Charts.config.drawStartPoints.y },//XY轴共同的绘制起始点
X_endPoints = { x: this.thisElWidth - Charts.config.drawCenter, y: this.thisElHeight - Charts.config.drawCenter / 2 },//X轴绘制结束点
Y_endPoints = { x: Charts.config.drawStartPoints.x, y: Charts.config.drawStartPoints.y },//Y轴绘制结束点
x_step = Math.floor((this.thisElWidth - Charts.config.drawCenter) / xAxisLength),//X轴,绘制月份+小竖线分割标志
y_step = Math.floor((this.thisElHeight - Charts.config.drawCenter) / yAxisLength),//Y轴步长
y_step_no_floor = (this.thisElHeight - Charts.config.drawCenter) / yAxisLength,//Y轴步长
y_step_tag = fn(max_yAxis, yAxisLength),//Y轴每个步长文本点
stepWidth = 10;
return {
xAxisLength,
yAxisLength,
max_yAxis: max_yAxis,
XY_startPoints: XY_startPoints,
X_endPoints: X_endPoints,
Y_endPoints: Y_endPoints,
x_step: x_step,
y_step: y_step,
y_step_no_floor,
y_step_tag,
stepWidth
}
},
drawPie: function (ctx) {
},
setOption: function (data) {
this.data = data;
this.init();
}
}
window.Charts = Charts;
})()
var line = {
xAxis: [
'2021-1',
'2021-2',
'2021-3',
'2021-4',
'2021-5',
'2021-6',
'2021-7',
'2021-8',
'2021-9',
'2021-10',
'2021-11',
'2021-12',
],
data: [
{
id: 1,
value: 300,
text: '我爱中国1',
xAxis: '2021-1'
},
{
id: 2,
value: 72,
text: '我爱中国2',
xAxis: '2021-2'
},
{
id: 3,
value: 350,
text: '我爱中国3',
xAxis: '2021-3'
},
{
id: 4,
value: 360,
text: '我爱中国4',
xAxis: '2021-4'
},
{
id: 5,
value: 180,
text: '我爱中国5',
xAxis: '2021-5'
},
{
id: 6,
value: 250,
text: '我爱中国6',
xAxis: '2021-6'
},
{
id: 7,
value: 252,
text: '我爱中国7',
xAxis: '2021-7'
},
{
id: 8,
value: 36,
text: '我爱中国8',
xAxis: '2021-8'
},
{
id: 9,
value: 324,
text: '我爱中国9',
xAxis: '2021-9'
},
{
id: 10,
value: 36,
text: '我爱中国10',
xAxis: '2021-10'
},
{
id: 11,
value: 396,
text: '我爱中国11',
xAxis: '2021-11'
},
{
id: 12,
value: 432,
text: '我爱中国12',
xAxis: '2021-12'
}
]
}
// Charts.config.type = 'pie';
var oChart = document.getElementById('charts');
var myChart = new Charts('#charts');
myChart.setOption(line);