Furaffinity-Loading-Animations

Library for creating different loading animations on Furaffinity

当前为 2024-01-21 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/485153/1315111/Furaffinity-Loading-Animations.js

  1. // ==UserScript==
  2. // @name Furaffinity-Loading-Animations
  3. // @namespace Violentmonkey Scripts
  4. // @grant none
  5. // @version 1.1.1
  6. // @author Midori Dragon
  7. // @description Library for creating different loading animations on Furaffinity
  8. // @icon https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png?v2
  9. // @homepageURL https://greasyfork.org/de/scripts/485153-furaffinity-loading-animations
  10. // @supportURL https://greasyfork.org/de/scripts/485153-furaffinity-loading-animations/feedback
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (() => {
  15. class LoadingSpinner {
  16. constructor(baseElem) {
  17. this._delay = 1000;
  18. this._size = 60;
  19. this._spinnerThickness = 4;
  20. this._spinnerLength = 1;
  21. this._linearSpin = false;
  22. this._forecolorHex = "#8941de";
  23. this._backcolorHex = "#f3f3f3";
  24. this._visible = false;
  25. this._baseElem;
  26. this.animationCurve = "cubic-bezier(.53,.24,.46,.83)";
  27. this.spinner;
  28. this.spinnerContainer;
  29. this.baseElem = baseElem;
  30. }
  31.  
  32. set baseElem(value) {
  33. if (this._baseElem == value) return;
  34. this._baseElem = value;
  35.  
  36. if (this.spinnerContainer)
  37. this.spinnerContainer.parentNode.removeChild(this.spinnerContainer);
  38.  
  39. if (!document.getElementById("flaspinnerstyle")) {
  40. const style = document.createElement("style");
  41. style.id = "flaspinnerstyle";
  42. style.type = "text/css";
  43. style.innerHTML = "@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }";
  44. document.head.appendChild(style);
  45. }
  46.  
  47. this.spinnerContainer = document.createElement("div");
  48. this.spinnerContainer.className = "fla-spinner-container";
  49. this.spinnerContainer.style.position = "relative";
  50. this.spinnerContainer.style.width = this.size + "px";
  51. this.spinnerContainer.style.height = this.size + "px";
  52. this.spinnerContainer.style.left = "50%";
  53. this.spinnerContainer.style.transform = "translateX(-50%)";
  54. this.spinnerContainer.style.display = "none";
  55.  
  56. this.spinner = document.createElement("div");
  57. this.spinner.className = "fla-spinner";
  58. this.updateSpinnerBorders();
  59. this.spinner.style.borderRadius = "50%";
  60. this.spinner.style.position = "relative";
  61. this.spinner.style.width = (this.size - this.spinnerThickness * 2) + "px";
  62. this.spinner.style.height = (this.size - this.spinnerThickness * 2) + "px";
  63. this.spinner.style.animation = `spin ${this.delay / 1000}s ${this.animationCurve} infinite`;
  64.  
  65. this.spinnerContainer.appendChild(this.spinner);
  66. this._baseElem.appendChild(this.spinnerContainer);
  67. }
  68. get baseElem() {
  69. return this._baseElem;
  70. }
  71.  
  72. set delay(value) {
  73. if (this._delay == value) return;
  74. this._delay = +value;
  75. if (this.spinner)
  76. this.spinner.style.animation = `spin ${this._delay / 1000}s ${this.animationCurve} infinite`;
  77. }
  78. get delay() {
  79. return this._delay;
  80. }
  81.  
  82. set linearSpin(value) {
  83. if (this._linearSpin == value) return;
  84. this._linearSpin = value;
  85.  
  86. this.animationCurve = this._linearSpin == true ? "linear" : "cubic-bezier(.53,.24,.46,.83)";
  87.  
  88. if (this.spinner)
  89. this.spinner.style.animation = `spin ${this.delay / 1000}s ${this.animationCurve} infinite`;
  90. }
  91. get linearSpin() {
  92. return this._linearSpin;
  93. }
  94.  
  95. set size(value) {
  96. if (this._size == value) return;
  97. this._size = +value;
  98.  
  99. if (this.spinnerContainer) {
  100. this.spinnerContainer.style.width = this._size + "px";
  101. this.spinnerContainer.style.height = this._size + "px";
  102. }
  103. if (this.spinner) {
  104. this.spinner.style.width = (this.size - this.spinnerThickness * 2) + "px";
  105. this.spinner.style.height = (this.size - this.spinnerThickness * 2) + "px";
  106. }
  107. }
  108. get size() {
  109. return this._size;
  110. }
  111.  
  112. set spinnerThickness(value) {
  113. if (this._spinnerThickness == value) return;
  114. this._spinnerThickness = +value;
  115.  
  116. this.updateSpinnerBorders();
  117. }
  118. get spinnerThickness() {
  119. return this._spinnerThickness;
  120. }
  121.  
  122. set spinnerLength(value) {
  123. if (this._spinnerLength == value) return;
  124. this._spinnerLength = +value;
  125.  
  126. this.updateSpinnerBorders();
  127. }
  128. get spinnerLength() {
  129. return this._spinnerLength;
  130. }
  131.  
  132. set forecolorHex(value) {
  133. if (this._forecolorHex == value) return;
  134. this._forecolorHex = value;
  135.  
  136. this.updateSpinnerBorders();
  137. }
  138. get forecolorHex() {
  139. return this._forecolorHex;
  140. }
  141.  
  142. set backcolorHex(value) {
  143. if (this._backcolorHex == value) return;
  144. this._backcolorHex = value;
  145.  
  146. this.updateSpinnerBorders();
  147. }
  148. get backcolorHex() {
  149. return this._backcolorHex;
  150. }
  151.  
  152. set visible(value) {
  153. if (this._visible == value) return;
  154. this._visible = value;
  155.  
  156. if (this.spinnerContainer)
  157. this.spinnerContainer.style.display = this._visible == true ? "block" : "none";
  158. }
  159. get visible() {
  160. return this._visible;
  161. }
  162.  
  163. updateSpinnerBorders() {
  164. if (this.spinner) {
  165. this.spinner.style.border = this.spinnerThickness + "px solid " + this.backcolorHex;
  166. if (this.spinnerLength >= 1)
  167. this.spinner.style.borderTop = this.spinnerThickness + "px solid " + this._forecolorHex;
  168. if (this.spinnerLength >= 2)
  169. this.spinner.style.borderRight = this.spinnerThickness + "px solid " + this._forecolorHex;
  170. if (this.spinnerLength >= 3)
  171. this.spinner.style.borderBottom = this.spinnerThickness + "px solid " + this._forecolorHex;
  172. if (this.spinnerLength >= 4)
  173. this.spinner.style.borderLeft = this.spinnerThickness + "px solid " + this._forecolorHex;
  174. }
  175. }
  176. }
  177. window.LoadingSpinner = LoadingSpinner;
  178.  
  179. class LoadingTextSpinner {
  180. constructor(baseElem) {
  181. this.characters = ["◜", "◠", "◝", "◞", "◡", "◟"];
  182. this.delay = 600;
  183. this.spinner;
  184. this._visible = false;
  185. this._fontSize = 15;
  186. this._currIndex = -1;
  187. this._intervalId;
  188. this._baseElemText = baseElem.textContent;
  189. this._baseElem;
  190. this.baseElem = baseElem;
  191. }
  192.  
  193. set baseElem(value) {
  194. if (this._baseElem == value) return;
  195. this._baseElem = value;
  196.  
  197. if (this.spinner)
  198. this.spinner.parentNode.removeChild(this.spinner);
  199.  
  200. this.spinner = document.createElement("div");
  201. this.spinner.className = "fla-text-spinner";
  202. if (this.fontSize)
  203. this.spinner.style.fontSize = this.fontSize + "px";
  204. this._baseElemText = this._baseElem.textContent;
  205. this._baseElem.appendChild(this.spinner);
  206. }
  207. get baseElem() {
  208. return this._baseElem;
  209. }
  210.  
  211. set fontSize(value) {
  212. if (this._fontSize == value) return;
  213. this._fontSize = value;
  214.  
  215. if (this.spinner) {
  216. if (this._fontSize)
  217. this.spinner.style.fontSize = this._fontSize + "px";
  218. else
  219. this.spinner.style.fontSize = "";
  220. }
  221. }
  222. get fontSize() {
  223. return this._fontSize;
  224. }
  225.  
  226. set visible(value) {
  227. if (this._visible == value) return;
  228. this._visible = value;
  229.  
  230. if (this.spinner)
  231. this.spinner.style.display = this._visible == true ? "block" : "none";
  232.  
  233. let run;
  234. if (this._visible) {
  235. run = true;
  236. this.baseElem.textContent = "";
  237. this.baseElem.appendChild(this.spinner);
  238. this._intervalId = setInterval(() => {
  239. if (this._currIndex >= this.characters.length)
  240. this._currIndex = 0;
  241. if (run == true) {
  242. this.spinner.textContent = this.characters[this._currIndex];
  243. this._currIndex++;
  244. }
  245. }, (this.delay / this.characters.length));
  246. } else {
  247. run = false;
  248. clearInterval(this._intervalId);
  249. this.baseElem.textContent = this._baseElemText;
  250. }
  251. }
  252. get visible() {
  253. return this._visible;
  254. }
  255. }
  256. window.LoadingTextSpinner = LoadingTextSpinner;
  257.  
  258. class LoadingImage {
  259. constructor(baseElem) {
  260. this.delay = 100;
  261. this.doScaleImage = true;
  262. this.scaleChange = 0.05;
  263. this.scaleChangeMax = 1.2;
  264. this.scaleChangeMin = 0.8;
  265. this.doRotateImage = true;
  266. this.rotadeDegrees = 5;
  267. this.image;
  268. this.imageContainer;
  269. this._visible = false;
  270. this._imageSrc = "https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png";
  271. this.isGrowing = true;
  272. this.scale = 1;
  273. this.rotation = 0;
  274. this._size = 60;
  275. this._intervalId;
  276. this._baseElem;
  277. this.baseElem = baseElem;
  278. }
  279.  
  280. set baseElem(value) {
  281. if (this._baseElem == value) return;
  282. this._baseElem = value;
  283.  
  284. if (this.image)
  285. this.image.parentNode.removeChild(this.image);
  286.  
  287. this.imageContainer = document.createElement("div");
  288. this.imageContainer.className = "fla-loading-image-container";
  289. this.imageContainer.style.position = "relative";
  290. this.imageContainer.style.width = this.size + "px";
  291. this.imageContainer.style.height = this.size + "px";
  292. this.imageContainer.style.left = "50%";
  293. this.imageContainer.style.transform = "translateX(-50%)";
  294. this.imageContainer.style.display = "none";
  295.  
  296. this.image = document.createElement("img");
  297. this.image.className = "fla-loading-image";
  298. this.image.src = this.imageSrc;
  299. this.image.style.width = "100%";
  300. this.image.style.height = "100%";
  301. this.image.style.transition = "transform 0.5s ease-in-out";
  302.  
  303. this.imageContainer.appendChild(this.image);
  304. this._baseElem.appendChild(this.imageContainer);
  305. }
  306. get baseElem() {
  307. return this._baseElem;
  308. }
  309.  
  310. set imageSrc(value) {
  311. if (this._imageSrc == value) return;
  312. this._imageSrc = value;
  313.  
  314. if (this.image)
  315. this.image.src = this._imageSrc;
  316. }
  317. get imageSrc() {
  318. return this._imageSrc;
  319. }
  320.  
  321. set size(value) {
  322. if (this._size == value) return;
  323. this._size = value;
  324.  
  325. if (this.imageContainer) {
  326. this.imageContainer.style.width = this._size + "px";
  327. this.imageContainer.style.height = this._size + "px";
  328. }
  329. }
  330. get size() {
  331. return this._size;
  332. }
  333.  
  334. set visible(value) {
  335. if (this._visible == value) return;
  336. this._visible = value;
  337.  
  338. if (this.imageContainer)
  339. this.imageContainer.style.display = this._visible == true ? "block" : "none";
  340.  
  341. if (this._visible == true) {
  342. this._intervalId = setInterval(() => {
  343. this.updateAnimationFrame();
  344. }, this.delay);
  345. } else
  346. clearInterval(this._intervalId);
  347. }
  348. get visible() {
  349. return this._visible;
  350. }
  351.  
  352. updateAnimationFrame() {
  353. if (this.isGrowing == true) {
  354. this.scale += this.scaleChange;
  355. this.rotation += this.rotadeDegrees;
  356. } else {
  357. this.scale -= this.scaleChange;
  358. this.rotation -= this.rotadeDegrees;
  359. }
  360.  
  361. if (this.scale >= this.scaleChangeMax || this.scale <= this.scaleChangeMin)
  362. this.isGrowing = !this.isGrowing;
  363.  
  364. this.image.style.transform = `scale(${this.scale}) rotate(${this.rotation}deg)`;
  365. }
  366. }
  367. window.LoadingImage = LoadingImage;
  368.  
  369. class ProgressBar {
  370. constructor(baseElem) {
  371. this.progressBarContainer;
  372. this.progressBarChild;
  373. this.progressBarShrinker;
  374. this.progressBarText;
  375. this.text;
  376. this.showPercent = false;
  377. this._imageSrc;
  378. this._visible = false;
  379. this._gradient = "linear-gradient(90deg, rgba(255,10,3,1) 0%, rgba(255,139,6,1) 16%, rgba(253,228,11,1) 36%, rgba(127,236,12,1) 59%, rgba(32,225,207,1) 75%, rgba(140,60,223,1) 95%)";
  380. this._backcolorHex = "#000000";
  381. this._height = 60;
  382. this._fontSize = 15;
  383. this._cornerRadius = 0;
  384. this._baseElem;
  385. this.baseElem = baseElem;
  386. }
  387.  
  388. set baseElem(value) {
  389. if (this._baseElem == value) return;
  390. this._baseElem = value;
  391.  
  392. if (this.progressBarContainer)
  393. this.progressBarContainer.parentNode.removeChild(this.progressBarContainer);
  394.  
  395. if (!document.getElementById("flaprogressstyle")) {
  396. const style = document.createElement("style");
  397. style.id = "flaprogressstyle";
  398. style.type = "text/css";
  399. style.innerHTML = `
  400. .fla-progressbar-container {
  401. width: 100%;
  402. position: relative;
  403. overflow: hidden;
  404. }
  405.  
  406. .fla-progress {
  407. color: white;
  408. text-align: center;
  409. line-height: 60px;
  410. font-size: 35px;
  411. font-family: "Segoe UI";
  412. width: 100%;
  413. height: 100%;
  414. position: absolute;
  415. background-size: cover;
  416. }
  417.  
  418. .fla-shrinker {
  419. position: absolute;
  420. top: 0;
  421. right: 0;
  422. transition: width 0.5s ease;
  423. width: 100%;
  424. height: 100%;
  425. }
  426.  
  427. .fla-progressbar-text {
  428. color: white;
  429. position: absolute;
  430. width: 100%;
  431. text-align: center;
  432. left: 50%;
  433. transform: translateX(-50%);
  434. text-shadow: -1px -1px 0 #000000, 1px -1px 0 #000000, -1px 1px 0 #000000, 1px 1px 0 #000000;
  435. }`;
  436. document.head.appendChild(style);
  437. }
  438.  
  439. this.progressBarContainer = document.createElement("div");
  440. this.progressBarContainer.className = "fla-progressbar-container";
  441. this.progressBarContainer.style.height = this.height + "px";
  442. this.progressBarContainer.style.display = "none";
  443.  
  444. this.progressBarChild = document.createElement("div");
  445. this.progressBarChild.className = "fla-progress";
  446. this.progressBarChild.style.background = this.gradient;
  447. if (this.imageSrc)
  448. this.progressBarChild.style.backgroundImage = "url(" + this.imageSrc + ")";
  449.  
  450. this.progressBarShrinker = document.createElement("div");
  451. this.progressBarShrinker.className = "fla-shrinker";
  452. this.progressBarShrinker.style.backgroundColor = this.backcolorHex;
  453.  
  454. this.progressBarText = document.createElement("span");
  455. this.progressBarText.className = "fla-progressbar-text";
  456. this.progressBarText.style.lineHeight = this.height + "px";
  457.  
  458. this.progressBarContainer.appendChild(this.progressBarChild);
  459. this.progressBarContainer.appendChild(this.progressBarShrinker);
  460. this.progressBarContainer.appendChild(this.progressBarText);
  461. this._baseElem.appendChild(this.progressBarContainer);
  462. }
  463. get baseElem() {
  464. return this._baseElem;
  465. }
  466.  
  467. set cornerRadius(value) {
  468. if (this._cornerRadius == value) return;
  469. this._cornerRadius = value;
  470.  
  471. if (this.progressBarContainer)
  472. this.progressBarContainer.style.borderRadius = this.cornerRadius + "px";
  473. }
  474. get cornerRadius() {
  475. return this._cornerRadius;
  476. }
  477.  
  478. set height(value) {
  479. if (this._height == value) return;
  480. this._height = value;
  481.  
  482. if (this.progressBarContainer)
  483. this.progressBarContainer.style.height = this._height + "px";
  484. if (this.progressBarText)
  485. this.progressBarText.style.lineHeight = this._height + "px";
  486. }
  487. get height() {
  488. return this._height;
  489. }
  490.  
  491. set fontSize(value) {
  492. if (this._fontSize == value) return;
  493. this._fontSize = value;
  494.  
  495. if (this.progressBarText) {
  496. if (this._fontSize)
  497. this.progressBarText.style.fontSize = this._fontSize + "px";
  498. else
  499. this.progressBarText.style.fontSize = "";
  500. }
  501. }
  502. get fontSize() {
  503. return this._fontSize;
  504. }
  505.  
  506. set gradient(value) {
  507. if (this._gradient == value) return;
  508. this._gradient = value;
  509.  
  510. if (this.progressBarChild)
  511. this.progressBarChild.style.background = this._gradient;
  512. }
  513. get gradient() {
  514. return this._gradient;
  515. }
  516.  
  517. set backcolorHex(value) {
  518. if (this._backcolorHex == value) return;
  519. this._backcolorHex = value;
  520.  
  521. if (this.progressBarShrinker)
  522. this.progressBarShrinker.style.backgroundColor = this._backcolorHex;
  523. }
  524. get backcolorHex() {
  525. return this._backcolorHex;
  526. }
  527.  
  528. set imageSrc(value) {
  529. if (this._imageSrc == value) return;
  530. this._imageSrc = value;
  531.  
  532. if (this.progressBarChild) {
  533. if (this._imageSrc)
  534. this.progressBarChild.style.backgroundImage = "url(" + this._imageSrc + ")";
  535. else
  536. this.progressBarChild.style.backgroundImage = "";
  537. }
  538. }
  539. get imageSrc() {
  540. return this._imageSrc;
  541. }
  542.  
  543. set visible(value) {
  544. if (this._visible == value) return;
  545. this._visible = value;
  546.  
  547. if (this.progressBarContainer)
  548. this.progressBarContainer.style.display = this._visible == true ? "block" : "none";
  549. }
  550. get visible() {
  551. return this._visible;
  552. }
  553.  
  554. update(value) {
  555. value = +value;
  556. if (value > 100)
  557. value = 100;
  558. else if (value < 0)
  559. value = 0;
  560. this.progressBarShrinker.style.width = (100 - value) + '%';
  561. this.progressBarText.textContent = (this.text ? this.text : "") + (this.showPercent == true ? value.toString() + "%" : "");
  562. }
  563. }
  564. window.ProgressBar = ProgressBar;
  565.  
  566. class LoadingBar {
  567. constructor(baseElem) {
  568. this.loadingBar;
  569. this._delay = 2000;
  570. this._text;
  571. this._height = 60;
  572. this._fontSize = 15;
  573. this._cornerRadius = 0;
  574. this._gradient = "repeating-linear-gradient(to right, rgba(255,10,3,1) 0%, rgba(255,139,6,1) 8%, rgba(253,228,11,1) 16%, rgba(127,236,12,1) 26%, rgba(32,225,207,1) 36%, rgba(140,60,223,1) 46%, rgba(140,60,223,1) 54%, rgba(32,225,207,1) 64%, rgba(127,236,12,1) 74%, rgba(253,228,11,1) 84%, rgba(255,139,6,1) 92%, rgba(255,10,3,1) 100%)";
  575. this._baseElem;
  576. this._visible = false;
  577. this.baseElem = baseElem;
  578. }
  579.  
  580. set baseElem(value) {
  581. if (this._baseElem == value) return;
  582. this._baseElem = value;
  583.  
  584. if (this.loadingBar)
  585. this.loadingBar.parentNode.removeChild(this.loadingBar);
  586.  
  587. if (!document.getElementById("flaloadingbarstyle")) {
  588. const style = document.createElement("style");
  589. style.id = "flaloadingbarstyle";
  590. style.type = "text/css";
  591. style.innerHTML = "@keyframes gradient { 0% { background-position: 0 0; } 100% { background-position: -200% 0; } }";
  592. document.head.appendChild(style);
  593. }
  594.  
  595. this.loadingBar = document.createElement("div");
  596. this.loadingBar.className = "fla-loadingbar";
  597. this.loadingBar.textContent = this.text;
  598. this.loadingBar.style.width = "100%";
  599. this.loadingBar.style.height = this.height + "px";
  600. this.loadingBar.style.lineHeight = this.height + "px";
  601. this.loadingBar.style.textShadow = "-1px -1px 0 #000000, 1px -1px 0 #000000, -1px 1px 0 #000000, 1px 1px 0 #000000";
  602. this.loadingBar.style.background = this.gradient;
  603. this.loadingBar.style.backgroundSize = "200% auto";
  604. this.loadingBar.style.backgroundPosition = "0 100%";
  605. this.loadingBar.style.animation = `gradient ${(this.delay / 1000)}s infinite`;
  606. this.loadingBar.style.animationFillMode = "forwards";
  607. this.loadingBar.style.animationTimingFunction = "linear";
  608. this.loadingBar.style.display = "none";
  609.  
  610. this._baseElem.appendChild(this.loadingBar);
  611. }
  612. get baseElem() {
  613. return this._baseElem;
  614. }
  615.  
  616. set delay(value) {
  617. if (this._delay == value) return;
  618. this._delay = value;
  619.  
  620. if (this.loadingBar)
  621. this.loadingBar.style.animation = `gradient ${(this._delay / 1000)}s infinite`;
  622. }
  623. get delay() {
  624. return this._delay;
  625. }
  626.  
  627. set text(value) {
  628. if (this._text == value) return;
  629. this._text = value;
  630.  
  631. if (this.loadingBar)
  632. this.loadingBar.textContent = this._text;
  633. }
  634. get text() {
  635. return this._text;
  636. }
  637.  
  638. set cornerRadius(value) {
  639. if (this._cornerRadius == value) return;
  640. this._cornerRadius = value;
  641.  
  642. if (this.loadingBar)
  643. this.loadingBar.style.borderRadius = this.cornerRadius + "px";
  644. }
  645. get cornerRadius() {
  646. return this._cornerRadius;
  647. }
  648.  
  649. set height(value) {
  650. if (this._height == value) return;
  651. this._height = value;
  652.  
  653. if (this.loadingBar) {
  654. this.loadingBar.style.height = this._height + "px";
  655. this.loadingBar.style.lineHeight = this._height + "px";
  656. }
  657. }
  658. get height() {
  659. return this._height;
  660. }
  661.  
  662. set fontSize(value) {
  663. if (this._fontSize == value) return;
  664. this._fontSize = value;
  665.  
  666. if (this.loadingBar) {
  667. if (this._fontSize)
  668. this.loadingBar.style.fontSize = this._fontSize + "px";
  669. else
  670. this.loadingBar.style.fontSize = "";
  671. }
  672. }
  673. get fontSize() {
  674. return this._fontSize;
  675. }
  676.  
  677. set gradient(value) {
  678. if (this._gradient == value) return;
  679. this._gradient = value;
  680.  
  681. if (this.loadingBar)
  682. this.loadingBar.style.background = this._gradient;
  683. }
  684. get gradient() {
  685. return this._gradient;
  686. }
  687.  
  688. set visible(value) {
  689. if (this._visible == value) return;
  690. this._visible = value;
  691.  
  692. if (this.loadingBar)
  693. this.loadingBar.style.display = this._visible == true ? "block" : "none";
  694. }
  695. get visible() {
  696. return this._visible;
  697. }
  698. }
  699. window.LoadingBar = LoadingBar;
  700. })();