jQuery+CSS3搞一個動畫簡歷

在線預覽(移動端慎入)css

github前端

又到了一年一度躁動不安的季節,跳槽升職加薪固然須要一份很nice的簡歷啦,做爲一位在本圈剛出道的前端小白,固然須要一份很nice的簡歷啦!css3

圖片展現

設計粗糙,原諒一個理科生(理科都還沒學好)的審美git

介紹頁

技能清單頁

經歷頁

做品頁

聯繫方式頁

核心動畫延遲函數

js文件目錄

│  jqExt.js // 擴展一些jq插件
│  main.js // 主函數
│  pageFirst.js // 第一屏動畫
│  pageSecond.js // 第二屏動畫
│  pageThird.js // 第三屏動畫
│  pageFourth.js // 第四屏動畫
|  pageFifth.js // 第五屏動畫
│  startAni.js // 頁面初始化動畫
│  utils.js // 工具函數
複製代碼

核心延遲函數

網站一共分爲五屏,每翻到一屏都會執行當前頁面的動畫,因爲動畫爲延遲逐個進行的方式,一開始很是簡單粗暴的使用setTimeout嵌套,醬紫:github

setTimeout(() => {
    /* 須要執行的動畫內容 */
    setTimeout(() => {
        /* 須要執行的動畫內容 */
        setTimeout(() => {
            /* 須要執行的動畫內容 */
        }, delay);
    }, delay);    
}, delay);
複製代碼

臭名遠揚的回調函數,其實我是沒問題的,但是咱得考慮到開源呀,這整出去不是打自個臉嗎,因此自個封裝了一個很是簡易還有點low的延遲庫,醬紫:web

class Timeout {
    constructor() {
        this.timer = null; // 定時器
        this.fns = []; // 存儲全部運動函數
        this.index = 0; // 索引
    }
    to(fn = () => { }, time = 0) {
        // 存儲全部執行函數以及對應的延遲時間
        this.fns.push({
            fn,
            time
        });
        return this;
    }
    start() {
        const _this = this;
        /* 經過索引判斷當前動畫是否執行完畢,不須要繼續執行 */
        if (_this.index === _this.fns.length) return;
        // 清除定時器
        _this.pause();
        _this.timer = setTimeout(() => {
            //執行當前階段函數
            requestAnimationFrame(_this.fns[_this.index].fn);
            // 索引+1
            _this.index++;
            if (_this.index === _this.fns.length) _this.pause();
            else _this.start();
            // 時間遞增
        }, _this.fns[_this.index].time);
    }
    // 暫停
    pause() {
        clearTimeout(this.timer);
    }
};
複製代碼

調用方式以下:chrome

const t = new Timeout();
t.to(() => {
    /* 動畫函數 */
}, delay)
.to(() => {
    /* 動畫函數 */
}, delay)
......
// 執行當前動畫組
t.start();
複製代碼

這就好多了canvas

每一個屏最終都會導出當前屏動畫的開始暫停開關數組

module.exports = {
    start() {
        t.start();
        /* 當前屏其餘動畫開始函數 */
    },
    pause() {
        t.pause();
        /* 當前屏其餘動畫暫停函數 */
    }
};
複製代碼

當頁面滾動到當前屏,執行start開始方法,離開以後執行pause暫停,尤爲是須要canvas和setInterval的屏,暫停能節約性能開銷呢瀏覽器

首屏隨機行駛的小車原理

預覽

首先準備若干量小車div,蜷縮在屏幕外邊隨時準備待命,開一個定時器,隨機抓出一輛小車放生

共有三個要素決定小車的運動形式(行駛方向、上下位置、運動速度)

行駛方向

車從左到右行駛 或 從右到左行駛

.car {
    // 小車向右邊行駛
    &.left {
        animation-name: moveL;
        @keyframes moveL {
            0% {
                transform: translateX(-300px) rotateY(0);
            } 100% {
                transform: translateX(140vw) rotateY(0);
            }
        }
    }

    // 小車向左邊行駛
    &.right {
        animation-name: moveR;
        @keyframes moveR {
            0% {
                transform: translateX(140vw) rotateY(180deg);
            } 100% {
                transform: translateX(-300px) rotateY(180deg);
            }
        }
    }
    
    // 鼠標移動到小車上中止
    &:hover {
        animation-play-state: paused;
    }
 }
複製代碼

上下位置

枚舉出全部小車可能出現的最佳位置,方便js隨機動態生成class

.car {
    /* 枚舉出左右車道小車位置,方便js隨機動態生成class */
    // 左車道
    &.bl1 {
        bottom: 91%;
        z-index: 8;
    }
    &.bl2 {
        bottom: 92%;
        z-index: 7;
    }
    // ......
    
    // 右車道
    &.br1 {
        bottom: 71%;
        z-index: 18;
    }

    &.br2 {
        bottom: 72%;
        z-index: 17;
    }
    // ......
}
複製代碼

行駛時間

.car {
    // 時間
    &.t1 {
        animation-duration: 1s;
    }

    &.t2 {
        animation-duration: 2s;
    }
    // ......
}
複製代碼

核心js代碼以下:

// 須要用到的運動類
const moveStyle = {
    dir: ['left', 'right'],
    time: ['t1', 't2', 't3', 't4', 't5', 't6', 't7', 't8'],
    pos: [['bl1', 'bl2', 'bl3', 'bl4', 'bl5', 'bl6', 'bl7', 'bl8'], ['br1', 'br2', 'br3', 'br4', 'br5', 'br6', 'br7', 'br8']]
}
const move = () => {
    /* moveArr爲須要運動的小車集合 */
    /* 隨機取出一輛小車 len爲小車個數 */
    moveObj = moveArr[Math.floor(Math.random() * len)];
    // 選出一輛不處於運動狀態的小車
    while (moveObj.prop('isAnimated')) {
        moveObj = moveArr[Math.floor(Math.random() * len)];
    };
    // 將即將運動的小車的加上運動標識
    moveObj.prop('isAnimated', true);
    /* 這裏來一個55開,決定當前小車行駛方向 */
    const dirNum = Math.round(Math.random()); // 0或1
    // 生成運動類名
    const className = `${moveStyle.dir[dirNum]} ${moveStyle.time[Math.ceil(Math.random() * 8)]} ${moveStyle.pos[dirNum][Math.ceil(Math.random() * 7)]}`;
    // 給小車加上class,並將類名存儲到自定義數據中,方便後期清空
    moveObj.addClass(className).prop('csName', className);
    // 每隔四秒走一次
    timer = setTimeout(() => {
        requestAnimationFrame(move);
    }, 4000);
}
複製代碼

固然,咱們須要監聽當前小車車是否運動完畢,以此來取消它的運動狀態,因此須要搞一個監聽:

// 當animate完成,會觸發當前事件
car.bind("animationEnd webkitAnimationEnd", animateComplete);
function animateComplete() {
    // 清空剛剛隨機生成的class運動類,而且將當前的運動狀態設置爲false
    $(this).removeClass($(this).prop('csName')).prop('isAnimated', false);
};
複製代碼

ok,差很少完成了,可是還有一個很重要的性能問題,假如瀏覽者離開了當前屏幕,咱們就須要清空當前小車的運動定時器,最終咱們依然導出了一個start(開始)和pause(暫停)函數

return {
    // 小車開始運動
    start: move,
    pause() {
        // 清除小車的定時器
        clearTimeout(timer);
        // 遍歷全部小車,清空他們的運動狀態
        cars.each(moveEl => {
            // 把運動中的車所有清除
            if ($(moveEl).prop('isAnimated')) $(moveEl).removeClass($(moveEl).prop('csName')).prop('isAnimated', false);
        });
    }
};
// 而後放到對應的頁面中去
// 好比首屏最終的導出函數就成了醬紫:
module.exports = {
    start() {
    	t.start();
        /* 小車開始 */
    	carAniFn.start();
    },
    pause() {
    	t.pause();
    	/* 離開當前屏,小車暫停 */
    	carAniFn.pause();
    }
};
複製代碼

頁面切換效果

全部頁面都包裝在一個div裏面,經過切換css類名來實現上下運動,css以下

/* vh是css3的一個相對單位,100vh至關於瀏覽器可視區域的高度 */
#swiper-box {
    .ts(.4s linear);
    &.page0 {
        .tf(translateY(0));
    }

    &.page1 {
        .tf(translateY(-100vh));
    }

    &.page2 {
        .tf(translateY(-200vh));
    }

    &.page3 {
        .tf(translateY(-300vh));
    }

    &.page4 {
        .tf(translateY(-400vh));
    }
}
複製代碼

監聽鼠標滾輪,在這裏須要注意下chrome和firefox滾動方向須要作一下兼容:

/* 擴展jq函數 */
$.fn.extend({
    onscroll(fn) {
        let dir = null;
        let gg, ff;
        $(this).bind('mousewheel || DOMMouseScroll', function (e) {
            gg = e.originalEvent.wheelDelta;
            ff = e.originalEvent.detail;
            dir = gg ? (gg < 0 ? true : false) : (ff < 0 ? false : true);
            fn && fn(dir, e);
        });
        return $(this);
    }
});
複製代碼

給須要滾動的父級元素加上鼠標滾輪事件

swiperBox.onscroll(function (dir) {
   /**/
    if (dir) index++;
    else index--;
    // 判斷index是否超出範圍,len爲屏幕個數
    if (index >= len) index = 0;
    if (index < 0) index = len - 1;
    if (index === prev) return;
    // 暫停上一屏的動畫
    arr[prev].pause();
    // 3d導航切換效果
    navA.eq(prev).removeClass('hover');
    navA.eq(index).addClass('hover');
    // 給父級加上已經寫好的class類名
    swiperBox[0].className = 'page' + index;
});
複製代碼

當滾動到當前屏以後,須要執行當前屏的動畫,在這裏咱們監聽父級頁面是否運動完成,運動完成以後就按需加載當前頁面對應的動畫:

/* 將對應的頁面存儲到數組當中,用於判斷是否已經require過 */
const partArr = [];
swiperBox.bind('transitionend webkitTransitionend', function (e) {
    /* 考慮到子元素會重複觸發當前事件,判斷下子 */
    if (e.target === this) {
        if (!partArr[index]) partArr[index] = requirePart(index); // 若是沒有導入,進行導入
        prev = index; // 記錄上一屏
        partArr[index].start(); // 執行當前屏的動畫
    }
});
// 用於導入各個頁面的函數
function requirePart(index) {
    switch (index) {
        case 0:
            return require('./pageFirst');
        case 1:
            return require('./pageSecond');
        case 2:
            return require('./pageThird');
        case 3:
            return require('./pageFourth');
        case 4:
            return require('./pageFifth');
    }
}
複製代碼

總結

因爲技術緣由頁面可能存在諸多潛在問題,歡迎感興趣的大佬能夠經過簡歷的聯繫方式來指導下我,最後再不要臉的附上地址:

在線預覽(移動端慎入)

github

我的技術博客(還在完善階段)

相關文章
相關標籤/搜索