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.

163 lines
3.5 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
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: 16px;
  94. margin: 0.5px 0;
  95. }
  96. div.bar > div {
  97. flex-grow: 1;
  98. flex-basis: 0;
  99. display: inline-block;
  100. box-sizing: border-box;
  101. margin: 0 0.5px;
  102. border: 0.25px solid #111;
  103. }
  104. div.non-segmented {
  105. flex-grow: inherit;
  106. flex-basis: inherit;
  107. }
  108. div.on {
  109. opacity: 0.75;
  110. }
  111. div.none { background-color: #555555; }
  112. div.bronze { background-color: #f4b083; }
  113. div.silver { background-color: #d8dce4; opacity: 0.8; }
  114. div.gold { background-color: #ffd966; opacity: 0.8; }
  115. div.diamond { background-color: #84f5ff; opacity: 0.9; }
  116. div.emerald, div.green { background-color: #8ef88e; opacity: 0.8; }
  117. div.gray { background-color: #777777; }
  118. div.off {
  119. opacity: 0.50;
  120. }
  121. div.bar.thin {
  122. height: 3px;
  123. }
  124. div.bar.thinner {
  125. height: 1px;
  126. }
  127. div.bar.thinner div {
  128. border-bottom: none;
  129. border-top: none;
  130. }
  131. div.bar.thinner div.none {
  132. background-color: #111111;
  133. }
  134. @media screen and (min-width: 1200) {
  135. div.bar div {
  136. margin: 1px 1px;
  137. }
  138. div.bar.thin {
  139. height: 4px;
  140. }
  141. div.bar.thinner {
  142. height: 4px;
  143. }
  144. }
  145. </style>