利用html5 canvas动态画饼状图的示例代码


Posted in HTML / CSS onApril 02, 2018

本文介绍了利用html5 canvas动态画饼状图的示例代码,分享给大家,具体如下:

先来看效果图

利用html5 canvas动态画饼状图的示例代码

这里并没引用jquery等第三方库,只是用dom操作和canvas的特性编写的。

canvas画圆大体分为实心圆和空心圆。

根据需求分析知道该圆为实心圆。

1.先用canvas画实心圆

利用html5 canvas动态画饼状图的示例代码

//伪代码
var canvas = document.createElement("canvas");
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(圆心x轴坐标,圆心y轴坐标,半径,开始角,结束角);
ctx.fillStyle = 'green';
ctx.closePath();
ctx.fill();

2.根据不同颜色绘制饼状图

//伪代码
var canvas = document.createElement("canvas");
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(圆心x轴坐标,圆心y轴坐标,半径,绿色开始角,绿色结束角);
ctx.fillStyle = 'green';
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(圆心x轴坐标,圆心y轴坐标,半径,红色开始角,红色结束角);
ctx.fillStyle = 'red';
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(圆心x轴坐标,圆心y轴坐标,半径,黄色开始角,黄色结束角);
ctx.fillStyle = 'yellow';
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(圆心x轴坐标,圆心y轴坐标,半径,紫色开始角,紫色结束角);
ctx.fillStyle = 'purple';
ctx.closePath();
ctx.fill();

3.动态绘制饼状图

动态绘制圆网上普遍推荐三种方法:requestAnimationFrame、setInterval(定时)、还有动态算角度的。

这里我用的是第一种requestAnimationFrame方式。

在编写的过程中发现一个问题,就是动态画圆时并不是以圆心的坐标画的。为了解决这一问题,需要在每次画圆时重新将canvas的画笔的坐标定义为最初圆心的坐标。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <style>
        #graph {
/*            border: 1px solid black;
            height: 100%;
            width: 100%;
            box-sizing: border-box;*/
        }
    </style>
</head>
<body>
<div id="circle" style="width: 500px;float: left;"></div>
</body>
</html>
<script type="text/javascript">
(function(window,undefined){
    var data = [
        {"product":"产品1","sales":[192.44 ,210.54 ,220.84 ,230.11 ,220.85 ,210.59 ,205.49 ,200.55 ,195.71 ,187.46 ,180.66 ,170.90]},
        {"product":"产品2","sales":[122.41 ,133.16 ,145.65 ,158.00 ,164.84 ,178.62 ,185.70 ,190.13 ,195.53 ,198.88 ,204.32 ,210.91]},
        {"product":"产品3","sales":[170.30 ,175.00 ,170.79 ,165.10 ,165.62 ,160.92 ,155.92 ,145.77 ,145.17 ,140.27 ,135.99 ,130.33]},
        {"product":"产品4","sales":[165.64 ,170.15 ,175.10 ,185.32 ,190.90 ,190.01 ,187.05 ,183.74 ,177.24 ,181.90 ,179.54 ,175.98]}
    ]
        
    var dom_circle = document.getElementById('circle');
    if(dom_circle != undefined && dom_circle != null)
    {
        var canvas = document.createElement("canvas");
        dom_circle.appendChild(canvas);
        var ctx = canvas.getContext('2d');
        var defaultStyle = function(Dom,canvas){
            if(Dom.clientWidth <= 300)
            {
                canvas.width = 300;
                Dom.style.overflowX = "auto";
            }
            else{
                canvas.width = Dom.clientWidth;
            }
            if(Dom.clientHeight <= 300)
            {
                canvas.height = 300;
                Dom.style.overflowY = "auto";
            }
            else
            {
                canvas.height = Dom.clientHeight;
            }
            //坐标轴区域
            //注意,实际画折线图区域还要比这个略小一点
            return {
                p1:'green',
                p2:'red',
                p3:'yellow',
                p4:'purple',
                x: 0 ,    //坐标轴在canvas上的left坐标
                y: 0 ,    //坐标轴在canvas上的top坐标
                maxX: canvas.width ,   //坐标轴在canvas上的right坐标
                maxY: canvas.height ,   //坐标轴在canvas上的bottom坐标
                r:(canvas.width)/2,  //起点
                ry:(canvas.height)/2,  //起点
                cr: (canvas.width)/4, //半径
                startAngle:-(1/2*Math.PI),               //开始角度
                endAngle:(-(1/2*Math.PI)+2*Math.PI),     //结束角度
                xAngle:1*(Math.PI/180)                   //偏移量
            };
        }
        //画圆
        var tmpAngle = -(1/2*Math.PI);
        var ds = null;
        var sum = data[0]['sales'][0]+data[0]['sales'][1]+data[0]['sales'][2]+data[0]['sales'][3]
        var percent1 = data[0]['sales'][0]/sum * Math.PI * 2 ;
        var percent2 = data[0]['sales'][1]/sum * Math.PI * 2 + percent1;
        var percent3 = data[0]['sales'][2]/sum * Math.PI * 2 + percent2;
        var percent4 = data[0]['sales'][3]/sum * Math.PI * 2 + percent3;
        console.log(percent1);
        console.log(percent2);
        console.log(percent3);
        console.log(percent4);
        var tmpSum = 0;
        var drawCircle = function(){
            
            
            if(tmpAngle >= ds.endAngle)
            {
                return false;
            }
            else if(tmpAngle+ ds.xAngle > ds.endAngle)
            {
                tmpAngle = ds.endAngle;
            }
            else{
                tmpAngle += ds.xAngle;
                tmpSum += ds.xAngle
            }
            // console.log(ds.startAngle+'***'+tmpAngle);
            // console.log(tmpSum);
            // ctx.clearRect(ds.x,ds.y,canvas.width,canvas.height);
            
            if(tmpSum > percent1 && tmpSum <percent2)
            {
                ctx.beginPath();
                ctx.moveTo(ds.r,ds.ry);
                ctx.arc(ds.r,ds.ry,ds.cr,ds.startAngle+percent1,tmpAngle);
            
                ctx.fillStyle = ds.p2;
            }
            else if(tmpSum > percent2 && tmpSum <percent3)
            {
                ctx.beginPath();
                ctx.moveTo(ds.r,ds.ry);
                ctx.arc(ds.r,ds.ry,ds.cr,ds.startAngle+percent2,tmpAngle);
                ctx.fillStyle = ds.p3;
            }
            else if(tmpSum > percent3 )
            {
                ctx.beginPath();
                ctx.moveTo(ds.r,ds.ry);
                ctx.arc(ds.r,ds.ry,ds.cr,ds.startAngle+percent3,tmpAngle);
                ctx.fillStyle = ds.p4;
            }
            else{
                ctx.beginPath();
                ctx.moveTo(ds.r,ds.ry);
                ctx.arc(ds.r,ds.ry,ds.cr,ds.startAngle,tmpAngle);
                ctx.fillStyle = ds.p1;
            }
            ctx.closePath();
            ctx.fill();
            requestAnimationFrame(drawCircle);
        }
        this.toDraw = function(){
            ds= defaultStyle(dom_circle,canvas);
            // console.log(tmpAngle);
            // console.log(ds.xAngle)
            ctx.clearRect(ds.x,ds.y,canvas.width,canvas.height);
            drawCircle();
        }
        this.toDraw();
        var self = this;
        window.onresize = function(){
            self.toDraw()
        }
    }

})(window);    
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
使用CSS3代码绘制可爱的Hello Kitty猫
Aug 03 HTML / CSS
一款纯css3实现的非常实用的鼠标悬停特效演示
Nov 05 HTML / CSS
利用CSS3实现文本框的清除按钮相关的一些效果
Jun 23 HTML / CSS
CSS3让登陆面板3D旋转起来
May 03 HTML / CSS
css3实现简单的白云飘动背景特效
Oct 28 HTML / CSS
HTML5 微格式和相关的属性名称
Feb 10 HTML / CSS
如何使用html5与css3完成google涂鸦动画
Dec 16 HTML / CSS
html5中valid、invalid、required的定义
Feb 21 HTML / CSS
html5中 media(播放器)的api使用指南
Dec 26 HTML / CSS
HTML5 Canvas中绘制矩形实例
Jan 01 HTML / CSS
使用HTML5 Canvas为图片填充颜色和纹理的教程
Mar 21 HTML / CSS
Adobe Html5 Extension开发初体验图文教程
Nov 14 HTML / CSS
简单聊聊H5的pushState与replaceState的用法
Apr 03 #HTML / CSS
如何使用localstorage代替cookie实现跨域共享数据问题
Apr 18 #HTML / CSS
Html5 localStorage入门教程
Apr 26 #HTML / CSS
在HTML5 canvas里用卷积核进行图像处理的方法
May 02 #HTML / CSS
HTML5新增的标签和属性归纳总结
May 02 #HTML / CSS
HTML5 video视频字幕的使用和制作方法
May 03 #HTML / CSS
html5调用摄像头功能的实现代码
May 07 #HTML / CSS
You might like
如何利用php array_multisort函数 对数据库结果进行复杂排序
2013/06/08 PHP
使用php从身份证号中获取一系列线索(星座、生肖、生日等)
2016/05/11 PHP
phpinfo的知识点总结
2019/10/10 PHP
做网页的一些技巧(续)
2007/02/01 Javascript
页面中body onload 和 window.onload 冲突的问题的解决
2009/07/01 Javascript
Jquery 选中表格一列并对表格排序实现原理
2012/12/15 Javascript
有关于JS构造函数的重载和工厂方法
2013/04/07 Javascript
js 用CreateElement动态创建标签示例
2013/11/20 Javascript
文本框水印提示效果的简单实现代码
2014/02/22 Javascript
jquery实现导航固定顶部的效果仿蘑菇街
2014/10/22 Javascript
原生js页面滚动延迟加载图片
2015/12/20 Javascript
轻松实现javascript图片轮播特效
2016/01/13 Javascript
基于JS实现密码框(password)中显示文字提示功能代码
2016/05/27 Javascript
jQuery实现图片轮播效果代码(基于jquery.pack.js插件)
2016/06/02 Javascript
微信小程序开发之map地图实现教程
2017/06/08 Javascript
laravel5.4+vue+element简单搭建的示例代码
2017/08/29 Javascript
Vue 滚动行为的具体使用方法
2017/09/13 Javascript
vue中post请求以a=a&amp;b=b 的格式写遇到的问题
2018/04/27 Javascript
[04:03]DOTA2肉山黑名单梦之声 风暴之灵中文配音鉴赏
2013/07/03 DOTA
[01:08:24]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第一场 2月5日
2021/03/11 DOTA
Python获取远程文件大小的函数代码分享
2014/05/13 Python
Python中字符编码简介、方法及使用建议
2015/01/08 Python
Python3学习urllib的使用方法示例
2017/11/29 Python
python操作mysql代码总结
2018/06/01 Python
通过Canvas及File API缩放并上传图片完整示例
2013/08/08 HTML / CSS
台湾百利市购物中心:e-Payless
2017/08/16 全球购物
施华洛世奇韩国官网:SWAROVSKI韩国
2018/06/05 全球购物
工厂保洁员岗位职责
2013/12/04 职场文书
学生感冒英文请假条
2014/02/04 职场文书
巾帼建功标兵事迹材料
2014/05/11 职场文书
村主任“四风”问题个人整改措施
2014/10/04 职场文书
任命书怎么写
2015/03/02 职场文书
保研导师推荐信
2015/03/25 职场文书
2015年大学生实习评语
2015/03/25 职场文书
2015教师年度工作总结范文
2015/04/07 职场文书
2015年幼儿园班务工作总结
2015/05/12 职场文书