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

Canvas实现绘制图表

这里用canvas实现了两个简单的图表,用到了canvas的基本用法,效果如下新建chart.js文件,封装绘制方法构造方法functionmyChart(

这里用canvas实现了两个简单的图表,用到了canvas的基本用法,效果如下

 

 

新建 chart.js 文件,封装绘制方法

构造方法

function myChart(config){
    this.width = config.width > 300 ? config.width : 200        //图表宽度
    this.height = config.height > 200 ? config.height : 200        //图表高度
    this.el = config.el         //容器DOM元素
    this.data = config.data     //数据
    this.title = config.title     //title
    this.type = config.type     //类型 line、pie
}

初始化方法

        init: function(){
            this.canvas = document.createElement('canvas')
            this.canvas.width = this.width
            this.canvas.height = this.height
            document.querySelector(this.el).append(this.canvas)
            this.ctx = this.canvas.getContext('2d')
            switch(this.type){
                case 'line':
                    this.drawLineChart()
                    break;
                case 'pie':
                    this.drawPieChart()
                    break;
                default :
                    this.drawLineChart()
                    break;
            }
        },

绘制折线图

        //绘制折线图
        drawLineChart: function(){
            var height = this.height
            this.max = 0
            this.min = Infinity
            this.startPoint = { x: 30, y: height - 15 }    //原点位置
            this.innerHieght = this.height - 30 - 15        
            this.innerWidth = this.width - 30
            this.findTerminal()
            this.drawCoordinate()
            this.drawLine()
        },
        //找到最大值和最小值
        findTerminal: function(){
            this.data.map((item, index) => {
                this.max = item.val > this.max ? item.val : this.max
                this.min = item.val <this.min ? item.val : this.min
            })
        },
        //绘制坐标轴
        drawCoordinate: function(){
            //绘制坐标轴
            this.ctx.clearRect(0, 0, this.width, this.height)
            this.ctx.beginPath()
            this.ctx.moveTo(this.startPoint.x, this.startPoint.y)
            this.ctx.lineTo(this.startPoint.x, this.startPoint.y - this.innerHieght)
            this.ctx.moveTo(this.startPoint.x, this.startPoint.y)
            this.ctx.lineTo(this.startPoint.x + this.innerWidth, this.startPoint.y)
            this.ctx.stroke()
            //绘制横向标尺
            var distance = Math.floor(this.innerWidth / this.data.length)
            this.ctx.beginPath()
            this.ctx.strokeStyle = "#999"
            for(let i = 0; i <this.data.length; i++){
                let curX = this.startPoint.x + distance*i
                this.ctx.moveTo(curX , this.startPoint.y)
                this.ctx.lineTo(curX , this.startPoint.y - 5)
                this.ctx.moveTo(curX , this.startPoint.y + 15)
                this.ctx.textAlign = "center"
                this.ctx.fillText(this.data[i]['key'] , curX , this.startPoint.y + 15 )
            }
            this.ctx.stroke()
            //绘制横向坐标
            var unit = Math.floor((this.max - this.min) / 20)
            this.ctx.beginPath()
            this.ctx.strokeStyle = "#999"
            for(let y = 0; y <20; y++){
                let curY = Math.floor(this.startPoint.y - this.innerHieght / 20 * y)
                let curVal = Math.floor(this.min + unit*y)
                this.ctx.moveTo(this.startPoint.x, curY)
                this.ctx.lineTo(this.startPoint.x + 5, curY)
                this.ctx.moveTo(this.startPoint.x - 30, curY)
                this.ctx.fillText(curVal, this.startPoint.x - 15 , curY + 3 )
            }
            this.ctx.stroke()
            //绘制title
            this.ctx.beginPath()
            this.ctx.fOnt= "20px Arial"
            this.ctx.fillText(this.title, this.width / 2 - 30 , 20)
            this.ctx.stroke()
        },
        //绘制折线
        drawLine: function(){
            var distance = Math.floor(this.innerWidth / this.data.length)
            this.ctx.beginPath()
            this.ctx.moveTo(this.startPoint.x, this.startPoint.y)
            for(let i = 0; i <this.data.length; i++){
                let curY = this.startPoint.y - (((this.data[i].val - this.min)/(this.max - this.min)) * this.innerHieght)
                this.ctx.lineTo(this.startPoint.x + i*distance, curY)
                this.ctx.strokeStyle = "#000"
                this.ctx.fOnt= "10px Arial"
                this.ctx.fillText(Math.floor(this.data[i].val), this.startPoint.x + i*distance, curY + 10 )
                this.ctx.stroke()
                this.ctx.beginPath()
                this.ctx.fill
                this.ctx.arc(this.startPoint.x + i*distance, curY,3,0,2*Math.PI);
                this.ctx.fill()
                this.ctx.beginPath()
                this.ctx.moveTo(this.startPoint.x + i*distance, curY)
            }
        }

绘制饼状图

        //绘制饼状图
        drawPieChart: function(){
            var shortAxis = this.width <this.height ? this.width : this.height
            this.radius = 0.4 * shortAxis
            var width = this.width
            var height = this.height
            this.centerPoint = { x: width/2, y: height/2 + 20}
            this.drawPieLegend()
            this.calcPercentage()
            this.drawPie()
        },
        //计算饼状图比例
        calcPercentage: function(){
            var total = 0
            this.data.map((item,index) => {
                total += item.val
            })
            this.data.map((item,index) => {
                item.proportion = Math.floor(item.val / total * 100000) / 100000
            })
        },
        //绘制饼状图内容
        drawPie: function(){
            var offset = 0
            for(let i = 0; i <this.data.length; i++){
                this.ctx.beginPath()
                this.ctx.moveTo(this.centerPoint.x, this.centerPoint.y)
                this.ctx.arc(this.centerPoint.x, this.centerPoint.y, this.radius, 2*Math.PI*offset, 2*Math.PI*(this.data[i].proportion + offset))
                this.ctx.closePath()
                this.ctx.fillStyle = this.data[i].bg
                this.ctx.fill()
                this.ctx.beginPath()
                let x = this.centerPoint.x + Math.cos(2*Math.PI*(this.data[i].proportion/2 + offset))*this.radius
                let y = this.centerPoint.y + Math.sin(2*Math.PI*(this.data[i].proportion/2 + offset))*this.radius
                this.ctx.moveTo(x, y)
                let x1 = this.centerPoint.x + Math.cos(2*Math.PI*(this.data[i].proportion/2 + offset))*(this.radius + 50)
                let y1 = this.centerPoint.y + Math.sin(2*Math.PI*(this.data[i].proportion/2 + offset))*(this.radius + 50)
                this.ctx.lineTo(x1, y1)
                this.ctx.stroke()
                this.ctx.fillText(this.data[i].proportion + '%', x1 - 10, y1)
                offset += this.data[i].proportion
            }
        },
        //绘制饼状图图例
        drawPieLegend: function(){
            for(let i = 0; i <this.data.length; i++){
                let color = '#'+Math.floor(Math.random()*0xffffff).toString(16)
                this.data[i].bg = color
                this.ctx.fillStyle = color
                this.ctx.fillRect(this.width - 100, 30 * i + 50, 40, 20)
                this.ctx.fillText(this.data[i].key, this.width - 50 , 30 * i + 65)
            }
        },

 使用:

引入 chart.js 文件

 
    var chart = new myChart({
        width: document.body.clientWidth,
        height: 500,
        el: '#app',
        data: arr,
        title: `${data.name}(${data.symbol})`,
        type: 'line'
    })
    chart.init()

推荐阅读
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 标题: ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了Java的公式汇总及相关知识,包括定义变量的语法格式、类型转换公式、三元表达式、定义新的实例的格式、引用类型的方法以及数组静态初始化等内容。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了一种图片处理应用,通过固定容器来实现缩略图的功能。该方法可以实现等比例缩略、扩容填充和裁剪等操作。详细的实现步骤和代码示例在正文中给出。 ... [详细]
author-avatar
我爱左_470
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有