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)