0

0

html5+canvas动态实现饼状图步骤详解

php中世界最好的语言

php中世界最好的语言

发布时间:2018-05-07 17:45:39

|

4104人浏览过

|

来源于php中文网

原创

这次给大家带来html5+canvas动态实现饼状图步骤详解,html5+canvas动态实现饼状图的注意事项有哪些,下面就是实战案例,一起来看一下。

先来看效果图

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

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

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

1.先用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>
<p id="circle" style="width: 500px;float: left;"></p>
</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>

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Tana
Tana

“节点式”AI智能笔记工具,支持超级标签。

下载

H5+WebWorkers多线程开发使用详解

H5离线应用与客户端存储使用详解

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

3

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

12

2026.03.03

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

69

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

59

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

46

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

24

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

20

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

4

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

348

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 7.2万人学习

HTML+CSS基础与实战
HTML+CSS基础与实战

共132课时 | 12万人学习

前端开发(基础+实战项目合集)
前端开发(基础+实战项目合集)

共60课时 | 4.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号