Canvas图形绘制(下)

简介: Canvas图形绘制

绘制扇形



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');
    /*在中心位置画一个半径150px的圆弧右上角 扇形  边  填充 */
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;
    /*把起点放到圆心位置*/
    ctx.moveTo(w/2,h/2);
    ctx.arc(w/2,h/2,150,0,-Math.PI/2,true);
    /*闭合路径*/
    //ctx.closePath();
    ctx.fill();
</script>
</body>
</html>


绘制数据饼图



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');
    /*1.根据37期的年龄分布绘制饼图*/
    /*2.准备统计的数据*/
    /*15-20岁 6个*/
    /*20-25岁 30个*/
    /*25-30岁 10个*/
    /*30-35岁 8个*/
    var data = [6, 30, 10, 8];
    /*3.在饼图表示出来*/
    /*4.需要把数据转出弧度*/
    var angleList = [];
    var total = 0;
    data.forEach(function (item, i) {
        total += item;
    });
    console.log(total);
    /*第二是转换成弧度的时候就可以去绘制扇形 减少一次遍历*/
    data.forEach(function (item, i) {
        var angle = Math.PI * 2 * (item/total);
        angleList.push(angle);
    });
    console.log(angleList);
    /*5.根据弧度绘制扇形*/
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;
    var x0 = w/2;
    var y0 = h/2;
    /*获取随机颜色*/
    var getRandomColor = function () {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }
    var startAngle = 0;
    angleList.forEach(function (item,i) {
        /*上一次绘制的结束弧度等于当前次的起始弧度*/
        var endAngle = startAngle + item;
        ctx.beginPath();
        ctx.moveTo(x0,y0);
        ctx.arc(x0,y0,150,startAngle,endAngle);
        ctx.fillStyle = getRandomColor();
        ctx.fill();
        /*记录当前的结束位置作为下一次的起始位置*/
        startAngle = endAngle;
    });
</script>
</body>
</html>


绘制文本


  • ctx.font = ‘微软雅黑’ 设置字体


  • strokeText()


  • fillText(text,x,y,maxWidth)


    text 要绘制的文本


    x,y 文本绘制的坐标(文本左下角)


    maxWidth 设置文本最大宽度,可选参数


  • ctx.textAlign文本水平对齐方式,相对绘制坐标来说的


    left


    center


    right


    start 默认


    end


  • ctx.direction属性css(rtl ltr) start和end于此相关


如果是ltr,start和left表现一致


如果是rtl,start和right表现一致


  • ctx.textBaseline 设置基线(垂直对齐方式 )


top 文本的基线处于文本的正上方,并且有一段距离


middle 文本的基线处于文本的正中间


bottom 文本的基线处于文本的证下方,并且有一段距离


hanging 文本的基线处于文本的正上方,并且和文本粘合


alphabetic 默认值,基线处于文本的下方,并且穿过文字


ideographic 和bottom相似,但是不一样


  • measureText() 获取文本宽度obj.widt


案例:画布中心绘制文字



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 100px auto;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');
    /*1.在画布的中心绘制一段文字*/
    /*2.申明一段文字*/
    var str = '您吃饭中饭了吗';
    /*3.确定画布的中心*/
    var w = ctx.canvas.width;
    var h = ctx.canvas.height;
    /*4.画一个十字架在画布的中心*/
    ctx.beginPath();
    ctx.moveTo(0, h / 2 - 0.5);
    ctx.lineTo(w, h / 2 - 0.5);
    ctx.moveTo(w / 2 - 0.5, 0);
    ctx.lineTo(w / 2 - 0.5, h);
    ctx.strokeStyle = '#eee';
    ctx.stroke();
    /*5.绘制文本*/
    ctx.beginPath();
    ctx.strokeStyle = '#000';
    var x0 = w/2;
    var y0 = h/2;
    /*注意:起点位置在文字的左下角*/
    /*有文本的属性  尺寸 字体  左右对齐方式  垂直对齐的方式*/
    ctx.font = '40px Microsoft YaHei';
    /*左右对齐方式 (center left right start end) 基准起始坐标*/
    ctx.textAlign = 'center';
    /*垂直对齐的方式 基线 baseline(top,bottom,middle) 基准起始坐标*/
    ctx.textBaseline = 'middle';
    //ctx.direction = 'rtl';
    //ctx.strokeText(str,x0,y0);
    ctx.fillText(str,x0,y0);
    /*6.画一个下划线和文字一样长*/
    ctx.beginPath();
    /*获取文本的宽度*/
    console.log(ctx.measureText(str));
    var width = ctx.measureText(str).width;
    ctx.moveTo(x0-width/2,y0 + 20);
    ctx.lineTo(x0+width/2,y0 + 20);
    ctx.stroke();
</script>
</body>
</html>


圆与文本综合案例:数据饼状图



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border: 1px solid #ccc;
            display: block;
            margin: 100px auto;
        }
    </style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
    /*var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');*/
    /*1.绘制饼状态图*/
    /*1.1 根据数据绘制一个饼图*/
    /*1.2 绘制标题 从扇形的弧中心伸出一条线在画一条横线在横线的上面写上文字标题*/
    /*1.3 在画布的左上角 绘制说明 一个和扇形一样颜色的矩形 旁边就是文字说明*/
    var PieChart = function (ctx) {
        /*绘制工具*/
        this.ctx = ctx || document.querySelector('canvas').getContext('2d');
        /*绘制饼图的中心*/
        this.w = this.ctx.canvas.width;
        this.h = this.ctx.canvas.height;
        /*圆心*/
        this.x0 = this.w / 2 + 60;
        this.y0 = this.h / 2;
        /*半径*/
        this.radius = 150;
        /*伸出去的线的长度*/
        this.outLine = 20;
        /*说明的矩形大小*/
        this.rectW = 30;
        this.rectH = 16;
        this.space = 20;
    }
    PieChart.prototype.init = function (data) {
        /*1.准备数据*/
        this.drawPie(data);
    };
    PieChart.prototype.drawPie = function (data) {
        var that = this;
        /*1.转化弧度*/
        var angleList = this.transformAngle(data);
        /*2.绘制饼图*/
        var startAngle = 0;
        angleList.forEach(function (item, i) {
            /*当前的结束弧度要等于下一次的起始弧度*/
            var endAngle = startAngle + item.angle;
            that.ctx.beginPath();
            that.ctx.moveTo(that.x0, that.y0);
            that.ctx.arc(that.x0, that.y0, that.radius, startAngle, endAngle);
            var color = that.ctx.fillStyle = that.getRandomColor();
            that.ctx.fill();
            /*下一次要使用当前的这一次的结束角度*/
            /*绘制标题*/
            that.drawTitle(startAngle, item.angle, color , item.title);
            /*绘制说明*/
            that.drawDesc(i,item.title);
            startAngle = endAngle;
        });
    };
    PieChart.prototype.drawTitle = function (startAngle, angle ,color , title) {
        /*1.确定伸出去的线 通过圆心点 通过伸出去的点  确定这个线*/
        /*2.确定伸出去的点 需要确定伸出去的线的长度*/
        /*3.固定伸出去的线的长度*/
        /*4.计算这个点的坐标*/
        /*5.需要根据角度和斜边的长度*/
        /*5.1 使用弧度  当前扇形的起始弧度 + 对应的弧度的一半 */
        /*5.2 半径+伸出去的长度 */
        /*5.3 outX = x0 + cos(angle) * ( r + outLine)*/
        /*5.3 outY = y0 + sin(angle) * ( r + outLine)*/
        /*斜边*/
        var edge = this.radius + this.outLine;
        /*x轴方向的直角边*/
        var edgeX = Math.cos(startAngle + angle / 2) * edge;
        /*y轴方向的直角边*/
        var edgeY = Math.sin(startAngle + angle / 2) * edge;
        /*计算出去的点坐标*/
        var outX = this.x0 + edgeX;
        var outY = this.y0 + edgeY;
        this.ctx.beginPath();
        this.ctx.moveTo(this.x0, this.y0);
        this.ctx.lineTo(outX, outY);
        this.ctx.strokeStyle = color;
        /*画文字和下划线*/
        /*线的方向怎么判断 伸出去的点在X0的左边 线的方向就是左边*/
        /*线的方向怎么判断 伸出去的点在X0的右边 线的方向就是右边*/
        /*结束的点坐标  和文字大小*/
        this.ctx.font = '14px Microsoft YaHei';
        var textWidth = this.ctx.measureText(title).width ;
        if(outX > this.x0){
            /*右*/
            this.ctx.lineTo(outX + textWidth,outY);
            this.ctx.textAlign = 'left';
        }else{
            /*左*/
            this.ctx.lineTo(outX - textWidth,outY);
            this.ctx.textAlign = 'right';
        }
        this.ctx.stroke();
        this.ctx.textBaseline = 'bottom';
        this.ctx.fillText(title,outX,outY);
    };
    PieChart.prototype.drawDesc = function (index,title) {
        /*绘制说明*/
        /*矩形的大小*/
        /*距离上和左边的间距*/
        /*矩形之间的间距*/
        this.ctx.fillRect(this.space,this.space + index * (this.rectH + 10),this.rectW,this.rectH);
        /*绘制文字*/
        this.ctx.beginPath();
        this.ctx.textAlign = 'left';
        this.ctx.textBaseline = 'top';
        this.ctx.font = '12px Microsoft YaHei';
        this.ctx.fillText(title,this.space + this.rectW + 10 , this.space + index * (this.rectH + 10));
    };
    PieChart.prototype.transformAngle = function (data) {
        /*返回的数据内容包含弧度的*/
        var total = 0;
        data.forEach(function (item, i) {
            total += item.num;
        });
        /*计算弧度 并且追加到当前的对象内容*/
        data.forEach(function (item, i) {
            var angle = item.num / total * Math.PI * 2;
            item.angle = angle;
        });
        return data;
    };
    PieChart.prototype.getRandomColor = function () {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    };
    var data = [
        {
            title: '15-20岁',
            num: 6
        },
        {
            title: '20-25岁',
            num: 30
        },
        {
            title: '25-30岁',
            num: 10
        },
        {
            title: '30以上',
            num: 8
        }
    ];
    var pieChart = new PieChart();
    pieChart.init(data);
</script>
</body>
</html>



相关文章
|
网络架构 Docker 容器
Docker容器动态添加端口
Docker容器动态添加端口
512 0
|
机器学习/深度学习 搜索推荐 算法
Learning Disentangled Representations for Recommendation | NIPS 2019 论文解读
近年来随着深度学习的发展,推荐系统大量使用用户行为数据来构建用户/商品表征,并以此来构建召回、排序、重排等推荐系统中的标准模块。普通算法得到的用户商品表征本身,并不具备可解释性,而往往只能提供用户-商品之间的attention分作为商品粒度的用户兴趣。我们在这篇文章中,想仅通过用户行为,学习到本身就具备一定可解释性的解离化的用户商品表征,并试图利用这样的商品表征完成单语义可控的推荐任务。
24239 0
Learning Disentangled Representations for Recommendation | NIPS 2019 论文解读
|
前端开发 Java 关系型数据库
基于Springboot+Vue实现校园招聘系统
基于Springboot+Vue实现校园招聘系统
263 2
|
SQL 开发框架 .NET
C#一分钟浅谈:数据绑定与数据源控件
在Web开发中,数据绑定和数据源控件是实现动态网页的关键技术。本文从基础概念入手,详细讲解数据绑定的原理及其在ASP.NET中的应用,并介绍常见数据绑定方式:手动绑定和自动绑定。接着,文章重点介绍了ASP.NET中的数据源控件,如`SqlDataSource`、`ObjectDataSource`、`XmlDataSource`和`LinqDataSource`,并通过具体示例演示如何使用`SqlDataSource`和`GridView`进行数据绑定。最后,还列举了一些常见问题及其解决办法,帮助读者更好地理解和应用这些技术。
267 4
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
333 4
|
Rust 安全 编译器
编程语言新宠:Rust语言的特性、优势与实战入门
【10月更文挑战第26天】Rust语言诞生于2006年,由Mozilla公司的Graydon Hoare发起。作为一门系统编程语言,Rust专注于安全和高性能。通过所有权系统和生命周期管理,Rust在编译期就能消除内存泄漏等问题,适用于操作系统、嵌入式系统等高可靠性场景。
1271 2
|
机器学习/深度学习 人工智能 自然语言处理
大语言模型的预训练[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相关理论知识和模型实现、模型应用以及各个版本之间的区别详解
大语言模型的预训练[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相关理论知识和模型实现、模型应用以及各个版本之间的区别详解
大语言模型的预训练[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相关理论知识和模型实现、模型应用以及各个版本之间的区别详解
钉钉回传中文信息乱码怎么处理?
钉钉回传中文信息乱码怎么处理?
1062 0
|
Java API 项目管理
Java一分钟之-Gradle插件开发:自定义构建逻辑
【6月更文挑战第5天】Gradle插件开发详解:从入门到发布。文章介绍如何创建自定义插件,强调依赖管理、任务命名和配置阶段的理解。示例代码展示插件实现及避免常见问题的方法。最后,讨论插件的发布与共享,助你提升构建效率并贡献于开发者社区。动手实践,打造强大Gradle插件!
402 3
|
数据可视化 数据挖掘 数据处理
Python对Excel两列数据进行运算【从基础到高级的全面指南】
【7月更文挑战第6天】使用Python的`pandas`库处理Excel数据,涉及安装`pandas`和`openpyxl`,读取数据如`df = pd.read_excel(&#39;data.xlsx&#39;)`,进行运算如`df[&#39;Sum&#39;] = df[&#39;Column1&#39;] + df[&#39;Column2&#39;]`,并将结果写回Excel。`pandas`还支持数据筛选、分组、可视化、异常处理和性能优化。通过熟练运用这些功能,可以高效分析Excel表格。