当前位置: 首页 > news >正文

canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...

学完我写的上一章小白上学canvas基础,我们就来这里现学现用了。这里先看我们的设计图和最终实现效果;
左面是设计稿,右面是完成后的效果图:

clipboard.png
没办法和原图一模一样。文字下方数字正的,我的是倒着的;
此图难点:扇形,圆形头像,弧形文字
话不多说直接上代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<style>
    html,body{background: #273341;}
    #mycanvas{}  
    .pie{width: 320px;height: 320px;margin: 0 auto;}
    img{width: 100%;display: none}
    .economy{text-align: center;transform: rotate(45deg);color: #fff;font-family: "微软雅黑";font-size: 14px;}
</style>
<body>
   <div class="pie">       
    <canvas id="canvas" width="960" height="960" style="width:320px;height:320px;"></canvas>
   </div>
<!-- canvas的画布宽高(分辨率)是width和height,而style中的宽高是canvas在页面中显示的宽高,画布分辨率越高,绘制出来的图任意缩放也不会出现很大的锯齿 -->
</body>
<script>
var canvas = document.getElementById('canvas');   
    var r2=380,r1=480;
    var ctx = canvas.getContext('2d');
if (canvas.getContext){
    var circle = {x: 480,
                  y: 480,
                  radius: 442}
    var smccircle = {x: 480,
                  y: 480,
                  radius: 342}
    //背景色
    ctx.fillStyle = '#273341';
    ctx.fillRect(0,0,960,960);
    ctx.fill();
   //外彩色扇形背景圆1
    ites(0,360,480,'#323d4b');
    //彩色外扇叶
    ites(0,30,r1,'#4c17e2');//>0
    ites(45,55,r1,'#1777e2');//>45
    ites(90,110,r1,'#17cde2');//>90
    ites(135,146,r1,'#3fc371');//>135
    ites(180,198,r1,'#ffbc3a');//>180
    ites(225,231,r1,'#e27217');//>225
    ites(270,290,r1,'#e217a1');//>270
    ites(315,335,r1,'#b017e2');//>315&<360
    //内覆盖扇形背景圆1
    ites(0,360,400,'#273341');

    //彩色内扇叶
    ites(0,45,r2,'#4c17e2');
    ites(45,90,r2,'#1777e2');
    ites(90,135,r2,'#17cde2');
    ites(135,180,r2,'#3fc371');
    ites(180,225,r2,'#ffbc3a');
    ites(225,270,r2,'#e27217');
    ites(270,315,r2,'#e217a1');
    ites(315,360,r2,'#b017e2');

    //内覆盖扇形背景圆2
    ites(0,360,300,'#273341');
    //交叉背景线
    line(0,480,960,480);
    line(480,0,480,960);
    line(0,0,960,960);
    line(960,0,0,960);
    
    ctx.arc(480,480,r2,0,rads(45),false);
    ctx.save();
    //头像边框
    drawCircularText(smccircle,'水分', rads(18), rads(28),'center');
    drawCircularText(smccircle,'蛋白质', rads(58), rads(78),'center');
    drawCircularText(smccircle,'内脏脂肪', rads(98), rads(127),'center');
    drawCircularText(smccircle,'骨骼', rads(153), rads(163),'center');
    drawCircularText(smccircle,'基础代谢', rads(188), rads(216),'center');
    drawCircularText(smccircle,'BMI', rads(241), rads(253),'center');
    drawCircularText(smccircle,'脂肪', rads(287), rads(298),'center');
    drawCircularText(smccircle,'肌肉', rads(333), rads(343),'center');

    ctx.restore();
    var v = 'left';
    drawCircularText(circle,'60.5%', rads(24), rads(38),v);
    drawCircularText(circle,'17.8%', rads(69), rads(83),v);
    drawCircularText(circle,'    6', rads(114), rads(130),v);
    drawCircularText(circle,'  4.3', rads(159), rads(175),v);
    drawCircularText(circle,' 1570', rads(204), rads(220),v);
    drawCircularText(circle,' 21.6', rads(249), rads(265),v);
    drawCircularText(circle,'17.1%', rads(294), rads(308),v);
    drawCircularText(circle,'55.5%', rads(339), rads(353),v);
    // Create a circular clipping path
    ctx.translate(480,480);
    ctx.beginPath();
    ctx.arc(0,0,160,0,Math.PI*2,true);
    ctx.closePath();
    ctx.strokeStyle="#ffbc3a";
    ctx.lineWidth =16;
    ctx.stroke();
    ctx.clip();
    var img = new Image();
    img.src='css/img/head.png';
    img.onload = function(){       
        ctx.drawImage(img,-160,-160,320,320);
    }
    
  }
    //转换弧度
    function rads(x){
        return Math.PI*x/180;
    }
    //圆
    function ites(a,b,r,color){
        ctx.beginPath();
        ctx.moveTo(480,480);
        ctx.arc(480,480,r,rads(a),rads(b),false);
        ctx.closePath();
        ctx.fillStyle = color;
        ctx.fill();
    }
    //线
    function line(a,b,c,d){
        ctx.beginPath();
        ctx.moveTo(a,b);
        ctx.lineTo(c,d);
        ctx.strokeStyle="#273341";
        ctx.closePath();
        ctx.lineWidth =10;
        ctx.stroke();
    }
     function siner(a,b,deg,font){
        ctx.save();
        ctx.fillStyle = '#fff'
        ctx.textAlign = "center";
        ctx.font = '48px 微软雅黑';
        ctx.translate(a, b);
        ctx.rotate(rads(deg))
        ctx.fillText(font, 0, 0);
        ctx.restore();
     }
    
    function drawCircularText(s,string, startAngle, endAngle ,lv){
        var radius = s.radius,
            angleDecrement = (startAngle - endAngle)/(string.length-1),
            angle = parseFloat(startAngle),
            index = 0,
            character;
        
        ctx.save();
        
        ctx.fillStyle = 'white';
        ctx.font = '40px 微软雅黑';
        ctx.textAlign = lv;
        ctx.textBaseline = 'middle';
        
        while (index < string.length) {
            character = string.charAt(index);
            
            ctx.save();
            ctx.beginPath();
            ctx.translate(s.x + Math.cos(angle) * radius,
                          s.y + Math.sin(angle) * radius);
            ctx.rotate(Math.PI/2 + angle);
            
            ctx.fillText(character, 0, 0);
//            ctx.strokeText(character, 0, 0);
            
            angle -= angleDecrement;
            index++;
            ctx.restore();
        }
        ctx.restore();
    }
   
/*//H绘制圆形头像
//  var ctx = document.getElementById('canvas').getContext('2d');
//  ctx.fillRect(0,0,240,240);
  ctx.translate(120,120);

  // Create a circular clipping path
  ctx.beginPath();
  ctx.arc(0,0,40,0,Math.PI*2,true);
  ctx.clip();

  // draw background
  var lingrad = ctx.createLinearGradient(0,-240,0,240);
  lingrad.addColorStop(0, '#232256');
  lingrad.addColorStop(1, '#143778');
  
  ctx.fillStyle = lingrad;
  ctx.fillRect(-75,-75,150,150);
  var img = new Image();
    img.src='css/img/head.jpg';
    img.onload = function(){       
        ctx.drawImage(img,-40,-40,80,80);
    }*/
  
</script>
</html>

上面的代码直接复制进你的html文件里打开就能看到效果。
注意事项:
开始时按240像素大小的画布写,最后发现放在分辨率高的手机上全是锯齿,所以最后采用960的宽高来写。
绘制完图片(头像)会覆盖整个画布,所以图片得最后绘制。
弧形文字需要一点一旦调整弧度。
留言:如有疑问关注我给我留言,我们一起成为大牛!

相关文章:

  • 【iOS第三方框架】FMDB刚刚好
  • C#框架及概念
  • vue webpack 构建
  • 设计模式之观察者模式(c++)
  • codeforces 492E. Vanya and Field(exgcd求逆元)
  • tcp 重发 应用层重传
  • Log4j具体使用实例
  • ios8之后的界面旋转简单原理
  • 设计模式之桥接模式(Bridge模式)
  • jsdoc文档
  • ESXI虚拟化增加系统盘容量
  • php过滤textarea 中的换行符问题
  • Unity3D-光照贴图技术
  • 说说动画卡顿的解决方案
  • ffmpeg从AVFrame取出yuv数据到保存到char*中
  • php的引用
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 2017-09-12 前端日报
  • C++类中的特殊成员函数
  • javascript从右向左截取指定位数字符的3种方法
  • mongo索引构建
  • STAR法则
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 来,膜拜下android roadmap,强大的执行力
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 一个项目push到多个远程Git仓库
  • 优秀架构师必须掌握的架构思维
  • 原生Ajax
  • ​2021半年盘点,不想你错过的重磅新书
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • # 数据结构
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • ${factoryList }后面有空格不影响
  • (39)STM32——FLASH闪存
  • (k8s中)docker netty OOM问题记录
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (南京观海微电子)——COF介绍
  • (七)Java对象在Hibernate持久化层的状态
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (转载)(官方)UE4--图像编程----着色器开发
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • 、写入Shellcode到注册表上线
  • .apk文件,IIS不支持下载解决
  • .axf 转化 .bin文件 的方法
  • .net Application的目录
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .net6 webapi log4net完整配置使用流程
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • /var/log/cvslog 太大
  • [ C++ ] STL---string类的模拟实现
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • []C/C++读取串口接收到的数据程序
  • [【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器
  • [100天算法】-不同路径 III(day 73)
  • [2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]