Furaffinity-Loading-Animations

Library for creating different loading animations on Furaffinity

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

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

  1. // ==UserScript==
  2. // @name Furaffinity-Loading-Animations
  3. // @namespace Violentmonkey Scripts
  4. // @grant none
  5. // @version 1.0.3
  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._baseElem;
  189. this.baseElem = baseElem;
  190. }
  191.  
  192. set baseElem(value) {
  193. if (this._baseElem == value) return;
  194. this._baseElem = value;
  195.  
  196. if (this.spinner)
  197. this.spinner.parentNode.removeChild(this.spinner);
  198.  
  199. this.spinner = document.createElement("div");
  200. this.spinner.className = "fla-text-spinner";
  201. if (this.fontSize)
  202. this.spinner.style.fontSize = this.fontSize + "px";
  203. this._baseElem.appendChild(this.spinner);
  204. }
  205. get baseElem() {
  206. return this._baseElem;
  207. }
  208.  
  209. set fontSize(value) {
  210. if (this._fontSize == value) return;
  211. this._fontSize = value;
  212.  
  213. if (this.spinner) {
  214. if (this._fontSize)
  215. this.spinner.style.fontSize = this._fontSize + "px";
  216. else
  217. this.spinner.style.fontSize = "";
  218. }
  219. }
  220. get fontSize() {
  221. return this._fontSize;
  222. }
  223.  
  224. set visible(value) {
  225. if (this._visible == value) return;
  226. this._visible = value;
  227.  
  228. if (this.spinner)
  229. this.spinner.style.display = this._visible == true ? "block" : "none";
  230.  
  231. if (this._visible) {
  232. this._intervalId = setInterval(() => {
  233. if (this._currIndex >= this.characters.length)
  234. this._currIndex = 0;
  235. this.spinner.textContent = this.characters[this._currIndex];
  236. this._currIndex++;
  237. }, (this.delay / this.characters.length));
  238. } else
  239. clearInterval(this._intervalId);
  240. }
  241. get visible() {
  242. return this._visible;
  243. }
  244. }
  245. window.LoadingTextSpinner = LoadingTextSpinner;
  246.  
  247. class LoadingImage {
  248. constructor(baseElem) {
  249. this.delay = 100;
  250. this.doScaleImage = true;
  251. this.scaleChange = 0.05;
  252. this.scaleChangeMax = 1.2;
  253. this.scaleChangeMin = 0.8;
  254. this.doRotateImage = true;
  255. this.rotadeDegrees = 5;
  256. this.image;
  257. this.imageContainer;
  258. this._visible = false;
  259. this._imageSrc = "https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png";
  260. this.isGrowing = true;
  261. this.scale = 1;
  262. this.rotation = 0;
  263. this._size = 60;
  264. this._intervalId;
  265. this._baseElem;
  266. this.baseElem = baseElem;
  267. }
  268.  
  269. set baseElem(value) {
  270. if (this._baseElem == value) return;
  271. this._baseElem = value;
  272.  
  273. if (this.image)
  274. this.image.parentNode.removeChild(this.image);
  275.  
  276. this.imageContainer = document.createElement("div");
  277. this.imageContainer.className = "fla-loading-image-container";
  278. this.imageContainer.style.position = "relative";
  279. this.imageContainer.style.width = this.size + "px";
  280. this.imageContainer.style.height = this.size + "px";
  281. this.imageContainer.style.left = "50%";
  282. this.imageContainer.style.transform = "translateX(-50%)";
  283. this.imageContainer.style.display = "none";
  284.  
  285. this.image = document.createElement("img");
  286. this.image.className = "fla-loading-image";
  287. this.image.src = this.imageSrc;
  288. this.image.style.width = "100%";
  289. this.image.style.height = "100%";
  290. this.image.style.transition = "transform 0.5s ease-in-out";
  291.  
  292. this.imageContainer.appendChild(this.image);
  293. this._baseElem.appendChild(this.imageContainer);
  294. }
  295. get baseElem() {
  296. return this._baseElem;
  297. }
  298.  
  299. set imageSrc(value) {
  300. if (this._imageSrc == value) return;
  301. this._imageSrc = value;
  302.  
  303. if (this.image)
  304. this.image.src = this._imageSrc;
  305. }
  306. get imageSrc() {
  307. return this._imageSrc;
  308. }
  309.  
  310. set size(value) {
  311. if (this._size == value) return;
  312. this._size = value;
  313.  
  314. if (this.imageContainer) {
  315. this.imageContainer.style.width = this._size + "px";
  316. this.imageContainer.style.height = this._size + "px";
  317. }
  318. }
  319. get size() {
  320. return this._size;
  321. }
  322.  
  323. set visible(value) {
  324. if (this._visible == value) return;
  325. this._visible = value;
  326.  
  327. if (this.imageContainer)
  328. this.imageContainer.style.display = this._visible == true ? "block" : "none";
  329.  
  330. if (this._visible == true) {
  331. this._intervalId = setInterval(() => {
  332. this.updateAnimationFrame();
  333. }, this.delay);
  334. } else
  335. clearInterval(this._intervalId);
  336. }
  337. get visible() {
  338. return this._visible;
  339. }
  340.  
  341. updateAnimationFrame() {
  342. if (this.isGrowing == true) {
  343. this.scale += this.scaleChange;
  344. this.rotation += this.rotadeDegrees;
  345. } else {
  346. this.scale -= this.scaleChange;
  347. this.rotation -= this.rotadeDegrees;
  348. }
  349.  
  350. if (this.scale >= this.scaleChangeMax || this.scale <= this.scaleChangeMin)
  351. this.isGrowing = !this.isGrowing;
  352.  
  353. this.image.style.transform = `scale(${this.scale}) rotate(${this.rotation}deg)`;
  354. }
  355. }
  356. window.LoadingImage = LoadingImage;
  357.  
  358. class ProgressBar {
  359. constructor(baseElem) {
  360. this.progressBarContainer;
  361. this.progressBarChild;
  362. this.progressBarShrinker;
  363. this.progressBarText;
  364. this.text;
  365. this.showPercent = false;
  366. this._imageSrc;
  367. this._visible = false;
  368. 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%)";
  369. this._backcolorHex = "#000000";
  370. this._height = 60;
  371. this._fontSize = 15;
  372. this._cornerRadius = 0;
  373. this._baseElem;
  374. this.baseElem = baseElem;
  375. }
  376.  
  377. set baseElem(value) {
  378. if (this._baseElem == value) return;
  379. this._baseElem = value;
  380.  
  381. if (this.progressBarContainer)
  382. this.progressBarContainer.parentNode.removeChild(this.progressBarContainer);
  383.  
  384. if (!document.getElementById("flaprogressstyle")) {
  385. const style = document.createElement("style");
  386. style.id = "flaprogressstyle";
  387. style.type = "text/css";
  388. style.innerHTML = `
  389. .fla-progressbar-container {
  390. width: 100%;
  391. position: relative;
  392. overflow: hidden;
  393. }
  394.  
  395. .fla-progress {
  396. color: white;
  397. text-align: center;
  398. line-height: 60px;
  399. font-size: 35px;
  400. font-family: "Segoe UI";
  401. width: 100%;
  402. height: 100%;
  403. position: absolute;
  404. background-size: cover;
  405. }
  406.  
  407. .fla-shrinker {
  408. position: absolute;
  409. top: 0;
  410. right: 0;
  411. transition: width 0.5s ease;
  412. width: 100%;
  413. height: 100%;
  414. }
  415.  
  416. .fla-progressbar-text {
  417. color: white;
  418. position: absolute;
  419. width: 100%;
  420. text-align: center;
  421. left: 50%;
  422. transform: translateX(-50%);
  423. text-shadow: -1px -1px 0 #000000, 1px -1px 0 #000000, -1px 1px 0 #000000, 1px 1px 0 #000000;
  424. }`;
  425. document.head.appendChild(style);
  426. }
  427.  
  428. this.progressBarContainer = document.createElement("div");
  429. this.progressBarContainer.className = "fla-progressbar-container";
  430. this.progressBarContainer.style.height = this.height + "px";
  431. this.progressBarContainer.style.display = "none";
  432.  
  433. this.progressBarChild = document.createElement("div");
  434. this.progressBarChild.className = "fla-progress";
  435. this.progressBarChild.style.background = this.gradient;
  436. if (this.imageSrc)
  437. this.progressBarChild.style.backgroundImage = "url(" + this.imageSrc + ")";
  438.  
  439. this.progressBarShrinker = document.createElement("div");
  440. this.progressBarShrinker.className = "fla-shrinker";
  441. this.progressBarShrinker.style.backgroundColor = this.backcolorHex;
  442.  
  443. this.progressBarText = document.createElement("span");
  444. this.progressBarText.className = "fla-progressbar-text";
  445. this.progressBarText.style.lineHeight = this.height + "px";
  446.  
  447. this.progressBarContainer.appendChild(this.progressBarChild);
  448. this.progressBarContainer.appendChild(this.progressBarShrinker);
  449. this.progressBarContainer.appendChild(this.progressBarText);
  450. this._baseElem.appendChild(this.progressBarContainer);
  451. }
  452. get baseElem() {
  453. return this._baseElem;
  454. }
  455.  
  456. set cornerRadius(value) {
  457. if (this._cornerRadius == value) return;
  458. this._cornerRadius = value;
  459.  
  460. if (this.progressBarContainer)
  461. this.progressBarContainer.style.borderRadius = this.cornerRadius + "px";
  462. }
  463. get cornerRadius() {
  464. return this._cornerRadius;
  465. }
  466.  
  467. set height(value) {
  468. if (this._height == value) return;
  469. this._height = value;
  470.  
  471. if (this.progressBarContainer)
  472. this.progressBarContainer.style.height = this._height + "px";
  473. if (this.progressBarText)
  474. this.progressBarText.style.lineHeight = this._height + "px";
  475. }
  476. get height() {
  477. return this._height;
  478. }
  479.  
  480. set fontSize(value) {
  481. if (this._fontSize == value) return;
  482. this._fontSize = value;
  483.  
  484. if (this.progressBarText) {
  485. if (this._fontSize)
  486. this.progressBarText.style.fontSize = this._fontSize + "px";
  487. else
  488. this.progressBarText.style.fontSize = "";
  489. }
  490. }
  491. get fontSize() {
  492. return this._fontSize;
  493. }
  494.  
  495. set gradient(value) {
  496. if (this._gradient == value) return;
  497. this._gradient = value;
  498.  
  499. if (this.progressBarChild)
  500. this.progressBarChild.style.background = this._gradient;
  501. }
  502. get gradient() {
  503. return this._gradient;
  504. }
  505.  
  506. set backcolorHex(value) {
  507. if (this._backcolorHex == value) return;
  508. this._backcolorHex = value;
  509.  
  510. if (this.progressBarShrinker)
  511. this.progressBarShrinker.style.backgroundColor = this._backcolorHex;
  512. }
  513. get backcolorHex() {
  514. return this._backcolorHex;
  515. }
  516.  
  517. set imageSrc(value) {
  518. if (this._imageSrc == value) return;
  519. this._imageSrc = value;
  520.  
  521. if (this.progressBarChild) {
  522. if (this._imageSrc)
  523. this.progressBarChild.style.backgroundImage = "url(" + this._imageSrc + ")";
  524. else
  525. this.progressBarChild.style.backgroundImage = "";
  526. }
  527. }
  528. get imageSrc() {
  529. return this._imageSrc;
  530. }
  531.  
  532. set visible(value) {
  533. if (this._visible == value) return;
  534. this._visible = value;
  535.  
  536. if (this.progressBarContainer)
  537. this.progressBarContainer.style.display = this._visible == true ? "block" : "none";
  538. }
  539. get visible() {
  540. return this._visible;
  541. }
  542.  
  543. update(value) {
  544. value = +value;
  545. if (value > 100)
  546. value = 100;
  547. else if (value < 0)
  548. value = 0;
  549. this.progressBarShrinker.style.width = (100 - value) + '%';
  550. this.progressBarText.textContent = (this.text ? this.text : "") + (this.showPercent == true ? value.toString() + "%" : "");
  551. }
  552. }
  553. window.ProgressBar = ProgressBar;
  554.  
  555. class LoadingBar {
  556. constructor(baseElem) {
  557. this.loadingBar;
  558. this._delay = 2000;
  559. this._text;
  560. this._height = 60;
  561. this._fontSize = 15;
  562. this._cornerRadius = 0;
  563. 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%)";
  564. this._baseElem;
  565. this._visible = false;
  566. this.baseElem = baseElem;
  567. }
  568.  
  569. set baseElem(value) {
  570. if (this._baseElem == value) return;
  571. this._baseElem = value;
  572.  
  573. if (this.loadingBar)
  574. this.loadingBar.parentNode.removeChild(this.loadingBar);
  575.  
  576. if (!document.getElementById("flaloadingbarstyle")) {
  577. const style = document.createElement("style");
  578. style.id = "flaloadingbarstyle";
  579. style.type = "text/css";
  580. style.innerHTML = "@keyframes gradient { 0% { background-position: 0 0; } 100% { background-position: -200% 0; } }";
  581. document.head.appendChild(style);
  582. }
  583.  
  584. this.loadingBar = document.createElement("div");
  585. this.loadingBar.className = "fla-loadingbar";
  586. this.loadingBar.textContent = this.text;
  587. this.loadingBar.style.width = "100%";
  588. this.loadingBar.style.height = this.height + "px";
  589. this.loadingBar.style.lineHeight = this.height + "px";
  590. this.loadingBar.style.textShadow = "-1px -1px 0 #000000, 1px -1px 0 #000000, -1px 1px 0 #000000, 1px 1px 0 #000000";
  591. this.loadingBar.style.background = this.gradient;
  592. this.loadingBar.style.backgroundSize = "200% auto";
  593. this.loadingBar.style.backgroundPosition = "0 100%";
  594. this.loadingBar.style.animation = `gradient ${(this.delay / 1000)}s infinite`;
  595. this.loadingBar.style.animationFillMode = "forwards";
  596. this.loadingBar.style.animationTimingFunction = "linear";
  597. this.loadingBar.style.display = "none";
  598.  
  599. this._baseElem.appendChild(this.loadingBar);
  600. }
  601. get baseElem() {
  602. return this._baseElem;
  603. }
  604.  
  605. set delay(value) {
  606. if (this._delay == value) return;
  607. this._delay = value;
  608.  
  609. if (this.loadingBar)
  610. this.loadingBar.style.animation = `gradient ${(this._delay / 1000)}s infinite`;
  611. }
  612. get delay() {
  613. return this._delay;
  614. }
  615.  
  616. set text(value) {
  617. if (this._text == value) return;
  618. this._text = value;
  619.  
  620. if (this.loadingBar)
  621. this.loadingBar.textContent = this._text;
  622. }
  623. get text() {
  624. return this._text;
  625. }
  626.  
  627. set cornerRadius(value) {
  628. if (this._cornerRadius == value) return;
  629. this._cornerRadius = value;
  630.  
  631. if (this.loadingBar)
  632. this.loadingBar.style.borderRadius = this.cornerRadius + "px";
  633. }
  634. get cornerRadius() {
  635. return this._cornerRadius;
  636. }
  637.  
  638. set height(value) {
  639. if (this._height == value) return;
  640. this._height = value;
  641.  
  642. if (this.loadingBar) {
  643. this.loadingBar.style.height = this._height + "px";
  644. this.loadingBar.style.lineHeight = this._height + "px";
  645. }
  646. }
  647. get height() {
  648. return this._height;
  649. }
  650.  
  651. set fontSize(value) {
  652. if (this._fontSize == value) return;
  653. this._fontSize = value;
  654.  
  655. if (this.loadingBar) {
  656. if (this._fontSize)
  657. this.loadingBar.style.fontSize = this._fontSize + "px";
  658. else
  659. this.loadingBar.style.fontSize = "";
  660. }
  661. }
  662. get fontSize() {
  663. return this._fontSize;
  664. }
  665.  
  666. set gradient(value) {
  667. if (this._gradient == value) return;
  668. this._gradient = value;
  669.  
  670. if (this.loadingBar)
  671. this.loadingBar.style.background = this._gradient;
  672. }
  673. get gradient() {
  674. return this._gradient;
  675. }
  676.  
  677. set visible(value) {
  678. if (this._visible == value) return;
  679. this._visible = value;
  680.  
  681. if (this.loadingBar)
  682. this.loadingBar.style.display = this._visible == true ? "block" : "none";
  683. }
  684. get visible() {
  685. return this._visible;
  686. }
  687. }
  688. window.LoadingBar = LoadingBar;
  689. })();