精华内容
下载资源
问答
  • 翻牌广告

    2013-04-24 10:30:10
    <!...-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"...--[2,753,1] published at 2013-04-11 17:18:31 from #152 by system--&...

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <!--[2,753,1] published at 2013-04-11 17:18:31 from #152 by system-->
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <meta name="keywords" content="">
    <meta name="description" content="">
    <meta name="publishid" content="2,753,1">
    <meta name="stencil" content="PGLS000027">
    <meta name="verify-v1" content="6HtwmypggdgP1NLw7NOuQBI2TW8+CfkYCoyeB8IDbn8=" />
    <script src="http://activity.itcpn.net/liantongjs/headtech.js"></script>
    </head>
    <body>
    <!-- Flash翻牌 开始 -->
    <style type="text/css">
    #flipper_div{ width:950px; margin:0px auto;}
    #ghc1{ width:950px; background:url(http://d2.sina.com.cn/shh/lechan/20120323keji/zhitou_bg.jpg) no-repeat 0 0;}
    </style>
    <div id="flipper_div" data-sudaclick="pp_zq"></div>
    <script type="text/javascript">
    <!--

    var fp_data = new Array();

    // AE维护部分 开始

    //位置1
    fp_data.push(["482303_145-75.jpg","http://www.baidu.com"]);
    fp_data.push(["482003.jpg","http://www.baidu.com"]);


    //位置2
    fp_data.push(["481937.jpg","http://www.baidu.com"]);
    fp_data.push(["481937.jpg","http://www.baidu.com"]);
    //位置3
    fp_data.push(["480862.jpg","http://www.baidu.com"]);
    fp_data.push(["427036.jpg","http://www.baidu.com"]);

    //AE维护部分 结束
    var fp_pics="",fp_links="";
    var fp_lens = fp_data.length;
    for(var i=0; i<fp_lens; i++){
     fp_pics += fp_data[i][0];
     fp_links += escape(fp_data[i][1]);
     if(i%2==0 && i!=fp_lens-1){
      fp_pics += "§";
      fp_links += "§";
     }else if(i%2==1 && i!=fp_lens-1){
      fp_pics += "§_§";
      fp_links += "§_§";
     }
    }
    var oswf = new sinaFlash("flipper.swf", "flipper", 600, 90, "7", "#FFFFFF", false, "High");
    oswf.addParam("allowScriptAccess", "always");
    oswf.addParam("menu", "false");
    oswf.addParam("wmode", "opaque");
    oswf.addParam("scale", "noscale");
    oswf.addVariable("pic_width", "10");
    oswf.addVariable("pic_height", "10");
    oswf.addVariable("colnum", "5");
    oswf.addVariable("hspace", "15");
    oswf.addVariable("vspace", "20");
    oswf.addVariable("flip_time", "200");
    oswf.addVariable("pause_time", "2000");
    oswf.addVariable("pics", fp_pics);
    oswf.addVariable("urls", fp_links);
    oswf.addVariable("rand", "0");
    oswf.write("flipper_div");
    //-->
    </script>
    <!-- Flash翻牌 结束 -->
    </html>

    展开全文
  • 翻牌游戏(海贼王)

    2019-08-06 15:57:31
    翻牌游戏 技术点: 1.html 2.CSS 3.javascript 效果分析: 1.整个项目的背景颜色为#999999; 2.页面显示为3*10的表格; 3.表格居于窗口的中间; 4.表格有个标题“找相同牌游戏”,位于表格中间; 5.表格中所有的...

    翻牌游戏
    技术点:
    1.html
    2.CSS
    3.javascript

    效果分析:
    1.整个项目的背景颜色为#999999;
    2.页面显示为3*10的表格;
    3.表格居于窗口的中间;
    4.表格有个标题“找相同牌游戏”,位于表格中间;
    5.表格中所有的单元格插入相同图片作为背景图。

     

    功能分析:
    1.页面运行时,所有的牌处于背面显示状态;
    2.如果翻的第一张和第二张不一样时,两张牌自动返回背面显示状态;如果一致,则同时显示数字,然后继续翻牌;
    3.所有的牌都显示完毕后,弹出一个窗口,显示“用时累计”

    第一部分

    HTML制表格

    <table border="1px" cellpadding="0" cellspacing="1">
                <caption><h2 size="13px">找 相 同 游 戏</h2></caption>
                <tr>
                    <td><img src="img/img0.jpg" id="img0" οnclick="fanpai(0)"/></td>
                    <td><img src="img/img0.jpg" id="img1" οnclick="fanpai(1)"/></td>
                    <td><img src="img/img0.jpg" id="img2" οnclick="fanpai(2)"/></td>
                    <td><img src="img/img0.jpg" id="img3" οnclick="fanpai(3)"/></td>
                    <td><img src="img/img0.jpg" id="img4" οnclick="fanpai(4)"/></td>
                    <td><img src="img/img0.jpg" id="img5" οnclick="fanpai(5)"/></td>
                    <td><img src="img/img0.jpg" id="img6" οnclick="fanpai(6)"/></td>
                    <td><img src="img/img0.jpg" id="img7" οnclick="fanpai(7)"/></td>
                    <td><img src="img/img0.jpg" id="img8" οnclick="fanpai(8)"/></td>
                    <td><img src="img/img0.jpg" id="img9" οnclick="fanpai(9)"/></td>    
                </tr>
                <tr>
                     <td><img src="img/img0.jpg" id="img10" οnclick="fanpai(10)"/></td>
                    <td><img src="img/img0.jpg" id="img11" οnclick="fanpai(11)"/></td>
                    <td><img src="img/img0.jpg"  id="img12" οnclick="fanpai(12)"/></td>
                    <td><img src="img/img0.jpg"  id="img13" οnclick="fanpai(13)"/></td>
                    <td><img src="img/img0.jpg"  id="img14" οnclick="fanpai(14)"/></td>
                    <td><img src="img/img0.jpg"  id="img15" οnclick="fanpai(15)"/></td>
                    <td><img src="img/img0.jpg"  id="img16" οnclick="fanpai(16)"/></td>
                    <td><img src="img/img0.jpg"  id="img17" οnclick="fanpai(17)"/></td>
                    <td><img src="img/img0.jpg"  id="img18" οnclick="fanpai(18)"/></td>
                    <td><img src="img/img0.jpg"  id="img19" οnclick="fanpai(19)"/></td>
                </tr>
                <tr>
                    <td><img src="img/img0.jpg"  id="img20" οnclick="fanpai(20)"/></td>
                    <td><img src="img/img0.jpg"  id="img21" οnclick="fanpai(21)"/></td>
                    <td><img src="img/img0.jpg"  id="img22" οnclick="fanpai(22)"/></td>
                    <td><img src="img/img0.jpg"  id="img23" οnclick="fanpai(23)"/></td>
                    <td><img src="img/img0.jpg"  id="img24" οnclick="fanpai(24)"/></td>
                    <td><img src="img/img0.jpg"  id="img25" οnclick="fanpai(25)"/></td>
                    <td><img src="img/img0.jpg"  id="img26" οnclick="fanpai(26)"/></td>
                    <td><img src="img/img0.jpg"  id="img27" οnclick="fanpai(27)"/></td>
                    <td><img src="img/img0.jpg"  id="img28" οnclick="fanpai(28)"/></td>
                    <td><img src="img/img0.jpg"  id="img29" οnclick="fanpai(29)"/></td>
                </tr>
            </table>

    CSS部分设计

    <style type="text/css">
                table{
                    border: 1px solid yellow;
                    width: 1200px;
                    height: 450px;
                }
                td{
                    width: 120px;
                    height:150px;
                }
                img{
                    width: 120px;
                    height: 150px;
                }
            </style>

    功能实现

    1.触发翻牌事件:

    (1)翻第一张牌;(2)翻第二张牌;

    2.盖牌,再接着翻第一张牌

    3.检查牌翻完成功与否

    4.洗牌

    JS部分代码:

    <script type="text/javascript">
            var pai=[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15];
            var flag=false;
            var oneid=-1;
            var index=0;
            function fanpai(id){
                if(pai[id]==-1){return;}
                    document.getElementById("img"+id).src="img/"+pai[id]+".jpg";
                    if(flag){//翻第2张
                        if(pai[id]==pai[oneid]){pai[id]=-1;pai[oneid]=-1;}
                        else{setTimeout("koupai("+id+","+oneid+")",100);}
                        oneid=-1;
                        flag=false;
                    }
                    else{//翻第1张
                        oneid=id;
                        flag=true;
                    }
                    checkSuccess();          
            }
        
            //每次载入页面进行重新洗牌
            function xipai(){
                var a,b,temp;
                for(var i=0;i<30;i++){
                    var a=Math.floor(Math.random()*30);
                    var b=Math.floor(Math.random()*30);
                    temp=pai[a];
                    pai[a]=pai[b];
                    pai[b]=temp;
                }
            }
            //第一次与第二次不相同,扣住两张牌
            function koupai(id,oneid){
                document.getElementById("img"+id).src="img/img0.jpg";
                document.getElementById("img"+oneid).src="img/img0.jpg";
            }
            //每次翻完两张相同的后,检验是否全部成功翻开
            function checkSuccess(){
                for(var i=0;i<30;i++){
                    if(pai[i]!=-1)
                        return;
                    }
                alert("Hello 恭喜,恭喜!!!你赢了!!!");
                location.reload();
            }
             xipai();

    附加显示时间

     function showTime(){
                var today=new Date();
                var year=today.getFullYear();//获得年
                var month=today.getMonth()+1;//获得月
                var day=today.getDate();//获得日
                var hh=today.getHours();//获得小时
                var mm=today.getMinutes();//获得分钟
                var ss=today.getSeconds();//获得秒    
                document.getElementById("mycolock").innerHTML=year+"年"+month+"月"+day+"日"+hh+":"+mm+":"+ss;
            }
                window.setInterval("showTime()",1000);//每隔1秒取一次当前的时间
                window.οnlοad=showTiwanwme;

    运行效果展示:

     

     

     

    完整代码:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <link href="img/test.jpg" rel="icon" sizes="any" type="image/x-icon" />
            <title>找相同游戏</title>
            <style type="text/css">
                table{
                    border: 1px solid yellow;
                    width: 1200px;
                    height: 450px;
                }
                td{
                    width: 120px;
                    height:150px;
                }
                img{
                    width: 120px;
                    height: 150px;
                }
            </style>
        </head>
        <body bgcolor="#999999">
            <center>
            <table border="1px" cellpadding="0" cellspacing="1">
                <caption><h2 size="13px">找 相 同 游 戏</h2></caption>
                <tr>
                    <td><img src="img/img0.jpg" id="img0" οnclick="fanpai(0)"/></td>
                    <td><img src="img/img0.jpg" id="img1" οnclick="fanpai(1)"/></td>
                    <td><img src="img/img0.jpg" id="img2" οnclick="fanpai(2)"/></td>
                    <td><img src="img/img0.jpg" id="img3" οnclick="fanpai(3)"/></td>
                    <td><img src="img/img0.jpg" id="img4" οnclick="fanpai(4)"/></td>
                    <td><img src="img/img0.jpg" id="img5" οnclick="fanpai(5)"/></td>
                    <td><img src="img/img0.jpg" id="img6" οnclick="fanpai(6)"/></td>
                    <td><img src="img/img0.jpg" id="img7" οnclick="fanpai(7)"/></td>
                    <td><img src="img/img0.jpg" id="img8" οnclick="fanpai(8)"/></td>
                    <td><img src="img/img0.jpg" id="img9" οnclick="fanpai(9)"/></td>    
                </tr>
                <tr>
                     <td><img src="img/img0.jpg" id="img10" οnclick="fanpai(10)"/></td>
                    <td><img src="img/img0.jpg" id="img11" οnclick="fanpai(11)"/></td>
                    <td><img src="img/img0.jpg"  id="img12" οnclick="fanpai(12)"/></td>
                    <td><img src="img/img0.jpg"  id="img13" οnclick="fanpai(13)"/></td>
                    <td><img src="img/img0.jpg"  id="img14" οnclick="fanpai(14)"/></td>
                    <td><img src="img/img0.jpg"  id="img15" οnclick="fanpai(15)"/></td>
                    <td><img src="img/img0.jpg"  id="img16" οnclick="fanpai(16)"/></td>
                    <td><img src="img/img0.jpg"  id="img17" οnclick="fanpai(17)"/></td>
                    <td><img src="img/img0.jpg"  id="img18" οnclick="fanpai(18)"/></td>
                    <td><img src="img/img0.jpg"  id="img19" οnclick="fanpai(19)"/></td>
                </tr>
                <tr>
                    <td><img src="img/img0.jpg"  id="img20" οnclick="fanpai(20)"/></td>
                    <td><img src="img/img0.jpg"  id="img21" οnclick="fanpai(21)"/></td>
                    <td><img src="img/img0.jpg"  id="img22" οnclick="fanpai(22)"/></td>
                    <td><img src="img/img0.jpg"  id="img23" οnclick="fanpai(23)"/></td>
                    <td><img src="img/img0.jpg"  id="img24" οnclick="fanpai(24)"/></td>
                    <td><img src="img/img0.jpg"  id="img25" οnclick="fanpai(25)"/></td>
                    <td><img src="img/img0.jpg"  id="img26" οnclick="fanpai(26)"/></td>
                    <td><img src="img/img0.jpg"  id="img27" οnclick="fanpai(27)"/></td>
                    <td><img src="img/img0.jpg"  id="img28" οnclick="fanpai(28)"/></td>
                    <td><img src="img/img0.jpg"  id="img29" οnclick="fanpai(29)"/></td>
                </tr>
            </table>
             <br /><br />
             <div id="mycolock"></div>
             </center>
        </body>
        <script type="text/javascript">
            var pai=[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15];
            var flag=false;
            var oneid=-1;
            var index=0;
            function fanpai(id){
                if(pai[id]==-1){return;}
                    document.getElementById("img"+id).src="img/"+pai[id]+".jpg";
                    if(flag){//翻第2张
                        if(pai[id]==pai[oneid]){pai[id]=-1;pai[oneid]=-1;}
                        else{setTimeout("koupai("+id+","+oneid+")",100);}
                        oneid=-1;
                        flag=false;
                    }
                    else{//翻第1张
                        oneid=id;
                        flag=true;
                    }
                    checkSuccess();          
            }
        
            //每次载入页面进行重新洗牌
            function xipai(){
                var a,b,temp;
                for(var i=0;i<30;i++){
                    var a=Math.floor(Math.random()*30);
                    var b=Math.floor(Math.random()*30);
                    temp=pai[a];
                    pai[a]=pai[b];
                    pai[b]=temp;
                }
            }
            //第一次与第二次不相同,扣住两张牌
            function koupai(id,oneid){
                document.getElementById("img"+id).src="img/img0.jpg";
                document.getElementById("img"+oneid).src="img/img0.jpg";
            }
            //每次翻完两张相同的后,检验是否全部成功翻开
            function checkSuccess(){
                for(var i=0;i<30;i++){
                    if(pai[i]!=-1)
                        return;
                    }
                alert("Hello 恭喜,恭喜!!!你赢了!!!");
                location.reload();
            }
             xipai();
             
              function showTime(){
                var today=new Date();
                var year=today.getFullYear();//获得年
                var month=today.getMonth()+1;//获得月
                var day=today.getDate();//获得日
                var hh=today.getHours();//获得小时
                var mm=today.getMinutes();//获得分钟
                var ss=today.getSeconds();//获得秒    
                document.getElementById("mycolock").innerHTML=year+"年"+month+"月"+day+"日"+hh+":"+mm+":"+ss;
            }
                window.setInterval("showTime()",1000);//每隔1秒取一次当前的时间
                window.οnlοad=showTime;
        </script>    
    </html>

     

    展开全文
  • 双十一剁手节过去了,大家应该在很多网页中看到了数字翻牌的效果吧,比如倒计时、数字增长等。相信很多人都已经自己独立实现过了,我也在网上看了一些demo,发现HTML结构大多比较复杂,用了4个并列的标签来放置前后...

    e24fc5fcf205e2be32c742c6dd09a70e.png

    双十一剁手节过去了,大家应该在很多网页中看到了数字翻牌的效果吧,比如倒计时、

    数字增长等。相信很多人都已经自己独立实现过了,我也在网上看了一些demo,发现HTML结构大多比较复杂,用了4个并列的标签来放置前后两个“牌”。本文就来讲解下,如何进一步精简HTML,让结构简单,让JS方法封装得易使用。先来看看最终效果:

    d49f2533ada9ee4b9d0ba2c27743ba22.gif

    每个翻牌的HTML结构(精简至2个并列标签):

    复制代码

    本次分享含有很多小技巧,灵活使用能够提升技术水平和工作效率,具体包括以下知识点:

    知识点1::before :after伪元素的使用

    知识点2:line-height: 0的妙用

    知识点3:transform-origin和perspective

    知识点4:backface-visibility

    知识点5:时间格式化函数的实现

    Let's do it!

    1 翻牌的构建

    1.1 基本结构

    首先解释下HTML的结构:

    复制代码

    【说明】

    flip: 纸牌的外框

    down:表示向下翻牌动效,还有对于的up。后面章节会具体讲解。

    front: 表示位于前面的纸牌

    back: 表示位于后面的纸牌

    number*: 表示纸牌上的数字

    flip的CSS代码如下:

    .flip {

    display: inline-block;

    position: relative;

    width: 60px;

    height: 100px;

    line-height: 100px;

    border: solid 1px #000;

    border-radius: 10px;

    background: #fff;

    font-size: 66px;

    color: #fff;

    box-shadow: 0 0 6px rgba(0, 0, 0, .5);

    text-align: center;

    font-family: "Helvetica Neue"

    }

    复制代码

    这段代码很基础,就不再详细解释了。眼尖的同学可能发现了,为什么要设置background为#fff(白色)呢?最终效果明明是黑的。留个疑问,下一小节就会明白了。

    基本结构的效果是这样的:

    99b221e58f072b36ef1252e92dbdfe72.png

    1.2 构建纸牌并用伪元素拆分上下两部分

    由于每个纸牌是上下对折、翻转的,所以每个纸牌要拆分成上下两部分。可是HTML中每个纸牌只有一个标签,怎么拆分成两个呢?这里就用到了before和after伪元素。

    知识点1: 伪元素的使用

    先看代码:

    .flip .digital:before,

    .flip .digital:after {

    content: "";

    position: absolute;

    left: 0;

    right: 0;

    background: #000;

    overflow: hidden;

    }

    .flip .digital:before {

    top: 0;

    bottom: 50%;

    border-radius: 10px 10px 0 0;

    }

    .flip .digital:after {

    top: 50%;

    bottom: 0;

    border-radius: 0 0 10px 10px;

    }

    复制代码

    :before和:after在digital内部生成了两个伪元素,其中,before用来生成纸牌的“上半张”,after用来生成纸牌的“下半张”。

    因此,before“上半张”为从“顶部(top: 0)”到“距底一半(bottom: 50%)”的部分,顶部两侧为圆角。

    同理,after“下半张”为“距顶一半(top: 50%)”到“底部(bottom: 0)”的部分,底部两侧为圆角。

    注意代码中的content: ""不能省略,否则伪元素是不显示的。

    效果如下:

    dce7bf9a0afb52129b9ad91d009d64be.png

    回答上一章节的问题,为什么底层设置background为白色?

    答案很简单,元素内部的纸片边角和外层边角之间会有一点点的缝隙,这个缝隙会露出底部的白色,从视觉效果上看,更加具有立体感。

    然后,为上下部分中间添加一条水平折线。

    .flip .digital:before,

    .flip .digital:after {

    content: "";

    position: absolute;

    left: 0;

    right: 0;

    background: #000;

    overflow: hidden;

    + box-sizing: border-box;

    }

    ...(略)

    .flip .digital:before {

    top: 0;

    bottom: 50%;

    border-radius: 10px 10px 0 0;

    + border-bottom: solid 1px #666;

    }

    复制代码

    外层flip添加box-sizing: border-box保证了下边框不会影响元素的原有高度。

    效果如下:

    0f640008719c7a83ef1c5b8bb8022556.png

    到这里,我们可以认为是4个小纸片,分别是:

    前上:.digital.front:before

    前下:.digital.front:after

    后上:.digital.back:before

    后下:.digital.back:after

    由于重叠在一起,只能看到一张纸牌。而看到的这个纸牌是后面(back)的纸牌,为什么呢?因为back的HTML写在了front的后面。不过没关系,后面我们会通过z-index来重新调整层叠顺序,先不着急。

    1.3 为纸牌添加文字

    还记的刚才的content: ""吗?纸牌的文字显示就用到了这个。

    先通过CSS定义好0~9的数字:

    .flip .number0:before,

    .flip .number0:after {

    content: "0";

    }

    .flip .number1:before,

    .flip .number1:after {

    content: "1";

    }

    .flip .number2:before,

    .flip .number2:after {

    content: "2";

    }

    ...(略)

    .flip .number9:before,

    .flip .number9:after {

    content: "9";

    }

    复制代码

    现在效果如下:

    b8ef5c2ea15ad0f07e571983fbd46b23.png

    可以很明显的看到两个问题:

    本应该在后面的back纸牌跑到了前面(z-index问题)

    下半张纸牌的文字应该只显示下半部分。

    先来解决问题2,这里就涉及到了第二个知识点。

    知识点2:line-height: 0的妙用

    提到文字的显示,肯定会想到基线(baseline),可能你也曾经看过这个图:

    16277f6bd94451c0102f83eaded1607c.png

    关于基线(baseline)的计算,确实很麻烦,我也在这里绕了很久。其实理解line-height:0可以换个角度,会更容易理解,请看下图:

    14cac9cc13d7b63d45a43d3f0ce0eda7.png

    当line-height为200px,每行文字高度为200px,文字在200px高度的行间区域垂直居中;

    当line-height为100px,每行文字高度为100px,文字在100px高度的行间区域垂直居中;

    当line-height为0时,行间距为0,中线的位置也为0,所以文字只有下半部分留在容器内。

    利用line-height:0的特性,就可以很轻易实现“下半张”纸牌只显示文字的下半部分,并且与“上半张”纸牌很好的衔接在一起。

    在代码中设置line-height为0:

    .flip .digital:after {

    top: 50%;

    bottom: 0;

    border-radius: 0 0 10px 10px;

    + line-height: 0;

    }

    复制代码

    效果如下:

    9e00e8a6b7f41d5551c24b3ebd33f1d3.png

    1.4 设置纸牌的层叠关系

    首先,先看下“向下翻牌”的视频演示,直观感受下每个纸片的层级关系:

    e9c0ddd605df401b8fa59351bbf44563.gif

    按照实物图就可以确定每张纸片的z-index:

    461946d30aeb3321583ca336941d4e15.png

    添加以下CSS代码:

    /*向下翻*/

    .flip.down .front:before {

    z-index: 3;

    }

    .flip.down .back:after {

    z-index: 2;

    }

    .flip.down .front:after,

    .flip.down .back:before {

    z-index: 1;

    }

    复制代码

    现在效果如下:

    103732ae2fe96554087e4a8cbb15b805.png

    咦?怎么不对?别着急,这是因为我们只设置了层级,但是没有把后面纸牌的下半部翻转上去。

    添加翻转代码:

    .flip.down .back:after {

    z-index: 2;

    + transform-origin: 50% 0%;

    + transform: perspective(160px) rotateX(180deg);

    }

    复制代码

    这里涉及到了知识点3。

    知识点3:transform-origin和perspective

    transform-origin是元素旋转的基本点。

    transform-origin: 50% 0%;表示将旋转基本点设置在横轴的中点,纵轴的顶点位置,如下图所示:

    f1e48969aeffdfefe94755e40d912169.png

    perspective(160px)可以理解为立体透视图的景深。在本次分享的效果中,我们的视角是正对牌面,并且纸牌位于视角中间。所以 transform-origin的第一个值(X轴位置)为50%。

    rotateX(180deg)表示以X轴进行翻转,对应这里就是上下翻转。这里已经通过transform-origin的第二个参数(Y轴位置:0%)将X轴放在了元素顶部。

    基于以上设置,已经可以正常显示了,如下图:

    b3dc156364edbb88415ee8e244d94392.png

    同理,“向上翻”也需要进行设置下。大家可以自己折两个纸片,参照上面的方法,应该很容易实现。这里不再重复讲解,直接放上代码,大家可以对比下哪里不同:

    /*向上翻*/

    .flip.up .front:after {

    z-index: 3;

    }

    .flip.up .back:before {

    z-index: 2;

    transform-origin: 50% 100%;

    transform: perspective(160px) rotateX(-180deg);

    }

    .flip.up .front:before,

    .flip.up .back:after {

    z-index: 1;

    }

    复制代码

    2 翻牌动画的实现

    现在纸片都已摆好了,剩下的就是实现CSS3动画,以及JS交互控制。

    2.1 CSS3翻牌动画

    我们还是以“向下翻”为例,再来看下之前的实物翻牌视频:

    e9c0ddd605df401b8fa59351bbf44563.gif

    可以看到,“向下翻”主要涉及两个元素的动画:

    前面纸牌的上半部向下翻转180度。

    后面纸牌的下半部(目前已翻转上去)向下翻转180度恢复原状态。

    b2c3e5d133fc9afb79be06f6e7f12f01.png

    直接上代码:

    .flip.down.go .front:before {

    transform-origin: 50% 100%;

    animation: frontFlipDown 0.6s ease-in-out both;

    box-shadow: 0 -2px 6px rgba(255, 255, 255, 0.3);

    }

    .flip.down.go .back:after {

    animation: backFlipDown 0.6s ease-in-out both;

    }

    @keyframes frontFlipDown {

    0% {

    transform: perspective(160px) rotateX(0deg);

    }

    100% {

    transform: perspective(160px) rotateX(-180deg);

    }

    }

    @keyframes backFlipDown {

    0% {

    transform: perspective(160px) rotateX(180deg);

    }

    100% {

    transform: perspective(160px) rotateX(0deg);

    }

    }

    复制代码

    以上代码涉及的知识点和原理没有新的东西,都已经讲解过了,就不详述了。box-shadow是为了给纸片的上边缘加一点白光,视觉效果更好一点。否则在翻转的时候,跟后面元素都是黑色,融在一起了。看看现在的效果:

    10ec628a9cc1fd97418054754ab4da83.gif

    显示不正常!为什么?因为前排上半部纸片的z-index最高,所以它在翻转到下半部的时候仍然遮挡住了其他纸片。怎么优雅的解决?超级简单,来看看第四个知识点:

    知识点4:backface-visibility

    backface-visibility表示元素的背面是否可见,默认为visible(可见)。

    这里的需求是,当前面上半部纸片翻转到一半的时候(90度)进入不可见状态。而纸牌翻转90度以后,正好是显露元素背面的开始,所以将backface-visibility设置为hidden即可完美解决!

    修改代码如下:

    .flip.down.go .front:before {

    transform-origin: 50% 100%;

    animation: frontFlipDown 0.6s ease-in-out both;

    box-shadow: 0 -2px 6px rgba(255, 255, 255, 0.3);

    + backface-visibility: hidden;

    }

    复制代码

    现在效果很完美!

    f0f0be1449321722bc050abb66beb527.gif

    大家可以试着自己实现向上翻转效果,代码直接放出:

    .flip.up.go .front:after {

    transform-origin: 50% 0;

    animation: frontFlipUp 0.6s ease-in-out both;

    box-shadow: 0 2px 6px rgba(255, 255, 255, 0.3);

    backface-visibility: hidden;

    }

    .flip.up.go .back:before {

    animation: backFlipUp 0.6s ease-in-out both;

    }

    @keyframes frontFlipUp {

    0% {

    transform: perspective(160px) rotateX(0deg);

    }

    100% {

    transform: perspective(160px) rotateX(180deg);

    }

    }

    @keyframes backFlipUp {

    0% {

    transform: perspective(160px) rotateX(-180deg);

    }

    100% {

    transform: perspective(160px) rotateX(0deg);

    }

    }

    复制代码

    2.2 JS实现翻牌交互

    现在我们来实现一个简单的交互。需求是:

    点击“+”,向下翻牌,数字+1

    点击“-”,向上翻牌,数字-1

    首先,修改下HTML:

    +

    M

    +

    +

    + 向下翻+1

    + 向上翻-1

    +

    复制代码

    配套的CSS如下,仅为了demo好看,无实际作用:

    .single-demo {

    margin: 50px auto;

    padding: 30px;

    width: 600px;

    text-align: center;

    border: solid 1px #999;

    }

    复制代码

    Javascript代码如下:

    var flip = document.getElementById('flip')

    var backNode = document.querySelector('.back')

    var frontNode = document.querySelector('.front')

    var btn1 = document.getElementById('btn1')

    var btn2 = document.getElementById('btn2')

    btn1.addEventListener('click', function() {

    flipDown();

    })

    btn2.addEventListener('click', function() {

    flipUp();

    })

    // 当前数字

    var count = 0

    // 是否正在翻转(防止翻转未结束就进行下一次翻转)

    var isFlipping = false

    // 向下翻转+1

    function flipDown() {

    // 如果处于翻转中,则不执行

    if (isFlipping) {

    return false

    }

    // 设置前牌的文字

    frontNode.setAttribute('class', 'digital front number' + count)

    // 计算后牌文字(越界判断)

    var nextCount = count >= 9 ? 0 : (count + 1)

    // 设置后牌的文字

    backNode.setAttribute('class', 'digital back number' + nextCount)

    // 添加go,执行翻转动画

    flip.setAttribute('class', 'flip down go')

    // 将翻转态设置为true

    isFlipping = true

    // 翻转结束后,恢复状态

    setTimeout(function() {

    // 去掉go

    flip.setAttribute('class', 'flip down')

    // 将翻转态设置为false

    isFlipping = false

    // 设置前牌文字为+1后的数字

    frontNode.setAttribute('class', 'digital front number' + nextCount)

    // 更新当前文字

    count = nextCount

    }, 1000)

    }

    // 向上翻转-1(同理,注释略)

    function flipUp() {

    if (isFlipping) {

    return false

    }

    frontNode.setAttribute('class', 'digital front number' + count)

    var nextCount = count <= 0 ? 9 : (count - 1)

    backNode.setAttribute('class', 'digital back number' + nextCount)

    flip.setAttribute('class', 'flip up go')

    isFlipping = true

    setTimeout(function() {

    flip.setAttribute('class', 'flip up')

    isFlipping = false

    frontNode.setAttribute('class', 'digital front number' + nextCount)

    count = nextCount

    }, 1000)

    }

    复制代码

    先看下交互效果:

    3bba84fecb275d534d8a99cdb8b3b479.gif

    这段Javascript代码很冗余,重复代码很多。在实际产品中,都是多个数字牌,这种方式显然无法应对。下一章节,我们来说下如何优雅的封装,以不变应万变。

    3 翻牌时钟的实现

    先看下最终效果:

    d49f2533ada9ee4b9d0ba2c27743ba22.gif

    3.1 HTML构建

    HTML代码如下:

    :

    :

    复制代码

    CSS代码如下(之前章节的CSS代码请保留):

    .clock {

    text-align: center;

    }

    .clock em {

    display: inline-block;

    line-height: 102px;

    font-size: 66px;

    font-style: normal;

    vertical-align: top;

    }

    复制代码

    效果如下,剩下的就是JS部分了。

    aadaecbe69756a69940d692490692be2.png

    3.2 构建Flipper类

    将每个翻牌封装成类,这样在应对多个翻牌的时候,可以方便的通过new Flipper()去独立控制每个翻牌对象。

    类的实现代码如下:

    function Flipper(config) {

    // 默认配置

    this.config = {

    // 时钟模块的节点

    node: null,

    // 初始前牌文字

    frontText: 'number0',

    // 初始后牌文字

    backText: 'number1',

    // 翻转动画时间(毫秒,与翻转动画CSS 设置的animation-duration时间要一致)

    duration: 600,

    }

    // 节点的原本class,与html对应,方便后面添加/删除新的class

    this.nodeClass = {

    flip: 'flip',

    front: 'digital front',

    back: 'digital back'

    }

    // 覆盖默认配置

    Object.assign(this.config, config)

    // 定位前后两个牌的DOM节点

    this.frontNode = this.config.node.querySelector('.front')

    this.backNode = this.config.node.querySelector('.back')

    // 是否处于翻牌动画过程中(防止动画未完成就进入下一次翻牌)

    this.isFlipping = false

    // 初始化

    this._init()

    }

    Flipper.prototype = {

    constructor: Flipper,

    // 初始化

    _init: function() {

    // 设置初始牌面字符

    this._setFront(this.config.frontText)

    this._setBack(this.config.backText)

    },

    // 设置前牌文字

    _setFront: function(className) {

    this.frontNode.setAttribute('class', this.nodeClass.front + ' ' + className)

    },

    // 设置后牌文字

    _setBack: function(className) {

    this.backNode.setAttribute('class', this.nodeClass.back + ' ' + className)

    },

    _flip: function(type, front, back) {

    // 如果处于翻转中,则不执行

    if (this.isFlipping) {

    return false

    }

    // 设置翻转状态为true

    this.isFlipping = true

    // 设置前牌文字

    this._setFront(front)

    // 设置后牌文字

    this._setBack(back)

    // 根据传递过来的type设置翻转方向

    let flipClass = this.nodeClass.flip;

    if (type === 'down') {

    flipClass += ' down'

    } else {

    flipClass += ' up'

    }

    // 添加翻转方向和执行动画的class,执行翻转动画

    this.config.node.setAttribute('class', flipClass + ' go')

    // 根据设置的动画时间,在动画结束后,还原class并更新前牌文字

    setTimeout(() => {

    // 还原class

    this.config.node.setAttribute('class', flipClass)

    // 设置翻转状态为false

    this.isFlipping = false

    // 将前牌文字设置为当前新的数字,后牌因为被前牌挡住了,就不用设置了。

    this._setFront(back)

    }, this.config.duration)

    },

    // 下翻牌

    flipDown: function(front, back) {

    this._flip('down', front, back)

    },

    // 上翻牌

    flipUp: function(front, back) {

    this._flip('up', front, back)

    }

    }

    复制代码

    可以注意到,Flipper的传参只接受一个对象形式的参数config,使用对象的方式向函数传参有很多优点:

    参数语义化,方便理解

    不用在意参数顺序

    传参的增删和顺序调整不会影响业务代码的使用

    使用Object.assign方法,可将传递进来的config参数覆盖默认参数。传递的config中没有的属性,则使用默认配置。当然,这种方式只适用于浅拷贝。

    关于prototype,以及为什么要设置constructor,请阅读我的另一篇文章《一张刮刮卡竟包含这么多前端知识点》第4.1章节,已经讲解得很详细了。

    代码逻辑请阅读注释。

    3.3 实现时钟业务逻辑

    接下来的工作就是将js与dom进行绑定。

    请看代码:

    这段代码一定要放在Flipper类代码的下面,Flipper.prototype一定要在业务逻辑代码之前执行,否则会报错找不到Flipper内部方法。

    // 定位时钟模块

    let clock = document.getElementById('clock')

    // 定位6个翻板

    let flips = clock.querySelectorAll('.flip')

    // 获取当前时间

    let now = new Date()

    // 格式化当前时间,例如现在是20:30:10,则输出"203010"字符串

    let nowTimeStr = formatDate(now, 'hhiiss')

    // 格式化下一秒的时间

    let nextTimeStr = formatDate(new Date(now.getTime() + 1000), 'hhiiss')

    // 定义牌板数组,用来存储6个Flipper翻板对象

    let flipObjs = []

    for (let i = 0; i < flips.length; i++) {

    // 创建6个Flipper实例,初始化并存入flipObjs

    flipObjs.push(new Flipper({

    // 每个Flipper实例按数组顺序与翻板DOM的顺序一一对应

    node: flips[i],

    // 按数组顺序取时间字符串对应位置的数字

    frontText: 'number' + nowTimeStr[i],

    backText: 'number' + nextTimeStr[i]

    }))

    }

    复制代码

    代码逻辑不难,请阅读注释。比较值得分享的是其中的时间格式化函数formatDate。

    知识点5:时间格式化函数的实现

    为了方便业务使用,实现一个时间格式化方法,这个方法在很多其他业务中都会使用到,具有很普遍的实用价值。

    需求是通过输入日期时间格式要求,输出对应的字符串。

    例如:

    yyyy-mm-dd hh:ii:ss 输出:2019-06-02 08:30:37

    yy-m-d h:i:s 输出:19-6-2 8:30:37

    先看代码:

    //正则格式化日期

    function formatDate(date, dateFormat) {

    /* 单独格式化年份,根据y的字符数量输出年份

    * 例如:yyyy => 2019

    yy => 19

    y => 9

    */

    if (/(y+)/.test(dateFormat)) {

    dateFormat = dateFormat.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));

    }

    // 格式化月、日、时、分、秒

    let o = {

    'm+': date.getMonth() + 1,

    'd+': date.getDate(),

    'h+': date.getHours(),

    'i+': date.getMinutes(),

    's+': date.getSeconds()

    };

    for (let k in o) {

    if (new RegExp(`(${k})`).test(dateFormat)) {

    // 取出对应的值

    let str = o[k] + '';

    /* 根据设置的格式,输出对应的字符

    * 例如: 早上8时,hh => 08,h => 8

    * 但是,当数字>=10时,无论格式为一位还是多位,不做截取,这是与年份格式化不一致的地方

    * 例如: 下午15时,hh => 15, h => 15

    */

    dateFormat = dateFormat.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));

    }

    }

    return dateFormat;

    };

    //日期时间补零

    function padLeftZero(str) {

    return ('00' + str).substr(str.length);

    }

    复制代码

    代码逻辑请阅读注释,这里再补充下“日期时间补零padLeftZero”函数的说明。由于月、日、时、分、秒最多为2位数,所以这里只考虑最多补一个0的情况。

    原理是:不管数字是几位,先在前面补两个0,再根据原数字的位数进行截取,最终输出固定为两位的补零数字

    例如:数字"16"是两位数,先补两个0变成"0016",再从该字符串的索引[2]开始截取(2=原数字的位数),由于字符串索引从[0]开始,所以[2]对应字符串的第3位,输出结果仍为"16。

    同理,数字"8"是1位数,先补两个0变成"008",再从该字符串的索引[1]开始截取(1=原数字的位数),即从第2位开始截取,输出"08"。

    这样就实现了补零的功能。

    现在看下效果,已经可以正确显示当前时间了。

    072e695482d7b8219241638d1efc4e99.png

    3.4 运行时钟

    万事俱备,只差加个定时器让时钟翻动起来。

    setInterval(function() {

    // 获取当前时间

    let now = new Date()

    // 格式化当前时间

    let nowTimeStr = formatDate(new Date(now.getTime() - 1000), 'hhiiss')

    // 格式化下一秒时间

    let nextTimeStr = formatDate(now, 'hhiiss')

    // 将当前时间和下一秒时间逐位对比

    for (let i = 0; i < flipObjs.length; i++) {

    // 如果前后数字没有变化,则直接跳过,不翻牌

    if (nowTimeStr[i] === nextTimeStr[i]) {

    continue

    }

    // 传递前后牌的数字,进行向下翻牌动画

    flipObjs[i].flipDown('number' + nowTimeStr[i], 'number' + nextTimeStr[i])

    }

    }, 1000)

    复制代码

    这段代码逻辑很简单了,主要就是进行前后时间字符串的对比,然后设置纸牌并翻转。最终效果:

    d49f2533ada9ee4b9d0ba2c27743ba22.gif

    4 Vue & React封装

    由于篇幅有限,这里不再详述,原理都是一样的,只是利用Vue和React的API和语法进行封装。

    原生JavaScript、Vue、React三个版本的演示源码请到我的github下载:

    本次分享讲解了如何优雅地实现结构简单的翻牌时钟,并对JS进行了科学高效的封装。其中也涉及到了CSS3的一些知识点和技巧。希望能对大家的工作有所帮助。

    欢迎关注我的个人微信公众号,随时获取最新文章^_^

    展开全文
  • 好久没有写博客了,上篇博文距现在都有七个多了,实在是惭愧。但是这段时间仍然是在忙于项目或是自我充电。这几天实现了个基于GridView的翻牌动画效果,这里就将其整理出来同各位分享。  、整体介绍  ...

      好久没有写博客了,上一篇博文距现在都有七个多月了,实在是惭愧。但是这段时间仍然是在忙于项目或是自我充电。这几天实现了一个基于GridView的翻牌动画效果,这里就将其整理出来同各位分享。

      一、整体介绍 

      GridView设置15个Item(5*3),刚好满屏显示(没有ScrollBar),没有点击某个Item前可以使用摇一摇功能对GridView中的图片进行切换,点击某个Item时对应的图片放大,然后实现“翻牌”效果,并将该Item中显示的图片切换为对应的文字。随后所有其他的Item也自动实现翻牌效果。

      (1)目录结构

      

      (2)效果图

        

      二、详细介绍

      按上面的目录结构从上致下

      1、GridAdapter 继承至 BaseAdapter

        重点代码:

        (1)自定义的一个Item touch事件监听接口

    1  public interface  OnItemTouchedListener {
    2         public boolean onItemTouch (View v, MotionEvent event, int position);
    3  }

        (2)设置OnItemTouchedListener

    1  public void setOnItemTouchedListener(OnItemTouchedListener onItemTouchedListener) {
    2         this.listener = onItemTouchedListener;
    3  }

        (3)getView()函数中动态设置 Item的高、宽加载网络图片为每个Item设置OnTouchListener

    复制代码
     1 @Override
     2     public View getView(final int position, View convertView, ViewGroup parent) {
     3         LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     4         convertView = inflater.inflate(R.layout.grid_item, parent, false);
     5 
     6         LayoutParams layoutParams = convertView.getLayoutParams();
     7         layoutParams.width = viewWidth; 8 layoutParams.height = viewHeight; 9  convertView.setLayoutParams(layoutParams); 10 ImageView imageView = (ImageView) convertView.findViewById(R.id.grid_image); 11 12 DisplayImageOptions options = new DisplayImageOptions.Builder()// 13 .cacheInMemory(true)// 14 .cacheOnDisc(true)// 15 .bitmapConfig(Config.RGB_565)// 16  .build(); 17  ImageLoader.getInstance().displayImage(urlArray.get(position), 18  imageView, options); 19 convertView.setOnTouchListener(new OnTouchListener() { 20 21  @Override 22 public boolean onTouch(View v, MotionEvent event) { 23 24 return listener.onItemTouch(v, event, position); 25  } 26  }); 27 28 return convertView; 29 }
    复制代码

       2、RotateAnimation

      参考于github上jianghejie的3DNumberRotate项目中的NumberRotate3DAnimation类,基于Camera实现数字3D翻转动画。

      3、自定义的Application类

      项目中使用了universal-image-loader加载网络图片,在这里对ImageLoader进行初始化:

    复制代码
     1 private void initImageLoader() {
     2 
     3         DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() //
     4                 .showImageForEmptyUri(R.mipmap.empty_img) //
     5                 .showImageOnFail(R.mipmap.empty_img) //
     6                 .cacheInMemory(true) //
     7                 .cacheOnDisc(true) //
     8                 .build();//
     9 
    10         File cacheDir = StorageUtils.getCacheDirectory(getApplicationContext());
    11         ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
    12                 getApplicationContext())//
    13                 .memoryCache(new LruMemoryCache(5 * 1024 * 1024))//
    14                 .memoryCacheSize(10 * 1024 * 1024)//
    15                 .defaultDisplayImageOptions(defaultOptions)//
    16                 .discCache(new UnlimitedDiscCache(cacheDir))//
    17                 .discCacheFileNameGenerator(new HashCodeFileNameGenerator())//
    18                 .build();
    19         ImageLoader.getInstance().init(config);
    20     }
    复制代码

      4、util包中的几个工具类

        (1)Constants:放一些常量,这里我存放的是GridView中网络图片的路径;

        (2)DisplayUtil:这是关于显示的一个工具类,包括获取屏幕高宽、dp转px等功能;

        (3)ItemCenterMeasure:这个类是设计用来根据GridView高宽计算Item尺寸的,其实可以省去,或者直接归并到DisplayUtil中;

      5、MainActivity中功能较多写的比较杂乱

        主要代码:

        (1)Adapter设置自定义的OnItemTouchedListener

    复制代码
     1  mAdapter.setOnItemTouchedListener(new GridAdapter.OnItemTouchedListener() {
     2 
     3             @Override
     4             public boolean onItemTouch(View v, MotionEvent event, int position) {
     5                 mView = v;
     6                 currentPos = position;
     7                 if(event.getAction() == MotionEvent.ACTION_DOWN){
     8                     if (isClicked) {
     9                         Toast toast = Toast.makeText(context, getString(R.string.warning),
    10                                 Toast.LENGTH_SHORT);
    11                         toast.setGravity(Gravity.CENTER, 0, 0);
    12                         toast.show();
    13                         return false;
    14                     } else{
    15                         //play sound
    16                         soundPool.play(music, 1, 1, 0, 0, 1);
    17                         //trigger zoom animation on items
    18                         ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.1f, 1.0f, 1.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    19                         scaleAnimation.setDuration(500);
    20                         AnimationSet animationSet = new AnimationSet(true);
    21                         animationSet.addAnimation(scaleAnimation);
    22                         animationSet.setFillAfter(true);
    23                         animationSet.setAnimationListener(new Animation.AnimationListener() {
    24 
    25                             @Override
    26                             public void onAnimationStart(Animation animation) {
    27 
    28                             }
    29 
    30                             @Override
    31                             public void onAnimationRepeat(Animation animation) {
    32 
    33                             }
    34 
    35                             @Override
    36                             public void onAnimationEnd(Animation animation) {
    37                                 enableRefreshFirst = true;
    38                                 RotateAnimation rotateAnim = null;
    39 
    40                                 float cX = mView.getWidth() / 2.0f;
    41                                 float cY = mView.getHeight() / 2.0f;
    42                                 rotateAnim = new RotateAnimation(cX, cY);
    43 
    44                                 if (rotateAnim != null) {
    45                                     rotateAnim.setInterpolatedTimeListener(MainActivity.this, mView);
    46                                     rotateAnim.setFillAfter(true);
    47                                     rotateAnim.setAnimationListener(new Animation.AnimationListener() {
    48 
    49                                         @Override
    50                                         public void onAnimationStart(Animation animation) {
    51 
    52                                         }
    53 
    54                                         @Override
    55                                         public void onAnimationRepeat(Animation animation) {
    56 
    57                                         }
    58 
    59                                         @Override
    60                                         public void onAnimationEnd(Animation animation) {
    61                                             handler.postDelayed(new Runnable() {
    62 
    63                                                 @Override
    64                                                 public void run() {
    65                                                     otherItemRotate();
    66                                                 }
    67                                             }, 500);
    68                                         }
    69                                     });
    70                                     mView.startAnimation(rotateAnim);
    71 
    72                                 }
    73 
    74                                 isClicked = true;
    75                             }
    76                         });
    77                         v.startAnimation(animationSet);
    78                     }
    79                 }
    80 
    81                 return false;
    82             }
    83         });
    复制代码

        (2)动态创建一个TextView,并算出GridView的高、宽

          其中计算GridView的高度这一句(DisplayUtil.SCREEN_HEIGHT_PIXELS - DisplayUtil.dp2px(16) * 2 - tvBmHeight - 80)在我设备(分辨率:1920*1080)上要减去80px才能使所有的Item整好全部显示出来,不知道为什么,如果不减去80px,GridViw 中的最后一行Item将会显示不完全也就是说要通过滑动ScrollBar才能看全。这一点还望大神能给予指点。

    复制代码
     1 private void createCRTextView() {
     2         LinearLayout ll = (LinearLayout) findViewById(R.id.logo_ly);
     3         tvBm = new TextView(context);
     4         tvBm.setText(getResources().getString(R.string.logo));
     5         tvBm.setTextAppearance(context, R.style.logoTextView);
     6         LinearLayout.LayoutParams crParams = new LinearLayout.LayoutParams(GridLayout.LayoutParams.WRAP_CONTENT, GridLayout.LayoutParams.WRAP_CONTENT);
     7         crParams.topMargin = 5;
     8         crParams.bottomMargin = 10;
     9         crParams.gravity = Gravity.CENTER;
    10         tvBm.setLayoutParams(crParams);
    11 
    12         tvBm.setOnClickListener(new View.OnClickListener() {
    13 
    14             @Override
    15             public void onClick(View v) {
    16                 ScaleAnimation  scaleAnim = new ScaleAnimation(1.0f, 1.2f, 1.0f, 1.2f,
    17                         Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    18                 scaleAnim.setDuration(500);
    19                 scaleAnim.setFillAfter(false);
    20                 tvBm.startAnimation(scaleAnim);
    21             }
    22         });
    23 
    24         ll.addView(tvBm);
    25         int tvBmHeight = crParams.height + 5 + 10;
    26 
    27 
    28         gridWidthPix = DisplayUtil.SCREEN_WIDTH_PIXELS - DisplayUtil.dp2px(16) * 2;
    29         //I am not sure why the right of next equality should minus 80px to display all items in the gridview without scrollbar in my devices (1       920*1080),
    30         //this may make a bad adaption for various devices with different resolution ratio
    31         gridHeightPix = DisplayUtil.SCREEN_HEIGHT_PIXELS - DisplayUtil.dp2px(16) * 2 - tvBmHeight - 80;
    32 
    33 
    34     }
    复制代码

        (3)摇一摇触发的时候更新GridView中的图片路径

    复制代码
     @Override
        public void onSensorChanged(SensorEvent event) {
            int sensorType = event.sensor.getType();
            float[] values = event.values;
            if (sensorType == Sensor.TYPE_ACCELEROMETER) {
                //values[0] X axis acceleration;values[1] Y axis acceleration;values[2] Z axis acceleration
                if (Math.abs(values[0]) > 17 || Math.abs(values[1]) > 17 || Math.abs(values[2]) > 17) {
    
                    if (!isClicked) {
                        vibrator.vibrate(500);
                        mAdapter.setUrls(Constants.getUrls(2));
                        mGridView.invalidate();
                    }
                }
            }
    
    
        }
    复制代码

      6、还有一个自定义的GridView,实现禁止滑动

      重写dispatchTouchEvent方法

    复制代码
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_MOVE) {
                return true;//禁止gridview滑动
            }
            return super.dispatchTouchEvent(ev);
        }
    复制代码

      7、布局文件这里就不给予说明了,很简单明了的,需要参考的可以直接下源码看。

        源码下载链接:

        (1)CSDN:需要1个下载积分,积分有点缺您要是愿意打赏请点这里下载

        (2)GitHub:实在吝啬或是没有积分也没关系,请到这里下载,当然也希望你Start一下,或是Fork;

      好了到此算是写完了,如果对您有用,劳烦您点个赞或是分享一下;如果您对代码有一些建议,期待您在评论处给予指正。

      最近状态有点不佳,送给自己以及各位一句话共勉:

    业精于勤 荒于嬉;行成于思 毁于随

     

    展开全文
  • css3的3D翻牌效果

    2015-11-05 19:22:00
    利用hover控制动画,个从翻面向正面翻,个从正面向反面翻。 利用:backface-visibility: hidden;控制反面的元素不显示。 不支持的浏览器直接切换层级换图。 <!DOCTYPE html> <html> <...
  • 、唯品会OLAP的演进 1、OLAP在唯品会的演进 1)Presto Presto作为当前唯品会OLAP的主力军,经历了数次架构和使用方式的进化。目前,具有500多台高配的物理机,CPU和内存都非常强悍,服务于20多个线上的业务。日均...
  • cocos2d-x 卡牌翻牌效果的实现

    千次阅读 2014-07-29 09:43:30
    cocos2d-x 卡牌翻牌效果的实现 2012年0725日 ⁄ 综合 ⁄ 共 3085字 ⁄ 字号 小 中 大 ⁄ 评论关闭 猴子原创,欢迎转载。转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,...
  • 北京2021年720日 /美通社/ -- 如今随着城市化水平的提高以及人们消费水平的变化,国内一些老牌高档酒店相继“翻牌”换新。万达酒店及度假村借此机会全力出击,意在打造个酒店翻牌经典...
  • 1美国数据公司被黑客入侵。10月1日,美国移动电话服务公司T-Mobile发出通告:为T-Mobile提供服务的益百利公司遭到黑客入侵,导致1500万用户个人信息泄露。2大众点评与美团网...
  • java翻牌源码用于姿态估计 是个跨平台框架,用于构建多模式应用机器学习管道,包括推理模型和媒体处理功能。 这个回购的主要目的是: 自定义 MediaPipe 解决方案的输出 自定义 2D 和 3D 输出的可视化 在 Python 上...
  • 最近做了个特效,css是从网上找的,地址是这个:把其中核心的css代码扒出来如下:/* The properties in this rule are only necessary for the 'flip' transition.* We need specify the perspective to create a ...
  • 二本,终于拿到腾讯阿里offer了,翻牌

    千次阅读 多人点赞 2021-07-28 14:05:21
    这是帅地让位读者写的份学习经历,这位读者,算是和帅地关系还不错的读者吧,他大一的时候就加了我微信了,当时还是经常骚扰我的,问这问那,甚至让我直接给他的算法题找 bug。。。。。但是,我看他挺真诚,并且...
  • 家长专栏|脑瘫儿童上肢功能评定的常用方法 家长专栏|原始反射对婴幼儿发育姿势的影响 @你,你有个儿童言语治疗微信群邀请 线下培训专栏|2019年首届儿童言语沟通障碍评估干预工作坊(五北京站)运动类 ...
  • 双十一剁手节过去了,大家应该在很多网页中看到了数字翻牌的效果吧,比如倒计时、数字增长等。相信很多人都已经自己独立实现过了,我也在网上看了一些demo,发现HTML结构大多...
  • 大家应该在很多网页中看到了数字翻牌的效果吧,比如倒计时、数字增长等。相信很多人都已经自己独立实现过了,我也在网上看了一些demo,发现HTML结构大多比较复杂,用了4个并列的标签来放置前...
  • 据悉,该片将于328日2D、3D同步上映。  黄圣依谈戏哽咽落泪  《我在路上最爱你》讲述段发生在旅行中的浪漫爱情故事。黄圣依扮演个到大城市闯荡的女孩,迫于生计到酒吧做“外围女”,
  • 双十一剁手节过去了,大家应该在很多网页中看到了数字翻牌的效果吧,比如倒计时、 数字增长等。相信很多人都已经自己独立实现过了,我也在网上看了一些demo,发现HTML结构大多比较复杂,用了4个并列的标签来放置前后...
  • “懒人抽奖平台” 官网:http://flop.lanrenmb.com/是武汉懒人云科技有限公司针对移动互联网营销推出的款互动营销型产品。“抽奖”是最合适商家产品口碑式的...、丰富型抽奖活动   为什么称为丰富型抽奖活动?...
  • 雷锋网323日报道,2001年227日,在海南省琼海市东岸的个默默无闻的小镇上,聚集了来自25个亚洲国家和澳大利亚的政要。博鳌亚洲论坛成立大会在这里举行。今日(2017年323日),第16届博鳌亚洲论坛2017年年会...
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼亲爱的勇者,新资料片《格斗之魂》即将到来。...福利放送【欢乐礼包,开心领取】1)1月8日更新后到1月10日24点,30级以上的勇者可以在法兰城阿萌处领取份更新礼包。...
  • 相信大家都已经早早地将王者荣耀更新了,但是呢更新之后有什么活动和福利。估计小伙伴们都不太清楚,别急!...累计桃花酥积分达到10分就可以翻牌一次,每次翻开的牌能成功凑成一对CP的话就可以获得100点的...
  • 最佳替换子串 暴力枚举 首个贪心 乘加构造 permutation 暴力模拟 学习最多知识点 lis ^型最长子序列 狗子翻牌期望 概率 大数乘 无限远皇后棋盘博弈 打表 黄金分割 最小异或和生成树 打表 根据公式递推
  • 分享Silverlight/WPF/Windows Phone周学习导读(95日-917日) 本周Silverlight学习资源更新: OOB模式下Exit事件的处理 Ringgo.Yao Silverlight3.0正式版(Silverli
  • WPF程序设计指南中的个计算你至今活了多少年多少多少天的例子 mervyn807 MVVM实践教程 快乐之王 WPF Summary:WPF的结构 海蓓娜楽 WPF Summary:WPF的框架 海蓓娜楽 WPF Summary:XAML语法 海...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 561
精华内容 224
关键字:

一月翻牌