热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【带着canvas去漂泊】(1)绘制柱状图

示例代码托管在:http:www.github.comdashnowordsblogs博客园地点:《大史住在大前端》原创博文目次华为云社区地点:【你要的前端打怪晋级指南】[TOC]

《【带着canvas去漂泊】(1)绘制柱状图》

示例代码托管在:
http://www.github.com/dashnowords/blogs

博客园地点:《大史住在大前端》原创博文目次

华为云社区地点:【你要的前端打怪晋级指南】

[TOC]

一. 任务说明

运用原生canvasAPI绘制柱状图。(柱状图截图来自于百度Echarts官方示例库【检察示例链接】)

《【带着canvas去漂泊】(1)绘制柱状图》

二. 重点提醒

柱状图或许是最轻易完成的图表范例了,矩形的部份直接运用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);
});
}

浏览器中可检察结果:

《【带着canvas去漂泊】(1)绘制柱状图》

四. 思考题

假如愿望在坐标轴末尾加一个箭头,须要怎么做呢?

/*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();//恢复画图上下文款式设置
}

箭头结果:

《【带着canvas去漂泊】(1)绘制柱状图》

y轴的箭头请自行完成即可。


推荐阅读
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 作为软件工程专业的学生,我深知课堂上教师讲解速度之快,很多时候需要课后自行消化和巩固。因此,撰写这篇Java Web开发入门教程,旨在帮助初学者更好地理解和掌握基础知识。通过详细记录学习过程,希望能为更多像我一样在基础方面还有待提升的学员提供有益的参考。 ... [详细]
  • WCF类型共享的最佳实践
    在使用WCF服务时,经常会遇到同一个实体类型在不同服务中被生成为不同版本的问题。本文将介绍几种有效的类型共享方法,以解决这一常见问题。 ... [详细]
  • Android 自定义 RecycleView 左滑上下分层示例代码
    为了满足项目需求,需要在多个场景中实现左滑删除功能,并且后续可能在列表项中增加其他功能。虽然网络上有很多左滑删除的示例,但大多数封装不够完善。因此,我们尝试自己封装一个更加灵活和通用的解决方案。 ... [详细]
  • WinMain 函数详解及示例
    本文详细介绍了 WinMain 函数的参数及其用途,并提供了一个具体的示例代码来解析 WinMain 函数的实现。 ... [详细]
  • 重要知识点有:函数参数默许值、盈余参数、扩大运算符、new.target属性、块级函数、箭头函数以及尾挪用优化《深切明白ES6》笔记目次函数的默许参数在ES5中,我们给函数传参数, ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本文详细解析了Autofac在高级应用场景中的具体实现,特别是如何通过注册泛型接口的类来优化依赖注入。示例代码展示了如何使用 `builder.RegisterAssemblyTypes` 方法,结合 `typeof(IEventHandler).Assembly` 和 `Where` 过滤条件,动态注册所有符合条件的类,从而简化配置并提高代码的可维护性。此外,文章还探讨了这一方法在复杂系统中的实际应用及其优势。 ... [详细]
  • Flowable 流程图路径与节点展示:已执行节点高亮红色标记,增强可视化效果
    在Flowable流程图中,通常仅显示当前节点,而路径则需自行获取。特别是在多次驳回的情况下,节点可能会出现混乱。本文重点探讨了如何准确地展示流程图效果,包括已结束的流程和正在执行的流程。具体实现方法包括生成带有高亮红色标记的图片,以增强可视化效果,确保用户能够清晰地了解每个节点的状态。 ... [详细]
  • 在探讨如何在Android的TextView中实现多彩文字与多样化字体效果时,本文提供了一种不依赖HTML技术的解决方案。通过使用SpannableString和相关的Span类,开发者可以轻松地为文本添加丰富的样式和颜色,从而提升用户体验。文章详细介绍了实现过程中的关键步骤和技术细节,帮助开发者快速掌握这一技巧。 ... [详细]
  • Spring框架中枚举参数的正确使用方法与技巧
    本文详细阐述了在Spring Boot框架中正确使用枚举参数的方法与技巧,旨在帮助开发者更高效地掌握和应用枚举类型的数据传递,适合对Spring Boot感兴趣的读者深入学习。 ... [详细]
  • 深入解析C#中app.config文件的配置与修改方法
    在C#开发过程中,经常需要对系统的配置文件进行读写操作,如系统初始化参数的修改或运行时参数的更新。本文将详细介绍如何在C#中正确配置和修改app.config文件,包括其结构、常见用法以及最佳实践。此外,还将探讨exe.config文件的生成机制及其在不同环境下的应用,帮助开发者更好地管理和维护应用程序的配置信息。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有