网站首页 » 前端开发 » JavaScript » JavaScript 做一个照片墙效果(二)
上一篇:
下一篇:

JavaScript 做一个照片墙效果(二)

前言

之前也写过一个照片墙效果,只不过,那个相对来说比较普通,只有拖拽图片才会有动画效果,而现在这个效果会更炫一些,至于效果如果,看到示例你自有定夺.这个效果是在网上看到的,感觉还不错,所以就自己就撸了一个出来。

在线示例:http://yunkus.com/demo/javascript-photo-wall/javascript-photo-wall-2/

样式
#imgBox{
    width: 800px;
    height: 400px;
    margin: 80px auto;
    perspective: 800px;
    display: flex;
    flex-wrap: wrap
}
#imgBox img{
    width:80px;
    height: 80px;
}
#btn{
    width: 100px;
    background: #373d41;
    padding: 0 20px;
    font: 16px/40px "微软雅黑";
    color: #fff;
    margin: 0 auto;
    border-radius: 5px;
    box-shadow: 2px 2px 5px #ccc;
    cursor: pointer;
}
HTML
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>照片墙效果(二)-云库网</title>
    </head>
    <body>
        <div id="imgBox">
            <img src="http://yunkus.com/demo/lib/images/demo-1.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-2.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-3.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-4.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-5.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-6.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-7.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-8.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-9.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-1.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-2.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-3.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-4.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-5.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-6.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-7.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-8.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-9.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-1.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-2.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-3.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-4.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-5.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-6.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-7.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-8.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-9.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-1.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-2.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-3.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-4.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-5.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-6.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-7.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-8.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-9.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-1.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-2.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-3.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-4.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-5.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-6.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-7.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-8.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-9.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-1.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-2.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-3.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-4.jpg" alt="" />
            <img src="http://yunkus.com/demo/lib/images/demo-5.jpg" alt="" />
        </div>
		<div id="btn">点击查看效果</div>
		<script src="index.js"></script>
    </body>
</html>
JavaScript 代码
const imgBox = document.querySelector("#imgBox");
const btn = document.querySelector("#btn");
const imgs = imgBox.querySelectorAll("img");
const imgsLen = imgs.length;
let isAnimate = false;  // 是否正在动画(如果是,则只有当动画完成后,再次点击按钮时才会生效)
let endNun = 0;  // 用来判断修改 isAnimate 的值
btn.onclick = album;
function album(){
    if(isAnimate){ // 如果上一次动画还没有演示完
        return;
    }
    isAnimate = true;
    endNun = 0;
    let count = 0; // Uncaught TypeError: Assignment to constant variable
    for(let i=0,item;item=imgs[i++];){
        item.style = "";
        item.timer = setTimeout(()=>{ // 每张图片各自带一个定时器,随机开始动画
            item.callBack = function(){
                item.callBack = function(){
                    count++;
                    item.callBack = function(){
                        endNun++; // 统计走完所有动画的元素个数
                        if(endNun === imgsLen){ // 最后一个元素的最后一个动画执行完后
                            isAnimate = false; // 改变状态,让按钮点击可以再次执行动画
                        }
                    }
                    if(count === imgsLen){ // 这里的作用当第二个动画所有的图片都完成了之后,再做以下动画
                        for(let j=0,itemObj;itemObj=imgs[j++];){
                            itemObj.style.transition='';
                            itemObj.style.transform = "rotateY(360deg) translateZ("+ getRandom()*-600 +"px)";
                            setTimeout(()=>{
                                moveFn(itemObj,"2s",function(){
                                    // 等待最后一个元素运动完才再进行下一个动画
                                    this.style.opacity = 1;
                                    this.style.transform = "rotateY(0deg) translateZ(0px)";
                                });
                            },getRandom()*500);
                        }
                    }
                }
                moveFn(item,"1s",function(){
                    this.style.opacity = 0;
                    this.style.borderRadius = "0";
                    this.style.transform = "scale(1)";
                });
            };
            moveFn(item,"1s",function(){
                this.style.borderRadius = "50%";
                this.style.transform = "scale(0)";
            })
        },getRandom()*1000);
    }

    function moveFn(target,time,fn){
        // transition-property
        // transition-duration
        // transition-timing-function
        // transition-delay
        // target.style.transition = propertyTime;
        target.style.transition = "borderRadius "+ time +", opacity "+ time +",transform " + time;
        let flag = false;
        fn && fn.bind(target)(); // 执行函数
        target.addEventListener("transitionend",endCallBack,false);
        function endCallBack(){
            this.callBack && this.callBack(); // 执行回调函数
            this.removeEventListener("transitionend",endCallBack); // 动画完成解绑事件监听
        }
    }
    function getRandom(){
        return Math.random();
    }
}

上面的解绑事件监听可以防止 transitionend 被多次触发,因为当我们有多个元素作动画时,那么监听 transitionend 事件时就会被多次触发,不过这里有一点需要注意,就是用这种移除监听方法来避免监听对应多次触发 transitionend 事件,多个属性作动画的时长应该要一致,不然就会产生意想不到的结果.
如果觉得上面这种方法不是很好,你可以在 moveFn() 函数中添加一个变量用来标记同一个元素在同一阶段(同时多个动画)只执行一次相关代码,代码如下:

其它实现方式
function moveFn(target,time,fn){
    target.style.transition = "borderRadius "+ time +", opacity "+ time +",transform " + time;
    let flag = false;
    fn && fn.bind(target)(); // 执行函数
    target.addEventListener("transitionend",function(){
        if(!!!flag){
            this.callBack && this.callBack();
            flag=true;
        }
    },false);
}

总之,萝卜青菜各有所爱,用你喜欢的方式,不管怎样,达到效果,并且你已经理解发其中的原理就好.

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/javascript-photo-wall-2/

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论 END