案例效果 | Paper.js与Canvas实现中秋画圆,比比谁画的圆

模板效果

模板代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>中秋画圆,比一比谁画的圆 | 公众号:HTML5 WEB前端分享</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
    <meta content="yes" name="apple-mobile-web-app-capable" />
    <meta content="yes" name="apple-touch-fullscreen" />
    <meta content="telephone=no,email=no" name="format-detection" />
    <link rel="stylesheet" type="text/css" href="http://css.h5course.cn/reset-1.0.0.css">
    <script src="http://js.h5course.cn/jquery-1.11.3.min.js"></script>
    <script src="http://js.h5course.cn/paper-full.min.js"></script>
    <style type="text/css">
        html,
        body {
            height: 100%;
            background-color: #000;
        }
        canvas[resize] {
            width: 100%;
            height: 100%;
        }
        .btn {
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            color: #fff;
            font-size: 18px;
            text-align: center;
            line-height: 50px;
            background-color: #009dec;
        }
    </style>
</head>
<body ontouchmove="event.preventDefault();" data-info="公众号:HTML5 WEB前端分享">
    <canvas id="myCanvas" resize hidpi="on"></canvas>
    <div class="btn">点击重新开始</div>
</body>
    <script type="text/paperscript" canvas="myCanvas">
        var vw = view.viewSize.width;
        var vh = view.viewSize.height;
        var vw2 = vw / 2;
        var vh2 = vh / 2;
        var vwMax = Math.max(vw, vh);     
        var vwMin = Math.min(vw, vh);
        // 定义绘制的状态
        var drawStatus = 1;
        // 定义绘制路径对象
        var drawPath = null;
        // 填充旋转角度
        var fillRotateDeg = 0;
        // 填充线的集合
        var fillLines = [];
        // 最终的画的圆
        var resultCircle = null;
        // 默认完美度0
        var perfect = 100;
        var showResult = false;

        // 视图中心点
        var centerPoint = new Point(vw2, vh2);
        var circleRadius = vwMin / 2 - 40;

        // 绘制提示的圆形
        var tipCircle = new Path.Circle(centerPoint, circleRadius);
        tipCircle.strokeColor = '#fff';
        tipCircle.strokeWidth = 3;

        // 绘制提示的半径
        var tipRadiusLine = new Path.Line(centerPoint, new Point(vw2 - circleRadius, vh2));
        tipRadiusLine.strokeColor = '#fff';
        tipRadiusLine.rotate(110, centerPoint);

        // 填充线的起始线(先不设置颜色,隐藏起来)
        var fillLongLine = new Path.Line(centerPoint, new Point(vh2 - vwMax, vh2));
        fillLongLine.rotate(110, centerPoint);

        /**
         * 动画处理函数
         * @param  {[type]} event [description]
         * @return {[type]}       [description]
         * @author 懂点君 公众号:HTML5 WEB前端分享
         */
        function onFrame(event) {
            // event.delta:自上一帧事件以来经过的时间(以秒为单位)
            event.delta = (event.delta > 0.2) ? 0.2 : event.delta;

            // 准备开始绘制
            if(drawStatus === 1) {
                // 隐藏提示的圆形
                if (tipCircle.visible) {
                    var opacity = tipCircle.opacity - 1 * event.delta;

                    // 防止透明度值变成负数
                    if (opacity < 0) {
                        opacity = 0;
                        tipCircle.visible = false;
                    }

                    tipCircle.opacity = opacity;
                }
                
            // 绘制结束
            } else if(drawStatus === 2) {
                // 设置提示的圆形可见
                if (!tipCircle.visible) {
                    tipCircle.visible = true;
                }    

                // 缓慢显示提示的圆形
                if(tipCircle.opacity < 1) {
                    opacity = tipCircle.opacity + 1 * event.delta;

                    // 防止透明度值超过1
                    if (opacity > 1) {
                        opacity = 1;
                    }

                    tipCircle.opacity = opacity;       

                // 填充中间的线
                } else {
                    if(fillRotateDeg < 360) {
                        var rotateDeg = event.delta * 150;
                        fillRotateDeg += rotateDeg;       

                        // 防止超出360度
                        if(fillRotateDeg > 360) {
                            rotateDeg = 360 - fillRotateDeg + rotateDeg;
                            fillRotateDeg = 360;
                        }

                        // 提示的线旋转
                        tipRadiusLine.rotate(rotateDeg, centerPoint);
                        // 填充的线旋转
                        fillLongLine.rotate(rotateDeg, centerPoint);

                        // 获取填充线与用户绘制线的交集点
                        var intersectionsDraw = fillLongLine.getIntersections(drawPath);
                        // 获取填充线与提示圆形的交集点
                        var intersectionsCircle = fillLongLine.getIntersections(tipCircle);

                        // 填充线的起点
                        var point1 = centerPoint;
                        if (intersectionsDraw.length) {
                            point1 = intersectionsDraw[0].point;
                        }

                        // 填充线的终点
                        var point2 = point1;
                        if (intersectionsCircle.length) {
                            point2 = intersectionsCircle[0].point;
                        }

                        // 绘制填充线
                        var fillLine = new Path.Line(point1, point2);
                        // fillLines用于再次重新开始绘制
                        fillLines.push(fillLine);
                        fillLine.strokeWidth = 2.5;
                        fillLine.strokeColor = '#fff';

                        // 最终画的圆(最终形成用户画的圆形)
                        if(!resultCircle) {
                            resultCircle = new Path();
                            resultCircle.visible = false;
                        }
                        // 把起点连接起来(最终形成用户画的圆形)
                        resultCircle.add(point1);

                        // 判断画的好不好
                        var distance = point1.getDistance(point2);
                        // 每一条填充线的长度接近0的话,这个圆就画的很圆
                        perfect -= (distance / circleRadius * rotateDeg / 360) * 100;

                        // 防止分数出现负数
                        if (perfect < 0) {
                            perfect = 0;
                        }

                        console.log(perfect);
                    } else {
                        if(!resultCircle.visible) {
                            // 关闭路径
                            resultCircle.closed = true;
                            // 平滑的路径
                            resultCircle.smooth();
                            resultCircle.strokeColor = '#FFEB3B';
                            resultCircle.strokeWidth = 3;
                            resultCircle.opacity = 0;
                            resultCircle.visible = true;
                        } else {
                            if(resultCircle.opacity < 0.75) {
                                var opacity = resultCircle.opacity + 1 * event.delta;

                                // 防止透明度超出
                                if (opacity > 1) {
                                    opacity = 1;
                                }

                                // 显示最终绘制的圆
                                resultCircle.opacity = opacity;
                                // 隐藏绘制的线
                                drawPath.opacity = 1 - opacity;                            
                            } else {
                                // 弹出分数
                                if(!showResult) {
                                    alert(parseInt(perfect) + '分');
                                    showResult = true;
                                }
                            }
                        }
                    }
                }           
            }

            // 每秒最多调用60次;执行onFrame函数后,视图将自动重新绘制;
            console.log('动画执行啦');
        }

        /**
         * 鼠标按下触发
         * @param  {[type]} event [description]
         * @return {[type]}       [description]
         * @author 懂点君 公众号:HTML5 WEB前端分享
         */
        function onMouseDown(event) {
            if(drawStatus === 1 && !drawPath) {
                drawPath = new Path({
                    segments: [event.point],
                    strokeColor: '#fff',
                });
                drawPath.strokeWidth = 6;                
            }

            console.log('鼠标按下啦');
        }

        /**
         * 鼠标拖拽触发
         * @param  {[type]} event [description]
         * @return {[type]}       [description]
         * @author 懂点君
         */
        function onMouseDrag(event) {
            if(drawStatus === 1) {
                drawPath.add(event.point);
            }

            console.log('鼠标拖拽啦');
        }

        /**
         * 鼠标抬起触发
         * @param  {[type]} event [description]
         * @return {[type]}       [description]
         * @author 懂点君 公众号:HTML5 WEB前端分享
         */
        function onMouseUp(event) {
            if(drawStatus === 1 && drawPath) {
                // 绘制结束
                drawStatus = 2;
            }
            
            console.log('鼠标抬起啦');
        }

        $('.btn').click(function() {
            // 移除图形
            tipCircle.remove();
            tipRadiusLine.remove();
            fillLongLine.remove();
            resultCircle.remove();
            drawPath.remove();
            fillLines.forEach(function (line) {
                line.remove();
            })

            // 绘制提示的圆形
            tipCircle = new Path.Circle(centerPoint, circleRadius);
            tipCircle.strokeColor = '#fff';
            tipCircle.strokeWidth = 3;

            // 绘制提示的半径
            tipRadiusLine = new Path.Line(centerPoint, new Point(vw2 - circleRadius, vh2));
            tipRadiusLine.strokeColor = '#fff';
            tipRadiusLine.rotate(110, centerPoint);

            // 填充线的起始线(先不设置颜色,隐藏起来)
            fillLongLine = new Path.Line(centerPoint, new Point(vh2 - vwMax, vh2));
            fillLongLine.rotate(110, centerPoint);

            // 定义绘制的状态
            drawStatus = 1;
            // 定义绘制路径对象
            drawPath = null;
            // 填充旋转角度
            fillRotateDeg = 0;
            // 填充线的集合
            fillLines = [];
            // 最终的画的圆
            resultCircle = null;
            // 默认完美度0
            perfect = 100;
            showResult = false;
        });
    </script>
</html>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懂点君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值