import { watch, computed, defineComponent, createVNode as _createVNode } from "vue"; import { raf, cancelRaf } from "@vant/use"; import { isObject, truthProp, numericProp, getSizeStyle, makeStringProp, makeNumberProp, makeNumericProp, createNamespace } from "../utils/index.mjs"; const [name, bem] = createNamespace("circle"); let uid = 0; const format = (rate) => Math.min(Math.max(+rate, 0), 100); function getPath(clockwise, viewBoxSize) { const sweepFlag = clockwise ? 1 : 0; 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`; } const circleProps = { text: String, size: numericProp, fill: makeStringProp("none"), rate: makeNumericProp(100), speed: makeNumericProp(0), color: [String, Object], clockwise: truthProp, layerColor: String, currentRate: makeNumberProp(0), strokeWidth: makeNumericProp(40), strokeLinecap: String, startPosition: makeStringProp("top") }; var stdin_default = defineComponent({ name, props: circleProps, emits: ["update:currentRate"], setup(props, { emit, slots }) { const id = `van-circle-${uid++}`; const viewBoxSize = computed(() => +props.strokeWidth + 1e3); const path = computed(() => getPath(props.clockwise, viewBoxSize.value)); const svgStyle = computed(() => { const ROTATE_ANGLE_MAP = { top: 0, right: 90, bottom: 180, left: 270 }; const angleValue = ROTATE_ANGLE_MAP[props.startPosition]; if (angleValue) { return { transform: `rotate(${angleValue}deg)` }; } }); watch(() => props.rate, (rate) => { let rafId; const startTime = Date.now(); const startRate = props.currentRate; const endRate = format(rate); const duration = Math.abs((startRate - endRate) * 1e3 / +props.speed); const animate = () => { const now = Date.now(); const progress = Math.min((now - startTime) / duration, 1); const rate2 = progress * (endRate - startRate) + startRate; emit("update:currentRate", format(parseFloat(rate2.toFixed(1)))); if (endRate > startRate ? rate2 < endRate : rate2 > endRate) { rafId = raf(animate); } }; if (props.speed) { if (rafId) { cancelRaf(rafId); } rafId = raf(animate); } else { emit("update:currentRate", endRate); } }, { immediate: true }); const renderHover = () => { const PERIMETER = 3140; const { strokeWidth, currentRate, strokeLinecap } = props; const offset = PERIMETER * currentRate / 100; const color = isObject(props.color) ? `url(#${id})` : props.color; const style = { stroke: color, strokeWidth: `${+strokeWidth + 1}px`, strokeLinecap, strokeDasharray: `${offset}px ${PERIMETER}px` }; return _createVNode("path", { "d": path.value, "style": style, "class": bem("hover"), "stroke": color }, null); }; const renderLayer = () => { const style = { fill: props.fill, stroke: props.layerColor, strokeWidth: `${props.strokeWidth}px` }; return _createVNode("path", { "class": bem("layer"), "style": style, "d": path.value }, null); }; const renderGradient = () => { const { color } = props; if (!isObject(color)) { return; } const Stops = Object.keys(color).sort((a, b) => parseFloat(a) - parseFloat(b)).map((key, index) => _createVNode("stop", { "key": index, "offset": key, "stop-color": color[key] }, null)); return _createVNode("defs", null, [_createVNode("linearGradient", { "id": id, "x1": "100%", "y1": "0%", "x2": "0%", "y2": "0%" }, [Stops])]); }; const renderText = () => { if (slots.default) { return slots.default(); } if (props.text) { return _createVNode("div", { "class": bem("text") }, [props.text]); } }; return () => _createVNode("div", { "class": bem(), "style": getSizeStyle(props.size) }, [_createVNode("svg", { "viewBox": `0 0 ${viewBoxSize.value} ${viewBoxSize.value}`, "style": svgStyle.value }, [renderGradient(), renderLayer(), renderHover()]), renderText()]); } }); export { circleProps, stdin_default as default };