1. Preface
I've always been very fond of win8 waiting for the prompt circle progress bar. When win8 first came out, it felt so amazing! I had no idea at that time and didn't study it. After searching for information online recently, I finally got it! Let’s go to the demo first and show off your ugly face! For preview, please see: win8 progress bar.
2. Brief introduction
Writing native JavaScript, you need to understand that js is based on object-oriented programming and circular coordinate calculation!
Implementation principle: abstract each dot into an object (ProgressBarWin8 type), store each dot object in an array (progressArray), delay the execution of the run method of each dot object. As for the faster and faster dot running, it is achieved by changing the timer delay milliseconds.
The code copy is as follows:
// Determine the coordinate size of element x and center x, and set the timer delay time
if (this.position.left < this.fixed.left) {
this.delay += .5;
} else {
this.delay -= .5;
}
It's better to use the source code! The expression ability is really not very good (the comments in the code are more detailed, and you will see more clearly).
The code copy is as follows:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Imitation win8 waiting for progress bar</title>
<style>
body {
margin: 0;
padding: 0;
background: green
}
</style>
</head>
<body>
<script>
//*********Preparation conditions*********
// Radi angle conversion formula: Radius = Math.PI* angle/180; functions such as Math.sin(), Math.cos() in js are calculated based on radians
// Calculation formula for the x-axis coordinates of the circle: Math.cos(Math.PI * Angle/180) * Radius + center x-axis coordinates of the x-axis
// Calculation formula for y-axis coordinates of circles: Math.sin(Math.PI * Angle/180) * Radius + y-axis coordinates of circles
//*********Preparation conditions*********
// Dot element class (there is no concept of class in js, just simulated here)
function ProgressBarWin8() {
// Center coordinates
this.fixed = {
left: 0,
top: 0
};
// html tag element coordinate
this.position = {
left: 0,
top: 0
};
this.radius = 70; // Circle radius
this.angle = 270; // Angle, default 270
this.delay = 30; // Timer delay milliseconds
this.timer = null; // Timer time object
this.dom = null; // html tag element
// html tag element style, position needs to be set to absolute
this.style = {
position: "absolute",
width: "10px",
height: "10px",
background: "#fff",
"border-radius": "5px"
};
}
// Each function in js has a prototype object attribute, and each instance can be accessed
ProgressBarWin8.prototype = {
// Run method
run: function() {
if (this.timer) {
clearTimeout(this.timer);
}
// Set the coordinates of the html tag element, that is, calculate the coordinates of the points x and y axis on the circle
this.position.left = Math.cos(Math.PI * this.angle / 180) * this.radius + this.fixed.left;
this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius + this.fixed.top;
this.dom.style.left = this.position.left + "px";
this.dom.style.top = this.position.top + "px";
// Change the angle
this.angle++;
// Determine the coordinate size of element x and center x, and set the timer delay time
if (this.position.left < this.fixed.left) {
this.delay += .5;
} else {
this.delay -= .5;
}
var scope = this;
// Timer, looping to call the run method, it feels a bit recursive
this.timer = setTimeout(function () {
// The call of the function in js this points to the caller, and this is currently window
scope.run();
}, this.delay);
},
// Initial setting of html tag elements
defaultSetting: function () {
// Create a span element
this.dom = document.createElement("span");
// Set the style of the span element, the traversal of the object in js is the attribute
for (var property in this.style) {
// Object methods in js can be used with . operators, or through key-value pairs
this.dom.style[property] = this.style[property];
}
// The width of the document display area in the innerWidth innerHeight window does not include borders and scroll bars. This property is readable and writable.
// Set the x and y-axis coordinates of the center of the circle, the current visual area is the general, that is, the center point
this.fixed.left = window.innerWidth / 2;
this.fixed.top = window.innerHeight / 2;
// Set the initial coordinates of the span element
this.position.left = Math.cos(Math.PI * this.angle / 180) * this.radius + this.fixed.left;
this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius + this.fixed.top;
this.dom.style.left = this.position.left + "px";
this.dom.style.top = this.position.top + "px";
// Add the span tag to the documet
document.body.appendChild(this.dom);
// Return the current object
return this;
}
};
// If you don't understand, comment out the following code and test the operation of a dot first
//new ProgressBarWin8().defaultSetting().run();
var progressArray = [], // is used to store each dot element object array. The array size in js is variable, similar to list collection
tempArray = [], // Used to store each object thrown by progressArray. After the window size is changed, reset the center coordinate of each object.
timer = 200; // Timer to execute an element object run method every milliseconds
// Create dot element object and save it in an array, and create 5 objects here
for (var i = 0; i < 5; ++i) {
progressArray.push(new ProgressBarWin8().defaultSetting());
}
// Extend the array each method, most lambdas in c# are implemented in this way
Array.prototype.each = function (fn) {
for (var i = 0, len = this.length; i < len;) {
// Change the scope of this in the function fn through the call(object,arg1,arg2,...)/apply(object,[arg1,arg2,...]) method, so that it can be used for inheritance
fn.call(this[i++], arguments);// Or: fn.apply(this[i++], arguments)
}
};
// The window size changes event, reset the center coordinates of each element object
window.onresize = function () {
tempArray.each(function () {
this.fixed.left = window.innerWidth / 2;
this.fixed.top = window.innerHeight / 2;
});
};
// How many milliseconds are used to execute the element object run method of the array collection
timer = setInterval(function () {
if (progressArray.length <= 0) {
// Clear this timer, otherwise it will be executed all the time (setTimeOut: how many milliseconds of delay execution, once; setInterval: how many milliseconds of execution, multiple times)
clearInterval(timer);
} else {
// The shift() method is used to delete the first element of the array from it and return the value of the first element.
var entity = progressArray.shift();
tempArray.push(entity);
// Execute the run method of each element object
entity.run();
}
},timer);
</script>
</body>
</html>