Circle.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. var __defProp = Object.defineProperty;
  2. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  3. var __getOwnPropNames = Object.getOwnPropertyNames;
  4. var __hasOwnProp = Object.prototype.hasOwnProperty;
  5. var __export = (target, all) => {
  6. for (var name2 in all)
  7. __defProp(target, name2, { get: all[name2], enumerable: true });
  8. };
  9. var __copyProps = (to, from, except, desc) => {
  10. if (from && typeof from === "object" || typeof from === "function") {
  11. for (let key of __getOwnPropNames(from))
  12. if (!__hasOwnProp.call(to, key) && key !== except)
  13. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  14. }
  15. return to;
  16. };
  17. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  18. var stdin_exports = {};
  19. __export(stdin_exports, {
  20. circleProps: () => circleProps,
  21. default: () => stdin_default
  22. });
  23. module.exports = __toCommonJS(stdin_exports);
  24. var import_vue = require("vue");
  25. var import_vue2 = require("vue");
  26. var import_use = require("@vant/use");
  27. var import_utils = require("../utils");
  28. const [name, bem] = (0, import_utils.createNamespace)("circle");
  29. let uid = 0;
  30. const format = (rate) => Math.min(Math.max(+rate, 0), 100);
  31. function getPath(clockwise, viewBoxSize) {
  32. const sweepFlag = clockwise ? 1 : 0;
  33. return `M ${viewBoxSize / 2} ${viewBoxSize / 2} m 0, -500 a 500, 500 0 1, ${sweepFlag} 0, 1000 a 500, 500 0 1, ${sweepFlag} 0, -1000`;
  34. }
  35. const circleProps = {
  36. text: String,
  37. size: import_utils.numericProp,
  38. fill: (0, import_utils.makeStringProp)("none"),
  39. rate: (0, import_utils.makeNumericProp)(100),
  40. speed: (0, import_utils.makeNumericProp)(0),
  41. color: [String, Object],
  42. clockwise: import_utils.truthProp,
  43. layerColor: String,
  44. currentRate: (0, import_utils.makeNumberProp)(0),
  45. strokeWidth: (0, import_utils.makeNumericProp)(40),
  46. strokeLinecap: String,
  47. startPosition: (0, import_utils.makeStringProp)("top")
  48. };
  49. var stdin_default = (0, import_vue2.defineComponent)({
  50. name,
  51. props: circleProps,
  52. emits: ["update:currentRate"],
  53. setup(props, {
  54. emit,
  55. slots
  56. }) {
  57. const id = `van-circle-${uid++}`;
  58. const viewBoxSize = (0, import_vue2.computed)(() => +props.strokeWidth + 1e3);
  59. const path = (0, import_vue2.computed)(() => getPath(props.clockwise, viewBoxSize.value));
  60. const svgStyle = (0, import_vue2.computed)(() => {
  61. const ROTATE_ANGLE_MAP = {
  62. top: 0,
  63. right: 90,
  64. bottom: 180,
  65. left: 270
  66. };
  67. const angleValue = ROTATE_ANGLE_MAP[props.startPosition];
  68. if (angleValue) {
  69. return {
  70. transform: `rotate(${angleValue}deg)`
  71. };
  72. }
  73. });
  74. (0, import_vue2.watch)(() => props.rate, (rate) => {
  75. let rafId;
  76. const startTime = Date.now();
  77. const startRate = props.currentRate;
  78. const endRate = format(rate);
  79. const duration = Math.abs((startRate - endRate) * 1e3 / +props.speed);
  80. const animate = () => {
  81. const now = Date.now();
  82. const progress = Math.min((now - startTime) / duration, 1);
  83. const rate2 = progress * (endRate - startRate) + startRate;
  84. emit("update:currentRate", format(parseFloat(rate2.toFixed(1))));
  85. if (endRate > startRate ? rate2 < endRate : rate2 > endRate) {
  86. rafId = (0, import_use.raf)(animate);
  87. }
  88. };
  89. if (props.speed) {
  90. if (rafId) {
  91. (0, import_use.cancelRaf)(rafId);
  92. }
  93. rafId = (0, import_use.raf)(animate);
  94. } else {
  95. emit("update:currentRate", endRate);
  96. }
  97. }, {
  98. immediate: true
  99. });
  100. const renderHover = () => {
  101. const PERIMETER = 3140;
  102. const {
  103. strokeWidth,
  104. currentRate,
  105. strokeLinecap
  106. } = props;
  107. const offset = PERIMETER * currentRate / 100;
  108. const color = (0, import_utils.isObject)(props.color) ? `url(#${id})` : props.color;
  109. const style = {
  110. stroke: color,
  111. strokeWidth: `${+strokeWidth + 1}px`,
  112. strokeLinecap,
  113. strokeDasharray: `${offset}px ${PERIMETER}px`
  114. };
  115. return (0, import_vue.createVNode)("path", {
  116. "d": path.value,
  117. "style": style,
  118. "class": bem("hover"),
  119. "stroke": color
  120. }, null);
  121. };
  122. const renderLayer = () => {
  123. const style = {
  124. fill: props.fill,
  125. stroke: props.layerColor,
  126. strokeWidth: `${props.strokeWidth}px`
  127. };
  128. return (0, import_vue.createVNode)("path", {
  129. "class": bem("layer"),
  130. "style": style,
  131. "d": path.value
  132. }, null);
  133. };
  134. const renderGradient = () => {
  135. const {
  136. color
  137. } = props;
  138. if (!(0, import_utils.isObject)(color)) {
  139. return;
  140. }
  141. const Stops = Object.keys(color).sort((a, b) => parseFloat(a) - parseFloat(b)).map((key, index) => (0, import_vue.createVNode)("stop", {
  142. "key": index,
  143. "offset": key,
  144. "stop-color": color[key]
  145. }, null));
  146. return (0, import_vue.createVNode)("defs", null, [(0, import_vue.createVNode)("linearGradient", {
  147. "id": id,
  148. "x1": "100%",
  149. "y1": "0%",
  150. "x2": "0%",
  151. "y2": "0%"
  152. }, [Stops])]);
  153. };
  154. const renderText = () => {
  155. if (slots.default) {
  156. return slots.default();
  157. }
  158. if (props.text) {
  159. return (0, import_vue.createVNode)("div", {
  160. "class": bem("text")
  161. }, [props.text]);
  162. }
  163. };
  164. return () => (0, import_vue.createVNode)("div", {
  165. "class": bem(),
  166. "style": (0, import_utils.getSizeStyle)(props.size)
  167. }, [(0, import_vue.createVNode)("svg", {
  168. "viewBox": `0 0 ${viewBoxSize.value} ${viewBoxSize.value}`,
  169. "style": svgStyle.value
  170. }, [renderGradient(), renderLayer(), renderHover()]), renderText()]);
  171. }
  172. });