index.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. function domReady(condition: DocumentReadyState[] = ['complete', 'interactive']) {
  2. return new Promise((resolve) => {
  3. if (condition.includes(document.readyState)) {
  4. resolve(true)
  5. } else {
  6. document.addEventListener('readystatechange', () => {
  7. if (condition.includes(document.readyState)) {
  8. resolve(true)
  9. }
  10. })
  11. }
  12. })
  13. }
  14. const safeDOM = {
  15. append(parent: HTMLElement, child: HTMLElement) {
  16. if (!Array.from(parent.children).find(e => e === child)) {
  17. return parent.appendChild(child)
  18. }
  19. },
  20. remove(parent: HTMLElement, child: HTMLElement) {
  21. if (Array.from(parent.children).find(e => e === child)) {
  22. return parent.removeChild(child)
  23. }
  24. },
  25. }
  26. /**
  27. * https://tobiasahlin.com/spinkit
  28. * https://connoratherton.com/loaders
  29. * https://projects.lukehaas.me/css-loaders
  30. * https://matejkustec.github.io/SpinThatShit
  31. */
  32. function useLoading() {
  33. const className = `loaders-css__square-spin`
  34. const styleContent = `
  35. @keyframes square-spin {
  36. 25% { transform: perspective(100px) rotateX(180deg) rotateY(0); }
  37. 50% { transform: perspective(100px) rotateX(180deg) rotateY(180deg); }
  38. 75% { transform: perspective(100px) rotateX(0) rotateY(180deg); }
  39. 100% { transform: perspective(100px) rotateX(0) rotateY(0); }
  40. }
  41. .${className} > div {
  42. animation-fill-mode: both;
  43. width: 50px;
  44. height: 50px;
  45. background: #fff;
  46. animation: square-spin 3s 0s cubic-bezier(0.09, 0.57, 0.49, 0.9) infinite;
  47. }
  48. .app-loading-wrap {
  49. position: fixed;
  50. top: 0;
  51. left: 0;
  52. width: 100vw;
  53. height: 100vh;
  54. display: flex;
  55. align-items: center;
  56. justify-content: center;
  57. background: #282c34;
  58. z-index: 9;
  59. }
  60. `
  61. const oStyle = document.createElement('style')
  62. const oDiv = document.createElement('div')
  63. oStyle.id = 'app-loading-style'
  64. oStyle.innerHTML = styleContent
  65. oDiv.className = 'app-loading-wrap'
  66. oDiv.innerHTML = `<div class="${className}"><div></div></div>`
  67. return {
  68. appendLoading() {
  69. safeDOM.append(document.head, oStyle)
  70. safeDOM.append(document.body, oDiv)
  71. },
  72. removeLoading() {
  73. safeDOM.remove(document.head, oStyle)
  74. safeDOM.remove(document.body, oDiv)
  75. },
  76. }
  77. }
  78. // ----------------------------------------------------------------------
  79. const { appendLoading, removeLoading } = useLoading()
  80. domReady().then(appendLoading)
  81. window.onmessage = (ev) => {
  82. ev.data.payload === 'removeLoading' && removeLoading()
  83. }
  84. setTimeout(removeLoading, 4999)