165 lines
5.4 kB
1
/**
2
* @license MIT
3
* topbar 2.0.0, 2023-02-04
4
* https://buunguyen.github.io/topbar
5
* Copyright (c) 2021 Buu Nguyen
6
*/
7
(function (window, document) {
8
"use strict";
9
10
// https://gist.github.com/paulirish/1579671
11
(function () {
12
var lastTime = 0;
13
var vendors = ["ms", "moz", "webkit", "o"];
14
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
15
window.requestAnimationFrame =
16
window[vendors[x] + "RequestAnimationFrame"];
17
window.cancelAnimationFrame =
18
window[vendors[x] + "CancelAnimationFrame"] ||
19
window[vendors[x] + "CancelRequestAnimationFrame"];
20
}
21
if (!window.requestAnimationFrame)
22
window.requestAnimationFrame = function (callback, element) {
23
var currTime = new Date().getTime();
24
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
25
var id = window.setTimeout(function () {
26
callback(currTime + timeToCall);
27
}, timeToCall);
28
lastTime = currTime + timeToCall;
29
return id;
30
};
31
if (!window.cancelAnimationFrame)
32
window.cancelAnimationFrame = function (id) {
33
clearTimeout(id);
34
};
35
})();
36
37
var canvas,
38
currentProgress,
39
showing,
40
progressTimerId = null,
41
fadeTimerId = null,
42
delayTimerId = null,
43
addEvent = function (elem, type, handler) {
44
if (elem.addEventListener) elem.addEventListener(type, handler, false);
45
else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
46
else elem["on" + type] = handler;
47
},
48
options = {
49
autoRun: true,
50
barThickness: 3,
51
barColors: {
52
0: "rgba(26, 188, 156, .9)",
53
".25": "rgba(52, 152, 219, .9)",
54
".50": "rgba(241, 196, 15, .9)",
55
".75": "rgba(230, 126, 34, .9)",
56
"1.0": "rgba(211, 84, 0, .9)",
57
},
58
shadowBlur: 10,
59
shadowColor: "rgba(0, 0, 0, .6)",
60
className: null,
61
},
62
repaint = function () {
63
canvas.width = window.innerWidth;
64
canvas.height = options.barThickness * 5; // need space for shadow
65
66
var ctx = canvas.getContext("2d");
67
ctx.shadowBlur = options.shadowBlur;
68
ctx.shadowColor = options.shadowColor;
69
70
var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
71
for (var stop in options.barColors)
72
lineGradient.addColorStop(stop, options.barColors[stop]);
73
ctx.lineWidth = options.barThickness;
74
ctx.beginPath();
75
ctx.moveTo(0, options.barThickness / 2);
76
ctx.lineTo(
77
Math.ceil(currentProgress * canvas.width),
78
options.barThickness / 2
79
);
80
ctx.strokeStyle = lineGradient;
81
ctx.stroke();
82
},
83
createCanvas = function () {
84
canvas = document.createElement("canvas");
85
var style = canvas.style;
86
style.position = "fixed";
87
style.top = style.left = style.right = style.margin = style.padding = 0;
88
style.zIndex = 100001;
89
style.display = "none";
90
if (options.className) canvas.classList.add(options.className);
91
document.body.appendChild(canvas);
92
addEvent(window, "resize", repaint);
93
},
94
topbar = {
95
config: function (opts) {
96
for (var key in opts)
97
if (options.hasOwnProperty(key)) options[key] = opts[key];
98
},
99
show: function (delay) {
100
if (showing) return;
101
if (delay) {
102
if (delayTimerId) return;
103
delayTimerId = setTimeout(() => topbar.show(), delay);
104
} else {
105
showing = true;
106
if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
107
if (!canvas) createCanvas();
108
canvas.style.opacity = 1;
109
canvas.style.display = "block";
110
topbar.progress(0);
111
if (options.autoRun) {
112
(function loop() {
113
progressTimerId = window.requestAnimationFrame(loop);
114
topbar.progress(
115
"+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
116
);
117
})();
118
}
119
}
120
},
121
progress: function (to) {
122
if (typeof to === "undefined") return currentProgress;
123
if (typeof to === "string") {
124
to =
125
(to.indexOf("+") >= 0 || to.indexOf("-") >= 0
126
? currentProgress
127
: 0) + parseFloat(to);
128
}
129
currentProgress = to > 1 ? 1 : to;
130
repaint();
131
return currentProgress;
132
},
133
hide: function () {
134
clearTimeout(delayTimerId);
135
delayTimerId = null;
136
if (!showing) return;
137
showing = false;
138
if (progressTimerId != null) {
139
window.cancelAnimationFrame(progressTimerId);
140
progressTimerId = null;
141
}
142
(function loop() {
143
if (topbar.progress("+.1") >= 1) {
144
canvas.style.opacity -= 0.05;
145
if (canvas.style.opacity <= 0.05) {
146
canvas.style.display = "none";
147
fadeTimerId = null;
148
return;
149
}
150
}
151
fadeTimerId = window.requestAnimationFrame(loop);
152
})();
153
},
154
};
155
156
if (typeof module === "object" && typeof module.exports === "object") {
157
module.exports = topbar;
158
} else if (typeof define === "function" && define.amd) {
159
define(function () {
160
return topbar;
161
});
162
} else {
163
this.topbar = topbar;
164
}
165
}.call(this, window, document));
166