360前端星计划(一)

2017年四月初,有幸参加了奇虎360组织的前端星计划并且顺利拿到360搜索的暑假实习生offer,应360的波波老师(PS:真名裕波,绝对是程序员中最会主持的,主持界中代码写的最好的)的号召,写成博客分享给大家。
先放一张图给大家,这是在奇虎360总部参加星计划的最后一天拍的合影。
这里写图片描述
跟所有互联网公司校招一样,通过一次笔试以及一份作业去甄选了一些小伙伴,因为这次HR丹丹姐大发善心,所以名额扩至了60人,估计是这样,所以我才有幸入选的吧,毕竟笔试成绩还是有点低的。。。 (笔试:78,作业:90),看上去还可以? 其实笔试满分 160 ,作业满分 200 。。。哦,天呐!

贴出第三届前端星计划的作业题目:

任务要求如下
在移动设备上,“手势密码”是一个很常见的UI。实现一个移动网页,允许用户设置手势密码和验证手势密码。已设置的密码记录在本地 localStorage 中。
这里写图片描述

请同学们按照上面的需求实现这个网页,在手机上可用。可以不用太考虑古老机器的兼容性,最新的 android 和 iPhone 可用即可。

代码实现如下
为了结构清晰,模块化依赖使用了 requireJs 。偷个懒使用了JQuery方便各种选择器。
index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="./css/normalize.css"/>
    <link rel="stylesheet" href="./css/style.css"/>
</head>
<body>
<div id="unlock">
    <h1>手势密码</h1>
    <div class="unlock-bg"></div>
    <ul class="unlock-circle">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <p class="unlock-prompt">请输入手势密码</p>
    <div class="unlock-radio">
        <label><input name="Fruit" type="radio" checked="checked"/>&nbsp;&nbsp;&nbsp;设置密码</label><br/>
        <br/><label><input name="Fruit" type="radio"/>&nbsp;&nbsp;&nbsp;验证密码</label>
    </div>
</div>
<script src="./js/require.js" data-main="./js/main.js"></script>
</body>
</html>

入口 js 文件,main.js

require.config({
    paths : {
        "jquery" : "jquery-3.1.1.min"
    }
});

define(['jquery', 'calcAngle', 'init'],function($, calcAngle, unlockSeq){
    var seq = "";
    var $container = $('#unlock');
    var $li = $('.unlock-circle > li');
    var $p = $('.unlock-prompt');
    var $input = $('.unlock-radio input');
    var queue = [];                    //盛放已经装入的元素
    var lastData = {};                //存放上一次触碰的圆点
    var confirmSeq = "";              //用于设置密码的确认密码
    //预处理圆点的圆心以及其序号
    $li.each(function(index, elem){
        elem.index = index;
        elem.pos = {
            left: elem.offsetLeft + elem.offsetWidth / 2,
            top: elem.offsetTop + elem.offsetHeight / 2
        }
    });
    /*判断 localstorage 中是否存在值,如果不存在,那么默认输入解锁手势,
     若存在,则设置解锁手势,设置手势默认输入一遍*/

    $container.on('touchmove', touchMove);
    $container.on('touchend',function(event){
        var setFlag = $input.eq(0).prop('checked');                    //判断当前是否在设置密码
        if(lastData.$hr){
            lastData.$hr.remove();
            $container.off('touchmove');
            setTimeout(function(){                                       //800ms后页面初始化
                queue = [];
                lastData = {};
                seq = "";
                $('hr').remove();
                $p.html('请输入手势密码');
                $li.removeClass('unlock-selected')
                $container.on('touchmove', touchMove);
            },800);
            if(setFlag && confirmSeq){                //确认设置密码
                if(confirmSeq == seq){
                    localStorage.setItem("unlockSeq", confirmSeq);
                    unlockSeq = confirmSeq;
                    $input.removeProp('checked');
                    $input.eq(1).prop('checked', 'checked');                //变换至解锁状态,同时更新 localstroge
                    $p.html('密码设置成功');
                    confirmSeq = "";
                }
                else{
                    confirmSeq = "";
                    $p.html('两次输入的不一样');
                }
                return ;
            }
            if(setFlag && seq.length < 5){
                $p.html('密码太短,至少需要5个点');
                return ;
            }
            //初始设置密码
            if(setFlag && !confirmSeq) {                   //首次设置密码
                confirmSeq = seq;
                $p.html('请再次输入手势密码');
                return ;
            }
            if(!setFlag){                                  //验证密码
                if(!unlockSeq){                             //如果没有设置密码去验证密码,强行跳回设置密码
                    $input.removeProp('checked');
                    $input.eq(0).prop('checked', 'checked');
                    $p.html('请先设置密码');
                }
                else{
                    if(unlockSeq != seq) $p.html('输入的密码不正确');
                    else                 $p.html('密码正确!');
                }
            }
        }
    });

    function touchMove(event){
        var clientX = event.touches[0].clientX;
        var clientY = event.touches[0].clientY;
        var $target = collision(clientX, clientY);
        var angle = 0;
        if($target && $.inArray($target.prop('index'), queue) == -1){
            var index = $target.prop('index');
            queue.push(index);
            seq += index;
            $target.addClass('unlock-selected');
            var $hr = $('<hr/>');
            $container.append($hr);
            var pos = $target.prop('pos');
            //不是第一次进来,既已经在画线...
            if(lastData.$hr){
                angle = calcAngle(pos.left, pos.top, lastData.pos);
                lastData.$hr.css({
                    'width': dist(pos.left, pos.top, lastData.$target),
                    'transform': 'rotate(-'+ angle +'deg)'
                });
            }
            //保存这次的状态
            lastData.$hr = $hr;
            lastData.pos = pos;
            lastData.index = index;
            lastData.$target = $target;
            angle = calcAngle(clientX, clientY, lastData.pos);
            $hr.css({
                'left': pos.left,
                'top': pos.top,
                'width': dist(clientX, clientY, $target),
                'transform': 'rotate(-'+ angle +'deg)'
            });
        }else if(lastData.$hr){
            angle = calcAngle(clientX, clientY, lastData.pos);
            lastData.$hr.css({
                'width': dist(clientX, clientY, lastData.$target),
                'transform': 'rotate(-'+ angle +'deg)'
            });
        }
        event.preventDefault();                             //禁止默认行为
    }
    //碰撞检测
    function collision(x, y){
        var $target;
        var flag = false;
        $li.each(function(index, elem){
            var distance = dist(x, y, $(elem));
            if(distance < elem.offsetWidth / 2){
                flag = true;
                $target = $(elem);
            }
        });
        if(flag) return $target;
        else return null;
    }
    //计算 触点 到 LI 圆心的距离
    function dist(x, y, $target){
        var pos = $target.prop('pos');
        return Math.sqrt((x - pos.left) * (x - pos.left) + (y - pos.top) * (y - pos.top));
    }
});

具体代码实现请见:我的 github
运行实例(可在chorme下模拟):戳我看实例

更多干货请见系列文章。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值