0%

[Electron]vanilla js套件系列-Loading效果

前情提要

筆者這邊的主要遇到的情境是,因為要抓攝影鏡頭的視訊streaming到畫面中的Video tag上,但初始化需要一點時間,導致使用者尚未初始化完成前就去按下截圖按鈕,導致程式邏輯錯亂,筆者第一想到的就是加上loading效果,就如同前面幾篇講到的,electron環境,筆者這邊希望使用Vanilla js的解法,幸好有找到解法,此篇就以介紹這個解法為主,跟著筆者一起套上loading效果吧。

內容

筆者會使用[Electron]vanilla js套件系列-listjs的例子,繼續完成其loading效果的demo,筆者想要示範的效果是在http request打出去時,顯示loading效果,response回來後將loading效果關閉,滿適合用這個情境來示範的。

宣告CSS

筆者這邊就直接參考範例中的css,直接貼上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* Absolute Center Spinner */
.loading {
position: fixed;
z-index: 999;
height: 2em;
width: 2em;
overflow: show;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0;
visibility: hidden;
}

/* Transparent Overlay */
.loading:before {
content: '';
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.3);
}

/* :not(:required) hides these rules from IE9 and below */
.loading:not(:required) {
/* hide "loading..." text */
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}

.loading:not(:required):after {
content: '';
display: block;
font-size: 10px;
width: 1em;
height: 1em;
margin-top: -0.5em;
-webkit-animation: spinner 1500ms infinite linear;
-moz-animation: spinner 1500ms infinite linear;
-ms-animation: spinner 1500ms infinite linear;
-o-animation: spinner 1500ms infinite linear;
animation: spinner 1500ms infinite linear;
border-radius: 0.5em;
-webkit-box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) -1.5em 0 0 0, rgba(0, 0, 0, 0.75) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
}

/* Animation */

@-webkit-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-moz-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-o-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}

宣告html區塊

筆者這邊就選擇body區塊中貼上

1
2
3
4
5
6
<div class="container">
<div id="loading" class="loading" onClick="hideSpinner()">
Loading&#8230;
</div>
<!--以下省略-->
</div>

宣告JS

先定義好showhide spinner的function

1
2
3
4
5
6
7
8
9
var loadingDiv = document.getElementById('loading');

function showSpinner() {
loadingDiv.style.visibility = 'visible';
}

function hideSpinner() {
loadingDiv.style.visibility = 'hidden';
}

實際呼叫

依照筆者的情境,呼叫其上章節中所撰寫的show及hide spinner function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// window load好後直接顯示spinner
showSpinner();
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((res) => {
var options = {
valueNames: [ 'id', 'title', 'body', 'userId' ],
item: '<tr><td class="id"></td><td class="title"></td><td class="body"></td><td class="userId"></td></tr>',
page: 10,
pagination: true
};
var values = res.data;
var postList = new List('table-list', options, values);
// 收到response後hide spinner
hideSpinner();
})
.catch((err) => {
// 發生錯誤也要先hide spinner後執行自身邏輯
hideSpinner();
console.log("Error: ", err)
});

loading效果顯示情境來說比較適合有errorcallback的使用情境,不然發生錯誤時loading效果會一直在,使用者體驗會扣分,最後記得在errorcallback中呼叫hideSpinner

結論

這篇就到這邊了,electron環境激發筆者開發各種Vanilla js的解決方案,雖辛苦,也是另一種收穫,收集各種Vanilla js的解決方案,太棒了,又解決了一個筆者頭痛的問題。

參考