作者: | 来源:互联网 | 2023-09-24 15:28
示例代码托管在:http:www.github.comdashnowordsblogs博客园地点:《大史住在大前端》原创博文目次华为云社区地点:【你要的前端打怪晋级指南】[TOC]
示例代码托管在:
http://www.github.com/dashnowords/blogs
博客园地点:《大史住在大前端》原创博文目次
华为云社区地点:【你要的前端打怪晋级指南】
[TOC]
一. 任务说明
运用原生canvasAPI
绘制柱状图。(柱状图截图来自于百度Echarts官方示例库【检察示例链接】)
二. 重点提醒
柱状图或许是最轻易完成的图表范例了,矩形的部份直接运用fillRect()
来绘制即可,为了将坐标轴标签笔墨绘制在小分割线中心,须要用measureText()
来丈量文本的宽度,然后举行响应的偏移,不然直接绘制的话笔墨的左边境会和直线相对齐。其他部份都是一些基础API的运用,愿望列位小伙伴经由过程做演习来熟习这些API的用法。
三. 示例代码
提醒:代码中将一般图表参数直接写在了函数里(也就是所谓的“魔鬼数字”),这类做法是不首倡的,由于它违反了开辟的基础准绳之一“开放关闭准绳”。假如你运用过Echarts
图表库就会发明,图表中险些一切要素都可以经由过程参数来定制,此处只须要关注canvasAPI
的完成要领即可。
/**
* 猎取canvas画图上下文
* @type {[type]}
*/
const canvas = document.getElementById('canvas');
const cOntext= canvas.getContext('2d');
//画图设置
let optiOns= {
chartZone:[50,50,1000,700],//标识画图地区
yAxisLabel:['0','100','200','300','400'],//标示Y轴坐标
yMax:400,//Y轴最大值
xAxisLabel:['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],//X轴坐标
data:[10,50,200,330,390,320,220],//柱状图数据
barStyle:{
width:70,//柱状图宽度
color:'#1abc9c'//柱状图色彩
}
}
/*Echarts运用时,会挪用实例要领echartsInstance.setOptions(options)来启动画图*/
drawBarChart(options);
/**
* 绘制柱状图
*/
function drawBarChart(options) {
drawAxis(options); //绘制坐标轴
drawYLabels(options); //绘制y轴坐标
drawXLabels(options); //绘制x轴坐标
//drawData(options);//绘制柱状图
drawDataGradient(options);//绘制渐变色柱状图
}
/**
* 绘制坐标轴
*/
function drawAxis(options) {
let chartZOne= options.chartZone;
context.strokeWidth = 4;
context.strokeStyle = '#353535';
context.moveTo(chartZone[0],chartZone[1]);
context.lineTo(chartZone[0],chartZone[3]); //y轴总高从50到700
context.lineTo(chartZone[2],chartZone[3]); //x轴总长从50到1000
context.stroke();
}
/**
* 绘制y轴坐标
*/
function drawYLabels(options) {
let labels = options.yAxisLabel;
let yLength = (options.chartZone[3] - options.chartZone[1])*0.98;
let gap = yLength / (labels.length - 1); labels.forEach(function (label, index) {
//绘制坐标笔墨
let offset = context.measureText(label).width + 20;
context.strokeStyle = '#eaeaea';
context.fOnt= '16px';
context.fillText(label, options.chartZone[0] - offset ,options.chartZone[3] - index * gap);
//绘制小距离
context.beginPath();
context.strokeStyle = '#353535';
context.moveTo(options.chartZone[0] - 10, options.chartZone[3] - index * gap);
context.lineTo(options.chartZone[0], options.chartZone[3] - index * gap);
context.stroke();
//绘制辅助线
context.beginPath();
context.strokeStyle = '#eaeaea';
context.strokeWidth = 2;
context.moveTo(options.chartZone[0], options.chartZone[3] - index * gap);
context.lineTo(options.chartZone[2], options.chartZone[3] - index * gap);
context.stroke();
});
}
/**
* 绘制x轴坐标
*/
function drawXLabels(options) {
let labels = options.xAxisLabel;
let xLength = (options.chartZone[2] - options.chartZone[0])*0.96;
let gap = xLength / labels.length; labels.forEach(function (label, index) {
//绘制坐标笔墨
let offset = context.measureText(label).width;
context.strokeStyle = '#eaeaea';
context.fOnt= '18px';
context.fillText(label, options.chartZone[0] + (index + 1) * gap - offset ,options.chartZone[3] + 20);
//绘制小距离
context.beginPath();
context.strokeStyle = '#353535';
context.moveTo(options.chartZone[0] + (index + 1) * gap - offset / 2 ,options.chartZone[3]);
context.lineTo(options.chartZone[0] + (index + 1) * gap - offset / 2,options.chartZone[3]+5);
context.stroke();
//存储偏移量
options.offsetXLabel = offset / 2;
});
}
/**
* 绘制数据
*/
function drawData(options) {
let data = options.data;
let xLength = (options.chartZone[2] - options.chartZone[0])*0.96;
let yLength = (options.chartZone[3] - options.chartZone[1])*0.98;
let gap = xLength / options.xAxisLabel.length;
//绘制矩形
data.forEach(function (item, index) {
context.fillStyle = options.barStyle.color || '#1abc9c'; //02BAD4
let x0 = options.chartZone[0] + (index + 1) * gap - options.barStyle.width / 2 - options.offsetXLabel;
let height = item / options.yMax * (options.chartZone[3] - options.chartZone[1])*0.98;
let y0 = options.chartZone[3] - height;
let width = options.barStyle.width;
context.fillRect(x0,y0,width,height);
});
}
/**
* 绘制线性渐变色柱状图
*/
function drawDataGradient(options) {
let data = options.data;
let xLength = (options.chartZone[2] - options.chartZone[0])*0.96;
let yLength = (options.chartZone[3] - options.chartZone[1])*0.98;
let gap = xLength / options.xAxisLabel.length;
//建立渐变色
let fillStyleGradient = context.createLinearGradient(50,50,50,700);
fillStyleGradient.addColorStop(0, options.barStyle.color);
fillStyleGradient.addColorStop(1, 'rgba(1,176,241,0.6)');
//绘制矩形
data.forEach(function (item, index) {
context.fillStyle = fillStyleGradient;
let x0 = options.chartZone[0] + (index + 1) * gap - options.barStyle.width / 2 - options.offsetXLabel;
let height = item / options.yMax * (options.chartZone[3] - options.chartZone[1])*0.98;
let y0 = options.chartZone[3] - height;
let width = options.barStyle.width;
context.fillRect(x0,y0,width,height);
});
}
浏览器中可检察结果:
四. 思考题
假如愿望在坐标轴末尾加一个箭头,须要怎么做呢?
/*x轴箭头示例*/
//1.options中增添箭头色彩和大小的设置
let optiOns= {
//...
axisArrow:{
size:2,
color:'#DA5961'
}
}
//箭头绘制函数
/**
* x轴绘制箭头
*/
function drawArrow(options) {
let factor = options.axisArrow.size;//猎取箭头大小因子
context.save();//保留当前设置的画图上下文
context.translate(options.chartZone[2], options.chartZone[3]);//挪动坐标系原点至x轴末尾
context.beginPath();//最先绘制箭头
context.moveTo(0,0);//挪动至新原点
context.lineTo(2 * factor,-3 * factor);
context.lineTo(10 * factor,0);
context.lineTo(2 * factor, 3 * factor);
context.lineTo(0,0);
context.globalAlpha = 0.7; //设置添补色透明度
context.fillStyle = options.axisArrow.color;//猎取箭头色彩
context.fill();//添补箭头途径
context.restore();//恢复画图上下文款式设置
}
箭头结果:
y轴的箭头请自行完成即可。