Online preview (caution on mobile devices)

github

Once again, it’s the season of the restless, job-hopping, promotion and salary increase, of course, you need a nice resume. As a rookie in the industry, you need a nice resume.

Pictures show

The design is rough, forgive a science student (science has not learned) aesthetic

Introduction page

Skill List page

Experience on page

Work on page

Contact page

Core animation delay function

Js file directory

│ ├ ─ pageSecond. Js │ pageFirst.js │ pageSecond. Js │ pageThird PageFourth. | js / / 4 screen animation pageFifth. Js / / 5 screen animation │ startAni. Js / / page to initialize the animation │ utils. Js/tools/functionCopy the code

Core delay function

The website is divided into five screens, and each screen will perform the animation of the current page. Since the animation is delayed one by one, it is very simple and crude to use setTimeout nesting at the beginning.

setTimeout((a)= > {
    /* The animation that needs to be executed */
    setTimeout((a)= > {
        /* The animation that needs to be executed */
        setTimeout((a)= > {
            /* The animation that needs to be executed */
        }, delay);
    }, delay);    
}, delay);
Copy the code

I have no problem with the infamous callback function, but we have to consider open source, which is not a shame, so I package a very simple and a little low delay library, let’s say:

class Timeout {
    constructor() {
        this.timer = null; / / timer
        this.fns = []; // Store all motion functions
        this.index = 0; / / index
    }
    to(fn = (a)= > { }, time = 0) {
        // Store all executing functions and their corresponding latency
        this.fns.push({
            fn,
            time
        });
        return this;
    }
    start() {
        const _this = this;
        /* The index is used to determine whether the current animation is finished, no further execution is required */
        if (_this.index === _this.fns.length) return;
        // Clear the timer
        _this.pause();
        _this.timer = setTimeout((a)= > {
            // Execute the current stage function
            requestAnimationFrame(_this.fns[_this.index].fn);
            / / index + 1
            _this.index++;
            if (_this.index === _this.fns.length) _this.pause();
            else _this.start();
            // time increments
        }, _this.fns[_this.index].time);
    }
    / / pause
    pause() {
        clearTimeout(this.timer); }};Copy the code

Call as follows:

const t = new Timeout();
t.to((a)= > {
    /* Animation function */
}, delay)
.to((a)= > {
    /* Animation function */
}, delay)
......
// Executes the current animation group
t.start();
Copy the code

That’s better

Each screen eventually exports the start and pause switches for the current screen animation

module.exports = {
    start() {
        t.start();
        /* Other animation start function */
    },
    pause() {
        t.pause();
        /* Other animation pause function */}};Copy the code

When the page scrolls to the current screen, execute the start method, and when it leaves, execute the pause method, especially if the screen requires canvas and setInterval. Pause can save performance

The principle of random car driving on the front screen

preview

There are three factors that determine the motion of the car (driving direction, up and down position, and speed).

Driving direction

Cars drive from left to right or right to left

.car {// car goes to the right &.left {animation-name: moveL; @keyframes moveL { 0% { transform: translateX(-300px) rotateY(0); } 100% { transform: translateX(140vw) rotateY(0); }} // Go to the left &.right {animation-name: moveR; @keyframes moveR { 0% { transform: translateX(140vw) rotateY(180deg); } 100% { transform: translateX(-300px) rotateY(180deg); }} // hover {animation-play-state: paused; }}Copy the code

Upper and lower position

Enumerates the best possible position of all cars to facilitate the random and dynamic generation of CLASS by JS

.bl1 {bottom: 91%;.bl1 {bottom: 91%; z-index: 8; } &.bl2 { bottom: 92%; z-index: 7; } / /... // right lane &.br1 {bottom: 71%; z-index: 18; } &.br2 { bottom: 72%; z-index: 17; } / /... }Copy the code

Travel time

.car {// time &.t1 {animation-duration: 1s; } &.t2 { animation-duration: 2s; } / /... }Copy the code

The core JS code is as follows:

// Exercise class to use
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 = (a)= > {
    /* moveArr is a collection of cars that need to move */
    /* Select a random car */
    moveObj = moveArr[Math.floor(Math.random() * len)];
    // Select a car that is not in motion
    while (moveObj.prop('isAnimated')) {
        moveObj = moveArr[Math.floor(Math.random() * len)];
    };
    // Add the movement symbol to the car that is about to move
    moveObj.prop('isAnimated'.true);
    /* Here comes a 55 drive, determines the current car driving direction */
    const dirNum = Math.round(Math.random()); / / 0 or 1
    // Generate the sports class name
    const className = `${moveStyle.dir[dirNum]} ${moveStyle.time[Math.ceil(Math.random() * 8)]} ${moveStyle.pos[dirNum][Math.ceil(Math.random() * 7)]}`;
    // Add a class to the car and store the class name in the custom data for later clearing
    moveObj.addClass(className).prop('csName', className);
    // Walk every four seconds
    timer = setTimeout((a)= > {
        requestAnimationFrame(move);
    }, 4000);
}
Copy the code

Of course, we need to monitor whether the current car has finished moving, so as to cancel its moving state, so we need to make a monitor:

// When animate completes, the current event is triggered
car.bind("animationEnd webkitAnimationEnd", animateComplete);
function animateComplete() {
    // Empty the randomly generated class motion class and set the current motion state to false
    $(this).removeClass($(this).prop('csName')).prop('isAnimated'.false);
};
Copy the code

Ok, we’re almost done, but there’s a very important performance issue. If the viewer leaves the current screen, we need to clear the current car’s motion timer, and we still end up exporting a start and pause function

return {
    // The car starts to move
    start: move,
    pause() {
        // Clear the car timer
        clearTimeout(timer);
        // Walk through all the cars, empty their motion state
        cars.each(moveEl= > {
            // Remove all moving cars
            if ($(moveEl).prop('isAnimated')) $(moveEl).removeClass($(moveEl).prop('csName')).prop('isAnimated'.false); }); }};// Then put it in the corresponding page
// For example, the final export function on the first screen looks like this:
module.exports = {
    start() {
    	t.start();
        /* The car starts */
    	carAniFn.start();
    },
    pause() {
    	t.pause();
    	/* Leave the current screen, the car pauses */carAniFn.pause(); }};Copy the code

Page switching effect

All pages are wrapped in a div that moves up and down by switching the CSS class name, as shown below

#swiper-box {.ts(.4s linear); #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)); }}Copy the code

Monitor the mouse wheel, here need to pay attention to chrome and Firefox scroll direction need to do some compatibility:

/* Extend the jq function */
$.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); }});Copy the code

Add mouse wheel events to parent elements that need to scroll

swiperBox.onscroll(function (dir) {
   / * * /
    if (dir) index++;
    else index--;
    Len is the number of screens
    if (index >= len) index = 0;
    if (index < 0) index = len - 1;
    if (index === prev) return;
    // Pause the animation on the previous screen
    arr[prev].pause();
    // 3d navigation toggle effect
    navA.eq(prev).removeClass('hover');
    navA.eq(index).addClass('hover');
    // Add the already written class name to the parent
    swiperBox[0].className = 'page' + index;
});
Copy the code

When scrolling to the current screen, the animation of the current screen needs to be executed. Here, we monitor whether the parent page has completed the movement, and then load the corresponding animation of the current page as required:

/* Store the corresponding page in an array to determine if */ is already required
const partArr = [];
swiperBox.bind('transitionend webkitTransitionend'.function (e) {
    /* Consider that the child element will repeatedly trigger the current event, the following */
    if (e.target === this) {
        if(! partArr[index]) partArr[index] = requirePart(index);// If there is no import, import it
        prev = index; // Record the previous screen
        partArr[index].start(); // Execute the animation of the current screen}});// The function used to import individual pages
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'); }}Copy the code

conclusion

Due to technical reasons, there may be many potential problems on the page, welcome interested leaders can guide me through the contact information of the resume, and finally shameless attached address:

Online preview (caution on mobile devices)

github

Personal technology blog (still in development)