Furaffinity-Loading-Animations

Library for creating different loading animations on Furaffinity

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

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

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