• Javascript 实现[网红] 时间轮盘


    话不多说,先上图。

    成品链接

    大致效果如上图,接下来就开始制作吧。

    HTML部分:

    我们需要将容器旋转rotate使之以圆点为中心。

    怎么转呢,请看图。

    将同一级的容器用一个大的容器包裹起来,绝对定位。这时,所有的子容器会重合在一起。

    然后我们用360°去除以子容器个数,可以得到每个子容器的角度差,采用角度差来旋转每个容器。

    效果如图:

    我们可以看到,他是重合在一起的,应位默认的旋转中心是容器的中心,

    这时我们需要改变旋转中心点,

    添加css属性 transform-origin: -50% 50%;

    效果如图:

    我们可以发现此时旋转过后的图形超出了父容器,所以需要改变他的位置,根据旋转可知。

    图形总长度为子容器长度的3倍(中间空白处为一个子容器长度)

    高度为 空白处高度加上 子容器高度的两倍

    经过位置变换(再填上文字)

    效果如图:

    以上讲解代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>时间轮盘 一</title>
        <style>
            #wrapper {
                width: 500px;
                height: 500px;
                margin: 100px auto;
                background: #ccc;
            }
            .container {
                width: 100%;
                height: 100%;
                position: relative;
                left: 300px;
                top: 210px;
            }
            .box {
                width: 150px;
                height: 30px;
                background: orange;
                /* border: 1px solid black; */
                position: absolute;
                top: 0;
                left: 0;
                transform-origin: -50% 50%;
            }
        </style>
    </head>
    <body>
        <div id="wrapper">
            <div class="container">
                <div class="box">我是1</div>
                <div class="box" style="transform: rotate(45deg)">我是2</div>
                <div class="box" style="transform: rotate(90deg)">我是3</div>
                <div class="box" style="transform: rotate(135deg)">我是4</div>
                <div class="box" style="transform: rotate(180deg)">我是5</div>
                <div class="box" style="transform: rotate(225deg)">我是6</div>
                <div class="box" style="transform: rotate(270deg)">我是7</div>
                <div class="box" style="transform: rotate(315deg)">我是</div>
            </div>
        </div>
    </body>
    </html>

    基本布局就是这样,接下来我们需要多制作几个,分别存放星期、时分秒。

    成品HTML代码部分如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="stylesheet" href="css/TimeRoulette.css">
        <title>时间轮盘</title>
    </head>
    <body>
        <div class="wrapper">
            <h1 class="workTitle">时间轮盘</h1>
            <p class="one-text">天可补,海可填,南山可移,日月既往,不可复追。</p>
            <div class="timeBox">
                <div class="year-wrapper" title="点击更换背景图片">
                    <p></p>
                </div>
                <div class="week-wrapper">
                    <ul class="week-content">
    
                    </ul>
                </div>
                <div class="hours-wrapper">
                    <ul class="hours-content">
                        
                    </ul>
                </div>
                <div class="minutes-wrapper">
                    <ul class="minutes-content">
                       
                    </ul>
                </div>
                <div class="seconds-wrapper">
                    <ul class="seconds-content">
                       
                    </ul>
                </div>
            </div>
        </div>
    </body>
    <script src="js/jquery.js"></script>
    <script src="js/TimeRoulette.js"></script>
    </html>

    大家可以发现,我们的hrml中并没有数据,有关星期,时分秒,的数据我们通过js生成,毕竟太多了,而且有规律可循。

    这里我们使用了jquery来实现dom操作

    接下来就是JS部分了!

    首先我们需要几个函数,将数字转换成大写(仅做了1000以内),将年份转化为干纪年法(显得霸气),将24小时转化为时辰(实现一半,所以此处未加上)

    // 数字大小写转换
    function numberToZh(num) {
    var zh = ["零","壹","贰","叁","肆","伍","陆","柒","捌","玖","拾","佰","仟","万"];
    var res = "";
    if(num <= 10) {
        res = zh[num];
    } else if(num < 20) {
        var bits = num % 10;
        res = zh[10] + zh[bits];
    } else if(num < 100) {
        var bits = num % 10;
        var decade = parseInt(num / 10);
        if(bits == 0) {
            res = zh[decade] + zh[10] + "整";
        } else {
            res = zh[decade] + zh[10] + zh[bits];
        }
        
    }
    return res;
    }
    
    // 干支纪年法
    function toAncientYear(year) {
    var sky = ["", "辛", "壬", "癸", "甲", "乙", "丙", "丁", "戊", "己", "庚"];
    var land = ["", "酉", "戌", "亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申"];
    
    // 用年份除以10得数中余数相对应的便是天干
    var one = year % 10;
    // 用年份除以12得数中余数相对应的便是地支
    var two = year % 12;
    
    var res = sky[one] + land[two];
    return res;
    }
    
    //时间转时辰
    function toAncientHours(num) {
        var res = "";
        switch(num) {
            case 1 : res = "子";break;
            case 2 : res = "丑";break;
            case 3 : res = "寅";break;
            case 4 : res = "卯";break;
            case 5 : res = "辰";break;
            case 6 : res = "巳";break;
            case 7 : res = "午";break;
            case 8 : res = "未";break;
            case 9 : res = "申";break;
            case 10 : res = "酉";break;
            case 11 : res = "戌";break;
            case 12 : res = "亥";break;
        }
        return res;
    }

    有了这几个小函数,我们就可以初始化时间轮盘了

    代码:

    function init() {
    
    // 更换背景图片
    $(".timeBox .year-wrapper").click(function(){
        $("body").css("background-image", "url(images/background"+ Math.ceil(Math.random()*4) +".jpg)")
    })
    // 设置文本值
    setNumText();
    
    // 设置干支纪年时间
    var nowYear = (new Date).getFullYear();
    var acientYear = toAncientYear(nowYear);
    $(".year-wrapper p").text(acientYear).attr("title","公元" + nowYear + "农历" + acientYear +"年");
    
    // 初始化内容位置,旋转到指定角度
    var weekLen = $(".week-content li").length;
    var weekDeg = 360/weekLen; 
    $(".week-content li").each(function(index) {
        $(this).css({
            "transform":"rotate("+index*weekDeg+"deg)",
            "transform-origin":"-100% 50%",
            "margin-left":parseInt($(this).css("width")) * 3 + "px",
            "margin-top":parseInt($(this).css("width")) * 2 - 10 + "px"
        })
    })
    
    //
    var hoursLen = $(".hours-content li").length;
    var hoursDeg = 360/hoursLen; 
    $(".hours-content li").each(function(index) {
        $(this).css({
            "transform":"rotate("+index*hoursDeg+"deg)",
            "transform-origin":"-250% 50%",
            "margin-left":parseInt($(this).css("width")) * 6 + "px",
            "margin-top":parseInt($(this).css("width")) * 3.5 - 10 + "px"
        })
    })
    
    //
    var minutesLen = $(".minutes-content li").length;
    var minutesDeg = 360/minutesLen;
    $(".minutes-content li").each(function(index) {
        $(this).css({
            "transform":"rotate("+index*minutesDeg+"deg)",
            "transform-origin":"-400% 50%",
            "margin-left":parseInt($(this).css("width")) * 9 + "px",
            "margin-top":parseInt($(this).css("width")) * 5 - 10 + "px"
        })
    })
    
    //
    var secondsLen = $(".seconds-content li").length;
    var secondsDeg = 360/secondsLen;
    $(".seconds-content li").each(function(index) {
        $(this).css({
            "transform":"rotate("+index*secondsDeg+"deg)",
            "transform-origin":"-550% 50%",
            "margin-left":parseInt($(this).css("width")) * 12 + "px",
            "margin-top":parseInt($(this).css("width")) * 6.5 - 10 + "px"
        })
    })
    
    //每秒刷新一次
    run();
    }
    // 设置文本内容
    function setNumText(){
        for(var i = 7; i > 0; i --) {
            $(".week-content").append("<li data-time = "+ i +"> 星期"+ numberToZh(i) +"<li>")
        }
        for(var i = 12;i > 0; i --) {
            $(".hours-content").append("<li data-time = "+ i +">"+ numberToZh(i) +"时<li>")
        }
        for(var i = 60;i > 0; i --) {
            $(".minutes-content").append("<li data-time = "+ i +">"+ numberToZh(i) +"<li>")
        }
        for(var i = 60;i > 0; i --) {
            $(".seconds-content").append("<li data-time = "+ i +">"+ numberToZh(i) +"<li>")
        }
    }

    此时,项目的静态效果已经有了,我们需要让他动起来,也就是上面代码中的run()函数

    // 刷新轮盘
    function run() {
        clearInterval(timer);
        var date = new Date();//获取本地时间
        // 分别获取时分秒年
        var week = date.getDay();
        var hours = date.getHours() % 12;
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
    
        // 计算对应的旋转角度差
        // rotateIndexH 为定义的全局变量,存储了小时的旋转圈数
        // rotateIndexM、rotateIndexS 同理为分、秒的
        // week
        var weekRote = 360 / 7 * (week);
    
        // hours
        var hoursRote = 360 / 12 * (hours) + rotateIndexH * 360;
    
        // minites secondes
        var tempDeg = 360 / 60;
        var minutesRote = tempDeg * (minutes) + rotateIndexM * 360;
        var secondsRote = tempDeg * (seconds) + rotateIndexS * 360;
        //var secondsRote = tempDeg * (seconds + 1) + rotateIndexS*360; // 加一是为了滚到位置再变色,去掉会先变色再滚到位置
    
        // 旋转 秒 的位置
        $(".seconds-wrapper").css("transform", "rotate(" + secondsRote + "deg)");
    
        // 点亮 由于时间是从0开始计数的所以这里判断
        var secondDot = seconds == 0 ? 60 : seconds;
        var minuteDot = minutes == 0 ? 60 : minutes;
        var hourDot = hours == 0 ? 60 : hours;
        var weekDot = hours == 0 ? 7 : week;
        // $(".hour-content li[data-time="+hourDot+"]").addClass("active").next("li").removeClass("active");
        // $(".minutes-content li[data-time="+minuteDot+"]").addClass("active").prev("li").removeClass("active");
        //$(".seconds-content li[data-time='"+secondDot+"']").addClass("active").next("li").removeClass("active");
    
        //为了节省性能,每当秒满60时,才去指向时、分的
        if (seconds == 59 || rotateIndexH == 0) {
            $(".week-wrapper").css("transform", "rotate(" + weekRote + "deg)");
            $(".hours-wrapper").css("transform", "rotate(" + hoursRote + "deg)");
            $(".minutes-wrapper").css("transform", "rotate(" + minutesRote + "deg)");
    
            //给当前时间的节点添加active 类 (这里 练一下选择器所以写成了一句。)
            $(".week-content li[data-time=" + weekDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
            $(".hours-content li[data-time=" + hourDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
            $(".minutes-content li[data-time=" + minuteDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
        }
    
        // 秒时每秒都需要更新的
        $(".seconds-content li[data-time=" + secondDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
    
        // 旋转圈数加一(解决360°转到0°时的bug)
        hours === 11 ? rotateIndexH++ : 0;
        minutes === 59 ? rotateIndexM++ : 0;
        seconds === 59 ? rotateIndexS++ : 0;
    
        // 让函数一秒钟执行一次
        var timer = setTimeout(run, 1000);
    }

    具体都做了详细的注释,这里就不多提,有个小问题,

    $(".seconds-content li[data-time='"+secondDot+"']").addClass("active").next("li").removeClass("active");
    不能获取,有人知道原因吗。。。。
    欢迎告知。

    CSS部分就不多说了,看代码:
    *{
        padding: 0;
        margin: 0;
        color: #eee;
        user-select: none;
    }
    body {
        background: #bebebe;
        background-image: url(../images/background2.jpg);
        background-repeat: no-repeat;
        background-position:top;
        background-attachment:fixed;
    }
    ul {
        list-style: none;
    }
    li {
        position: absolute;
        display: inline-block;
    }
    .wrapper {
        overflow: hidden;
        height: 100vh;
        box-sizing: border-box;
        padding-top: 50px;
    }
    .timeBox {
        margin: 5px auto;
        width: 800px;
        height: 800px;
        /* background: #ccc; */
        position: relative;
    }
    .wrapper .workTitle {
        color: #878787;
        font-family: Arial, Helvetica, sans-serif;
        text-align: center;
        line-height: 2em;
        letter-spacing: .3em;
    }
    .wrapper .one-text {
        color: #dbdbdb;
        text-align: center;
        font-size: 18px;
        font-style: italic;
        text-shadow: 8px 7px 4px rgba(100,150,200,0.8);
        letter-spacing: .2em;
    }
    .timeBox .week-wrapper {
        transition: 1s;
        position: absolute;
        width: 200px;
        height: 200px;
        top: 300px;
        left: 300px;
        z-index: 9;
    }
    .timeBox .week-wrapper .week-content li {
        width: 50px;
    }
    .timeBox .hours-wrapper {
        transition: ease 1s;
        position: absolute;
        width: 350px;
        height: 350px;
        top: 225px;
        left: 225px;
        z-index: 8;
    }
    .timeBox .hours-wrapper .hours-content li {
        width: 50px;
    }
    .timeBox .minutes-wrapper {
        transition: 1s;
        position: absolute;
        width: 500px;
        height: 500px;
        top: 150px;
        left: 150px;
        z-index: 7;
    }
    .timeBox .minutes-wrapper .minutes-content li {
        width: 50px;
    }
    .timeBox .seconds-wrapper {
        transition: all 1s linear;
        position: absolute;
        width: 650px;
        height: 650px;
        top: 75px;
        left: 75px;
        z-index: 6;
    }
    .timeBox .seconds-wrapper .seconds-content li {
        transition: .5s;
        width: 50px;
    }
    .timeBox .year-wrapper {
        width: 80px;
        height: 80px;
        border-radius: 50%;
        position: absolute;
        top:50%;
        left: 50%;
        transform: translate(-50%,-50%);
        cursor: pointer;
        z-index: 10;
    }
    .timeBox .year-wrapper p {
        text-align: center;
        line-height: 80px;
        font-size: 18px;
        font-weight: bold;
    }
    .timeBox .year-wrapper::after {
        content:"";
        display: block;
        width: 300px;
        height: 26px;
        /* background:rgba(139,90,43); */
        /* border:1px solid #aaa;
        border-radius: 3px; */
        position: absolute;
        top:27px;
        left: 80px;
    }
    .active {
        /* color: rgb(139,90,43); */
        color: #FF7F00;
    }
    @media screen and (max-700px) {
        .wrapper .timeBox {
            transform: scale(0.5,0.5) translate(-50%,-50%);
            margin: 0 auto;
        }
        .wrapper .timeBox ul li {
            font-size:16px;
        }
    }
    
    

    最后,附上完整的代码;

    var rotateIndexH = 0;
    var rotateIndexM = 0;
    var rotateIndexS = 0;
    init();
    
    function init() {
    
        // 更换背景图片
        $(".timeBox .year-wrapper").click(function () {
            $("body").css("background-image", "url(images/background" + Math.ceil(Math.random() * 4) + ".jpg)")
        })
        // 设置文本值
        setNumText();
    
        // 设置干支纪年时间
        var nowYear = (new Date).getFullYear();
        var acientYear = toAncientYear(nowYear);
        $(".year-wrapper p").text(acientYear).attr("title", "公元" + nowYear + "农历" + acientYear + "年");
    
        // 初始化内容位置,旋转到指定角度
        var weekLen = $(".week-content li").length;
        var weekDeg = 360 / weekLen;
        $(".week-content li").each(function (index) {
            $(this).css({
                "transform": "rotate(" + index * weekDeg + "deg)",
                "transform-origin": "-100% 50%",
                "margin-left": parseInt($(this).css("width")) * 3 + "px",
                "margin-top": parseInt($(this).css("width")) * 2 - 10 + "px"
            })
        })
    
        //
        var hoursLen = $(".hours-content li").length;
        var hoursDeg = 360 / hoursLen;
        $(".hours-content li").each(function (index) {
            $(this).css({
                "transform": "rotate(" + index * hoursDeg + "deg)",
                "transform-origin": "-250% 50%",
                "margin-left": parseInt($(this).css("width")) * 6 + "px",
                "margin-top": parseInt($(this).css("width")) * 3.5 - 10 + "px"
            })
        })
    
        //
        var minutesLen = $(".minutes-content li").length;
        var minutesDeg = 360 / minutesLen;
        $(".minutes-content li").each(function (index) {
            $(this).css({
                "transform": "rotate(" + index * minutesDeg + "deg)",
                "transform-origin": "-400% 50%",
                "margin-left": parseInt($(this).css("width")) * 9 + "px",
                "margin-top": parseInt($(this).css("width")) * 5 - 10 + "px"
            })
        })
    
        //
        var secondsLen = $(".seconds-content li").length;
        var secondsDeg = 360 / secondsLen;
        $(".seconds-content li").each(function (index) {
            $(this).css({
                "transform": "rotate(" + index * secondsDeg + "deg)",
                "transform-origin": "-550% 50%",
                "margin-left": parseInt($(this).css("width")) * 12 + "px",
                "margin-top": parseInt($(this).css("width")) * 6.5 - 10 + "px"
            })
        })
    
        //每秒刷新一次
        run();
    }
    
    
    // 设置文本内容
    function setNumText() {
        for (var i = 7; i > 0; i--) {
            $(".week-content").append("<li data-time = " + i + "> 星期" + numberToZh(i) + "<li>")
        }
        for (var i = 12; i > 0; i--) {
            $(".hours-content").append("<li data-time = " + i + ">" + numberToZh(i) + "时<li>")
        }
        for (var i = 60; i > 0; i--) {
            $(".minutes-content").append("<li data-time = " + i + ">" + numberToZh(i) + "<li>")
        }
        for (var i = 60; i > 0; i--) {
            $(".seconds-content").append("<li data-time = " + i + ">" + numberToZh(i) + "<li>")
        }
    }
    
    // 数字大小写转换
    function numberToZh(num) {
        var zh = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "拾", "佰", "仟", "万"];
        var res = "";
        if (num <= 10) {
            res = zh[num];
        } else if (num < 20) {
            var bits = num % 10;
            res = zh[10] + zh[bits];
        } else if (num < 100) {
            var bits = num % 10;
            var decade = parseInt(num / 10);
            if (bits == 0) {
                res = zh[decade] + zh[10] + "整";
            } else {
                res = zh[decade] + zh[10] + zh[bits];
            }
    
        }
        return res;
    }
    
    // 刷新轮盘
    function run() {
        clearInterval(timer);
        var date = new Date();//获取本地时间
        // 分别获取时分秒年
        var week = date.getDay();
        var hours = date.getHours() % 12;
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
    
        // 计算对应的旋转角度差
        // rotateIndexH 为定义的全局变量,存储了小时的旋转圈数
        // rotateIndexM、rotateIndexS 同理为分、秒的
        // week
        var weekRote = 360 / 7 * (week);
    
        // hours
        var hoursRote = 360 / 12 * (hours) + rotateIndexH * 360;
    
        // minites secondes
        var tempDeg = 360 / 60;
        var minutesRote = tempDeg * (minutes) + rotateIndexM * 360;
        var secondsRote = tempDeg * (seconds) + rotateIndexS * 360;
        //var secondsRote = tempDeg * (seconds + 1) + rotateIndexS*360; // 加一是为了滚到位置再变色,去掉会先变色再滚到位置
    
        // 旋转 秒 的位置
        $(".seconds-wrapper").css("transform", "rotate(" + secondsRote + "deg)");
    
        // 点亮 由于时间是从0开始计数的所以这里判断
        var secondDot = seconds == 0 ? 60 : seconds;
        var minuteDot = minutes == 0 ? 60 : minutes;
        var hourDot = hours == 0 ? 60 : hours;
        var weekDot = hours == 0 ? 7 : week;
        // $(".hour-content li[data-time="+hourDot+"]").addClass("active").next("li").removeClass("active");
        // $(".minutes-content li[data-time="+minuteDot+"]").addClass("active").prev("li").removeClass("active");
        //$(".seconds-content li[data-time='"+secondDot+"']").addClass("active").next("li").removeClass("active");
    
        //为了节省性能,每当秒满60时,才去指向时、分的
        if (seconds == 59 || rotateIndexH == 0) {
            $(".week-wrapper").css("transform", "rotate(" + weekRote + "deg)");
            $(".hours-wrapper").css("transform", "rotate(" + hoursRote + "deg)");
            $(".minutes-wrapper").css("transform", "rotate(" + minutesRote + "deg)");
    
            //给当前时间的节点添加active 类 (这里 练一下选择器所以写成了一句。)
            $(".week-content li[data-time=" + weekDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
            $(".hours-content li[data-time=" + hourDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
            $(".minutes-content li[data-time=" + minuteDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
        }
    
        // 秒时每秒都需要更新的
        $(".seconds-content li[data-time=" + secondDot + "]").parents("ul:first").children("li[class='active']").removeClass("active").end().end().addClass("active");
    
        // 旋转圈数加一(解决360°转到0°时的bug)
        hours === 11 ? rotateIndexH++ : 0;
        minutes === 59 ? rotateIndexM++ : 0;
        seconds === 59 ? rotateIndexS++ : 0;
    
        // 让函数一秒钟执行一次
        var timer = setTimeout(run, 1000);
    }
    
    // 干支纪年法
    function toAncientYear(year) {
        var sky = ["", "辛", "壬", "癸", "甲", "乙", "丙", "丁", "戊", "己", "庚"];
        var land = ["", "酉", "戌", "亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申"];
    
        // 用年份除以10得数中余数相对应的便是天干
        var one = year % 10;
        // 用年份除以12得数中余数相对应的便是地支
        var two = year % 12;
    
        var res = sky[one] + land[two];
        return res;
    }
    
    //时间转时辰
    function toAncientHours(num) {
        var res = "";
        switch (num) {
            case 1: res = "子"; break;
            case 2: res = "丑"; break;
            case 3: res = "寅"; break;
            case 4: res = "卯"; break;
            case 5: res = "辰"; break;
            case 6: res = "巳"; break;
            case 7: res = "午"; break;
            case 8: res = "未"; break;
            case 9: res = "申"; break;
            case 10: res = "酉"; break;
            case 11: res = "戌"; break;
            case 12: res = "亥"; break;
        }
        return res;
    }

    欢迎交流学习。

    转载请注明出处,谢谢!

    
    

     源码地址 提取码:aiml 

  • 相关阅读:
    Redis高可用配置(Keepalived)
    Redis断线重连编码注意事项
    Redis持久化配置
    真正实现Netty私有协议开发
    winform 程序隐藏窗口运行
    VirtualBox设置共享文件夹和镜像访问的方法
    SSIS父子维度
    SSIS 抽取excel出错:所请求的 OLE DB 访问接口 Microsoft.ACE.OLEDB.12.0 尚未注册
    .net C#实现 中文转Unicode、Unicode转中文 及与js对应关系
    HttpHelper使用记录
  • 原文地址:https://www.cnblogs.com/tcxq/p/10758647.html
Copyright © 2020-2023  润新知