You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.2 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <script lang="ts" context="module">
  2. const COLORS = [
  3. "none",
  4. "bronze",
  5. "silver",
  6. "gold",
  7. "emerald",
  8. "diamond"
  9. ]
  10. </script>
  11. <script lang="ts">
  12. export let target = 1;
  13. export let count = 0;
  14. export let green = false;
  15. export let thin = false;
  16. export let thinner = false;
  17. export let gray = false;
  18. export let titlePercentageOnly = false;
  19. export let titleTime = false;
  20. let offClass = COLORS[0];
  21. let onClass = COLORS[1];
  22. let ons = 0;
  23. let offs = 1;
  24. let nonSegmented = false;
  25. let title = "";
  26. $: {
  27. let level = Math.floor(count / target);
  28. if (level >= COLORS.length - 1 || (level > 1 && green)) {
  29. offs = 0;
  30. ons = target;
  31. offClass = "gold";
  32. onClass = "diamond";
  33. } else {
  34. if (count > 0 && count == (level * target)) {
  35. level -= 1;
  36. }
  37. ons = count - (level * target);
  38. offs = target - ons;
  39. offClass = COLORS[level];
  40. onClass = COLORS[level + 1];
  41. }
  42. if (green) {
  43. onClass = "green"
  44. offClass = "none"
  45. }
  46. if (gray) {
  47. onClass = "gray"
  48. offClass = "none"
  49. }
  50. // Mark it non-segmented if the target is too high. This prevents a clunky progress bar,
  51. // or a browser freeze if you set the target very high.
  52. nonSegmented = (target >= 50);
  53. }
  54. $: {
  55. const percentage = ((count / target) * 100).toFixed(0);
  56. if (titlePercentageOnly) {
  57. title = `${percentage}%`;
  58. } else if (titleTime) {
  59. let unit = "days";
  60. let progressTime = (count / 86400000);
  61. let totaltTime = (target / 86400000);
  62. if (totaltTime < 1) {
  63. unit = "hours";
  64. totaltTime *= 24;
  65. progressTime *= 24;
  66. }
  67. title = `${progressTime.toFixed(1)} / ${totaltTime.toFixed(1)} ${unit} (${percentage}%)`;
  68. } else {
  69. title = `${count} / ${target} (${percentage}%)`
  70. }
  71. }
  72. </script>
  73. <div class="bar" title="{title}" class:thin class:thinner>
  74. {#if nonSegmented}
  75. <div style="flex: {ons}" class={"non-segmented on " + onClass}></div>
  76. <div style="flex: {offs}" class={"non-segmented off " + offClass}></div>
  77. {:else}
  78. {#each {length: ons} as _}
  79. <div class={"on " + onClass}></div>
  80. {/each}
  81. {#each {length: offs} as _}
  82. <div class={"off " + offClass}></div>
  83. {/each}
  84. {/if}
  85. </div>
  86. <style>
  87. div.bar {
  88. display: flex;
  89. flex-direction: row;
  90. margin: 0;
  91. box-sizing: border-box;
  92. width: 100%;
  93. height: 1em;
  94. }
  95. div.bar > div {
  96. flex-grow: 1;
  97. flex-basis: 0;
  98. display: inline-block;
  99. box-sizing: border-box;
  100. border: 1px solid #111;
  101. }
  102. div.non-segmented {
  103. flex-grow: inherit;
  104. flex-basis: inherit;
  105. }
  106. div.on {
  107. opacity: 0.75;
  108. }
  109. div.none { background-color: #555555; }
  110. div.bronze { background-color: #f4b083; }
  111. div.silver { background-color: #d8dce4; opacity: 0.8; }
  112. div.gold { background-color: #ffd966; opacity: 0.8; }
  113. div.diamond { background-color: #84f5ff; opacity: 0.9; }
  114. div.emerald, div.green { background-color: #8ef88e; opacity: 0.8; }
  115. div.gray { background-color: #777777; }
  116. div.off {
  117. opacity: 0.50;
  118. }
  119. div.bar.thin {
  120. height: 0.25em;
  121. }
  122. div.bar.thinner {
  123. height: 0.125em;
  124. }
  125. div.bar.thinner div.none {
  126. background-color: #111111;
  127. }
  128. </style>