progress.mjs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import { defineComponent, computed, openBlock, createElementBlock, normalizeClass, unref, createElementVNode, normalizeStyle, renderSlot, toDisplayString, createCommentVNode, createBlock, withCtx, resolveDynamicComponent } from 'vue';
  2. import { ElIcon } from '../../icon/index.mjs';
  3. import { WarningFilled, CircleCheck, CircleClose, Check, Close } from '@element-plus/icons-vue';
  4. import { progressProps } from './progress2.mjs';
  5. import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
  6. import { useNamespace } from '../../../hooks/use-namespace/index.mjs';
  7. import { isFunction, isString } from '@vue/shared';
  8. const _hoisted_1 = ["aria-valuenow"];
  9. const _hoisted_2 = { viewBox: "0 0 100 100" };
  10. const _hoisted_3 = ["d", "stroke", "stroke-linecap", "stroke-width"];
  11. const _hoisted_4 = ["d", "stroke", "opacity", "stroke-linecap", "stroke-width"];
  12. const _hoisted_5 = { key: 0 };
  13. const _sfc_main = defineComponent({
  14. ...{
  15. name: "ElProgress"
  16. },
  17. __name: "progress",
  18. props: progressProps,
  19. setup(__props) {
  20. const STATUS_COLOR_MAP = {
  21. success: "#13ce66",
  22. exception: "#ff4949",
  23. warning: "#e6a23c",
  24. default: "#20a0ff"
  25. };
  26. const props = __props;
  27. const ns = useNamespace("progress");
  28. const barStyle = computed(() => {
  29. const barStyle2 = {
  30. width: `${props.percentage}%`,
  31. animationDuration: `${props.duration}s`
  32. };
  33. const color = getCurrentColor(props.percentage);
  34. if (color.includes("gradient")) {
  35. barStyle2.background = color;
  36. } else {
  37. barStyle2.backgroundColor = color;
  38. }
  39. return barStyle2;
  40. });
  41. const relativeStrokeWidth = computed(
  42. () => (props.strokeWidth / props.width * 100).toFixed(1)
  43. );
  44. const radius = computed(() => {
  45. if (["circle", "dashboard"].includes(props.type)) {
  46. return Number.parseInt(
  47. `${50 - Number.parseFloat(relativeStrokeWidth.value) / 2}`,
  48. 10
  49. );
  50. }
  51. return 0;
  52. });
  53. const trackPath = computed(() => {
  54. const r = radius.value;
  55. const isDashboard = props.type === "dashboard";
  56. return `
  57. M 50 50
  58. m 0 ${isDashboard ? "" : "-"}${r}
  59. a ${r} ${r} 0 1 1 0 ${isDashboard ? "-" : ""}${r * 2}
  60. a ${r} ${r} 0 1 1 0 ${isDashboard ? "" : "-"}${r * 2}
  61. `;
  62. });
  63. const perimeter = computed(() => 2 * Math.PI * radius.value);
  64. const rate = computed(() => props.type === "dashboard" ? 0.75 : 1);
  65. const strokeDashoffset = computed(() => {
  66. const offset = -1 * perimeter.value * (1 - rate.value) / 2;
  67. return `${offset}px`;
  68. });
  69. const trailPathStyle = computed(() => ({
  70. strokeDasharray: `${perimeter.value * rate.value}px, ${perimeter.value}px`,
  71. strokeDashoffset: strokeDashoffset.value
  72. }));
  73. const circlePathStyle = computed(() => ({
  74. strokeDasharray: `${perimeter.value * rate.value * (props.percentage / 100)}px, ${perimeter.value}px`,
  75. strokeDashoffset: strokeDashoffset.value,
  76. transition: "stroke-dasharray 0.6s ease 0s, stroke 0.6s ease, opacity ease 0.6s"
  77. }));
  78. const stroke = computed(() => {
  79. let ret;
  80. if (props.color) {
  81. ret = getCurrentColor(props.percentage);
  82. } else {
  83. ret = STATUS_COLOR_MAP[props.status] || STATUS_COLOR_MAP.default;
  84. }
  85. return ret;
  86. });
  87. const statusIcon = computed(() => {
  88. if (props.status === "warning") {
  89. return WarningFilled;
  90. }
  91. if (props.type === "line") {
  92. return props.status === "success" ? CircleCheck : CircleClose;
  93. } else {
  94. return props.status === "success" ? Check : Close;
  95. }
  96. });
  97. const progressTextSize = computed(() => {
  98. return props.type === "line" ? 12 + props.strokeWidth * 0.4 : props.width * 0.111111 + 2;
  99. });
  100. const content = computed(() => props.format(props.percentage));
  101. function getColors(color) {
  102. const span = 100 / color.length;
  103. const seriesColors = color.map((seriesColor, index) => {
  104. if (isString(seriesColor)) {
  105. return {
  106. color: seriesColor,
  107. percentage: (index + 1) * span
  108. };
  109. }
  110. return seriesColor;
  111. });
  112. return seriesColors.sort((a, b) => a.percentage - b.percentage);
  113. }
  114. const getCurrentColor = (percentage) => {
  115. var _a;
  116. const { color } = props;
  117. if (isFunction(color)) {
  118. return color(percentage);
  119. } else if (isString(color)) {
  120. return color;
  121. } else {
  122. const colors = getColors(color);
  123. for (const color2 of colors) {
  124. if (color2.percentage > percentage)
  125. return color2.color;
  126. }
  127. return (_a = colors[colors.length - 1]) == null ? void 0 : _a.color;
  128. }
  129. };
  130. return (_ctx, _cache) => {
  131. return openBlock(), createElementBlock("div", {
  132. class: normalizeClass([
  133. unref(ns).b(),
  134. unref(ns).m(_ctx.type),
  135. unref(ns).is(_ctx.status),
  136. {
  137. [unref(ns).m("without-text")]: !_ctx.showText,
  138. [unref(ns).m("text-inside")]: _ctx.textInside
  139. }
  140. ]),
  141. role: "progressbar",
  142. "aria-valuenow": _ctx.percentage,
  143. "aria-valuemin": "0",
  144. "aria-valuemax": "100"
  145. }, [
  146. _ctx.type === "line" ? (openBlock(), createElementBlock(
  147. "div",
  148. {
  149. key: 0,
  150. class: normalizeClass(unref(ns).b("bar"))
  151. },
  152. [
  153. createElementVNode(
  154. "div",
  155. {
  156. class: normalizeClass(unref(ns).be("bar", "outer")),
  157. style: normalizeStyle({ height: `${_ctx.strokeWidth}px` })
  158. },
  159. [
  160. createElementVNode(
  161. "div",
  162. {
  163. class: normalizeClass([
  164. unref(ns).be("bar", "inner"),
  165. { [unref(ns).bem("bar", "inner", "indeterminate")]: _ctx.indeterminate },
  166. { [unref(ns).bem("bar", "inner", "striped")]: _ctx.striped },
  167. { [unref(ns).bem("bar", "inner", "striped-flow")]: _ctx.stripedFlow }
  168. ]),
  169. style: normalizeStyle(barStyle.value)
  170. },
  171. [
  172. (_ctx.showText || _ctx.$slots.default) && _ctx.textInside ? (openBlock(), createElementBlock(
  173. "div",
  174. {
  175. key: 0,
  176. class: normalizeClass(unref(ns).be("bar", "innerText"))
  177. },
  178. [
  179. renderSlot(_ctx.$slots, "default", { percentage: _ctx.percentage }, () => [
  180. createElementVNode(
  181. "span",
  182. null,
  183. toDisplayString(content.value),
  184. 1
  185. )
  186. ])
  187. ],
  188. 2
  189. )) : createCommentVNode("v-if", true)
  190. ],
  191. 6
  192. )
  193. ],
  194. 6
  195. )
  196. ],
  197. 2
  198. )) : (openBlock(), createElementBlock(
  199. "div",
  200. {
  201. key: 1,
  202. class: normalizeClass(unref(ns).b("circle")),
  203. style: normalizeStyle({ height: `${_ctx.width}px`, width: `${_ctx.width}px` })
  204. },
  205. [
  206. (openBlock(), createElementBlock("svg", _hoisted_2, [
  207. createElementVNode("path", {
  208. class: normalizeClass(unref(ns).be("circle", "track")),
  209. d: trackPath.value,
  210. stroke: `var(${unref(ns).cssVarName("fill-color-light")}, #e5e9f2)`,
  211. "stroke-linecap": _ctx.strokeLinecap,
  212. "stroke-width": relativeStrokeWidth.value,
  213. fill: "none",
  214. style: normalizeStyle(trailPathStyle.value)
  215. }, null, 14, _hoisted_3),
  216. createElementVNode("path", {
  217. class: normalizeClass(unref(ns).be("circle", "path")),
  218. d: trackPath.value,
  219. stroke: stroke.value,
  220. fill: "none",
  221. opacity: _ctx.percentage ? 1 : 0,
  222. "stroke-linecap": _ctx.strokeLinecap,
  223. "stroke-width": relativeStrokeWidth.value,
  224. style: normalizeStyle(circlePathStyle.value)
  225. }, null, 14, _hoisted_4)
  226. ]))
  227. ],
  228. 6
  229. )),
  230. (_ctx.showText || _ctx.$slots.default) && !_ctx.textInside ? (openBlock(), createElementBlock(
  231. "div",
  232. {
  233. key: 2,
  234. class: normalizeClass(unref(ns).e("text")),
  235. style: normalizeStyle({ fontSize: `${progressTextSize.value}px` })
  236. },
  237. [
  238. renderSlot(_ctx.$slots, "default", { percentage: _ctx.percentage }, () => [
  239. !_ctx.status ? (openBlock(), createElementBlock(
  240. "span",
  241. _hoisted_5,
  242. toDisplayString(content.value),
  243. 1
  244. )) : (openBlock(), createBlock(unref(ElIcon), { key: 1 }, {
  245. default: withCtx(() => [
  246. (openBlock(), createBlock(resolveDynamicComponent(statusIcon.value)))
  247. ]),
  248. _: 1
  249. }))
  250. ])
  251. ],
  252. 6
  253. )) : createCommentVNode("v-if", true)
  254. ], 10, _hoisted_1);
  255. };
  256. }
  257. });
  258. var Progress = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "/home/runner/work/element-plus/element-plus/packages/components/progress/src/progress.vue"]]);
  259. export { Progress as default };
  260. //# sourceMappingURL=progress.mjs.map