简单的 canvas 翻角效果

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Document</title>
  <style>
    .container:before {
    content: "";
    position: absolute;
    left: 50px;
    top: 0;
    width: 1px;
    height: 102px;
    background: #fff;
}

.container:after {
    content: "";
    position: absolute;
    left: 0px;
    top: 50px;
    width: 102px;
    height: 1px;
    background: #fff;
}

.container {
    background: #abcdef;
    display: inline-block;
    font-size: 0;
    position: relative;
}
  </style>
 </head>
 <body>
    <div class="container">
        <canvas class="myCanvas" width="100" height="100"></canvas>
    </div>
    <script>
        var canvas = document.querySelector('.myCanvas'); //获取canvas对应dom
//        var ctx = canvas.getContext('2d'); //此方法较为基础 , 意为获取canvas绘画2d内容的工具(上下文)
//        var cw = 100; //分辨率 , 其实直接从dom上获取可能更好些
//        var ch = 100; //分辨率 , 其实直接从dom上获取可能更好些

//API

//保存上下文状态 (比如画笔尺寸 颜色 旋转角度)
//        ctx.save() 
//返回上次保存的上下文状态    
//ctx.restore()
//上下文移动到具体位置
//ctx.moveTo(x,y) 
//上下文以划线的形式移动到某位置
//ctx.lineTo(x,y) 
// 画线动作
//ctx.stroke() 
//上下文(画笔)按贝塞尔曲线移动(简单理解为可控的曲线即可)
//ctx.quadraticCurveTo()
//画圆
//ctx.arc() 
//开启新的画笔路径
//ctx.beginPath() 
//关闭当前画笔路径
//ctx.closePath() 
//创建canvas渐变对象
//ctx.createLinearGradient() 
 //对闭合区域进行填充
//ctx.fill()
//画笔的重叠模式
//ctx.globalCompositeOperation 

/**


首先是绘制黑色翻出的部分 , 图形分解为如下几部分(请根据上图脑补)

左上角向右下的半弧 ╮
然后是竖直向下的竖线 |
然后是向右的半圆 ╰
再然后是向右的横线
接着还是向右下的半弧 ╮
最后是将线连接会起点
**/

var canvas = document.querySelector('.myCanvas');
        var ctx = canvas.getContext('2d');
        var cw = 100;
        var ch = 100;
        var percent = 0;
        var points = {
            x1 : 100,
            y1 : 0,
            x2 : 100,
            y2 : 0
        }
        var speed = 1;
        var aSpeed = 0.1;
        ctx.moveTo(0,0);
        ctx.strokeStyle = 'black';
        ctx.strokeWidth= 1;
        ctx.save();
        var deg = Math.PI / 180;
        
        function start(type){
            if(type === 'show'){
                points = {
                    x1 : 100,
                    y1 : 0,
                    x2 : 100,
                    y2 : 0
                }
                aSpeed = .1;
                speed = 1;
            }else{
                points = {
                    x1 : 50,
                    y1 : 0,
                    x2 : 100,
                    y2 : 50
                }
                aSpeed =  -.1;
                speed = -1;
            }
            draw(points , type);
        }
        
        function draw(points , type){
            var disX = Math.floor(points.x2 - points.x1);
            var disY = Math.floor(points.y2 - points.y1);
            if(disY < 0 && type == 'hide'){
//                console.log('改展开动画了');
                ctx.clearRect(0,0,cw,ch);
                setTimeout(function(){
                    start('show');
                } , 2000)
                return ;
            }else if(disY > 50 && type == 'show'){
//                console.log('改收起动画了');
                setTimeout(function(){
                    start('hide');
                } , 2000)
                return ;
            }
            ctx.clearRect(0,0,cw,ch);
            drawPageCorShow(points , disX , disY);
            drawPageCor(points, disX , disY);
            window.requestAnimationFrame(function(){
                draw(points , type);
            })
        }
        
        function drawPageCorShow(points, disX , disY){
            ctx.save();
            ctx.beginPath();
            //闭合三角形
            ctx.moveTo(points.x1 , points.y1);
            ctx.lineTo(points.x2 , points.y2);
            ctx.lineTo(points.x2 , points.y1);
            ctx.lineTo(points.x1 , points.y1);

            ctx.closePath();
            ctx.strokeStyle = "#080";
            ctx.stroke();
            
            ctx.fillStyle = '#ff6600';
            ctx.fill();
            //重叠模式
            ctx.globalCompositeOperation = 'source-atop';
            
            ctx.beginPath();
            ctx.font = '14px Arial';
            ctx.textAlign = 'center';
            ctx.translate(78 , 22);
            ctx.rotate(45 * deg);
            ctx.fillStyle = '#fff';
            ctx.fillText('NEW' , 0 , 0);
            ctx.closePath();
            ctx.restore();
            
        }
        
        function drawPageCor(points, disX , disY){
            ctx.save();
            ctx.beginPath();
            //移動到位置 左上
            ctx.moveTo(points.x1,points.y1);
            //画第一个曲线
            ctx.quadraticCurveTo(points.x1 + (disX/10),points.y1 + disY/10 ,(points.x1 + disX/10),points.y1 + disY/2);
            //直线向下
            ctx.lineTo(points.x1 + disX / 10 , points.y2 - (disY/5));
            //半圆向右
            ctx.arc(points.x1+disX/5,points.y2 - (disY/5),disY/10,deg*180 , deg*90,true);
            // 直线向右
            ctx.lineTo(points.x2 - disX/2 , points.y2 - (disY / 10))
            //曲线向右
            ctx.quadraticCurveTo(points.x2 -disX/10,points.y2 - (disY/10)  ,points.x2,points.y2 );
            //闭合图形
            ctx.lineTo(points.x1,points.y1);
            
            ctx.closePath();
            
            var gradient = ctx.createLinearGradient(points.x1 , points.y2 , points.x1 + (disX/2) , points.y1 + disY/2);
            gradient.addColorStop(0 , '#ccc');
            gradient.addColorStop(0.7 , '#111');
            gradient.addColorStop(1 , '#000');
            
            ctx.fillStyle = gradient;
            ctx.fill();
            ctx.restore();
            //更新速度位置
            points.x1 -= speed;
            points.y2 += speed;
            speed += aSpeed;
        }
        start('show');
    </script>
 </body>
</html>

原文地址:http://web.jobbole.com/93229/

posted @ 2018-01-09 17:49  Terre  阅读(290)  评论(0编辑  收藏  举报

风光无限好