Canvas特效页面分享

Canvas特效页面分享

     canvas是一个可以使用脚本(通常为JavaScript)来绘制图形的 HTML 元素.例如,它可用于绘制图表、制作图片构图或者制作简单的(以及不那么简单的)动画。
     Canvas 的默认大小为300像素×150像素(宽×高,像素的单位是px)。但是,可以使用HTML的高度和宽度属性来自定义Canvas 的尺寸。为了在 Canvas 上绘制图形,我们使用一个JavaScript上下文对象,它能动态创建图像( creates graphics on the fly)。
     canvas>看起来和 img 元素很相像,唯一的不同就是它并没有 src 和 alt 属性。实际上, 标签只有两个属性—— width和height。这些都是可选的,并且同样利用 DOMproperties 来设置。当没有设置宽度和高度的时候,canvas会初始化宽度为300像素和高度为150像素。该元素可以使用CSS来定义大小,但在绘制时图像会伸缩以适应它的框架尺寸:如果CSS的尺寸与初始画布的比例不一致,它会出现扭曲。

getContext():

     getContext() 方法返回一个用于在画布上绘图的环境。
     参数 contextID 指定了您想要在画布上绘制的类型。当前唯一的合法值是 “2d”,它指定了二维绘图,并且导致这个方法返回一个环境对象,该对象导出一个二维绘图 API。

lineWidth:

     绘制线条宽度

strokeStyle:

     trokeStyle 属性设置或返回用于笔触的颜色、渐变。

createLinearGradient():

     createLinearGradient() 方法创建线性的渐变对象。
渐变可用于填充矩形、圆形、线条、文本等等context.createLinearGradient(x0,y0,x1,y1)

beginPath:

     开始绘画

lineCap:

     lineCap 属性设置或返回线条末端线帽的样式。
     Butt:默认。向线条的每个末端添加平直的边缘。
     Round:向线条的每个末端添加圆形线帽。
     Square:向线条的每个末端添加正方形线帽。

arc():

     arc() 方法创建弧/曲线(用于创建圆或部分圆)。
context.arc(x,y,r,sAngle,eAngle,counterclockwise)
     补充(弧度):弧长等于半径的弧,其所对的圆心角为1弧度;
根据定义,一周的弧度数为2πr/r=2π,360°角=2π弧度,因此,1弧度约为57.3°,即57°17’44.806’’,1°为π/180弧度,近似值为0.01745弧度,周角为2π弧度,平角(即180°角)为π弧度,直角为π/2弧度。

Stroke:

     stroke() 方法会实际地绘制出通过 moveTo() 和 lineTo() 等方法定义的路径

requestAnimationFrame:

为什么不使用setTimeout和setInterval方法:
1、即使向其传递毫秒为单位的参数,它们也不能达到ms的准确性。这是因为javascript是单线程的,可能会发生阻塞。
2、没有对调用动画的循环机制进行优化。
3、没有考虑到绘制动画的最佳时机,只是一味地以某个大致的事件间隔来调用循环。
其实,使用setInterval或setTimeout来实现主循环,根本错误就在于它们抽象等级不符合要求。我们想让浏览器执行的是一套可以控制各种细节的api,实现如“最优帧速率”、“选择绘制下一帧的最佳时机”等功能。但是如果使用它们的话,这些具体的细节就必须由开发者自己来完成。

requestAnimationFrame不需要使用者指定循环间隔时间,浏览器会基于当前页面是否可见、CPU的负荷情况等来自行决定最佳的帧速率,从而更合理地使用CPU。
详细解释请跳转另一个大佬的笔记

clearRect:

     清空画布

cancelAnimationFrame:

     此方法可以停止函数动画的执行
     save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。 restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响

Rotate:

     rotate() 方法旋转当前的绘图。

globalCompositeOperation :

     globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上
     (destination-out):在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的

     大家如果认真看完的话应该已经可自己写canvas动画了,但是这里还是给大家附上我自己写的一个刮刮乐小demo,

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>audio</title>
<style type="text/css">
    canvas {
        /* canvas 默认宽高 300*150 
        css设置的宽高,只能设置canvas对象在页面显示的大小。
        并不能增加画布内部的像素数
    */
        border: 1px solid black;
        /* width: 500px;
    height: 500px; */
        margin: 0 auto;
        position: absolute;
        left: 0;
        top: 0;
    }

    div {
        width: 500px;
        height: 500px;
        background: url("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4210473879,3554842544&fm=27&gp=0.jpg") no-repeat;
        background-size: 100% 100%;
        position: relative;
    }

    div p {
        font-size: 50px;
        line-height: 500px;
        text-align: center;
        width: 100%;
    }
</style>

</head>
<body>
<!-- 在标签上添加canvas像素值 -->
<div>
    <p>一等奖</p>
    <canvas id="canvasId" width="500" height="500">您的浏览器不支持canvas!</canvas>
</div>
<script type="text/javascript">
    var cv = document.getElementById("canvasId"),
        p = document.getElementsByTagName("p")[0];

    //设置中奖几率
    var num = 10000 * Math.random(),
        result = "谢谢惠顾";
    if (num < 1000) {
        result = "三等奖";
    }
    if (num < 50) {
        result = "二等奖";
    }
    if (num < 5) {
        result = "一等奖";
    }
    p.innerText = result;
    try {
        var ct = cv.getContext("2d");
        //绘制背景色
        ct.fillStyle = "#aaa";
        ct.fillRect(0, 0, 500, 500);
        //设置绘制状态
        ct.lineCap = "round";   //设置线条两端为圆弧
        ct.lineJoin = "round";   //设置线条转折为圆弧
        ct.lineWidth = 60;
        /*设置新绘制清除新绘制内容和原内容的重叠区域*/
        ct.globalCompositeOperation = "destination-out";
    } catch (e) {
        console.log(e);
    }
    //绘制曲线
//  var flag = false,
//      lx, ly;
//  cv.onmousedown = function (e) {
//      flag = true;
//      lx = e.offsetX;
//      ly = e.offsetY;
//  }
//
//  cv.onmousemove = function (e) {
//      if (flag) {
//          ct.beginPath();
//          ct.moveTo(lx, ly);
//          ct.lineTo(e.offsetX, e.offsetY);
//          ct.stroke();
//          ct.closePath();
//
//          //更新坐标
//          lx = e.offsetX;
//          ly = e.offsetY;
//      }
//  }
//
//  cv.onmouseup = function (e) {
//      flag = false;
//  }
     var lx ;
        var ly ;
    function touchMove(event) { 
    	console.log(1)
    	event.preventDefault(); //阻止事件默认动作
            var completed = 0;
            var data = ct.getImageData(0, 0, 500, 500).data;
            var total = data.length / 4;
            var touch = event.touches[0];
            var x = touch.pageX;
            var y = touch.pageY;
            console.log(lx)
            console.log(ly)
             ct.beginPath();
            ct.moveTo(lx, ly);  //线条开始位置
            ct.lineTo(x, y);//线条结束位置
            ct.stroke();
            ct.closePath();

            //更新坐标
            lx = x;
            ly = y;
//          ct.beginPath();
//          ct.arc(x, y, 20, 0, Math.PI * 2, false);
//          ct.fill();
            for (var i = 3; i < data.length; i += 4) {
                if (data[i] === 0) {
                    completed += 1;
                }
            }
            if (completed > total / 1.4) {//根据自己要刮开的面积大小改变数值
                console.log("已完成刮奖");
                ct.clearRect(0, 0, 500, 500);//完成刮奖后清除剩余没有刮开的地方
            }
    };
    function touchStart(event) {
    	
    	 var touch = event.touches[0];
      lx = touch.pageX;
         ly = touch.pageY;
        console.log(lx)
        console.log(ly)
    }
     cv.addEventListener("touchmove", touchMove, false);//注册事件
     cv.addEventListener("touchstart", touchStart, false);//注册事件
</script>

</html>

PS:在这个demo中我使用的事件是移动端的触摸事件,想要在PC端实现的同学把事件改为鼠标触发即可。

同时在这个demo里还有一个设计思路,我们消除黑幕的时候是不是可以考虑重复话圆点来完成呢?或者使用锯齿波浪线?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值