import { createNamespace, isObj, addUnit } from '../utils'; import { raf, cancelRaf } from '../utils/dom/raf'; import { BLUE, WHITE } from '../utils/constant'; const [createComponent, bem] = createNamespace('circle'); const PERIMETER = 3140; let uid = 0; function format(rate) { return 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`; } export default createComponent({ props: { text: String, value: { type: Number, default: 0 }, speed: { type: Number, default: 0 }, size: { type: [String, Number], default: 100 }, fill: { type: String, default: 'none' }, rate: { type: Number, default: 100 }, layerColor: { type: String, default: WHITE }, color: { type: [String, Object], default: BLUE }, strokeWidth: { type: Number, default: 40 }, clockwise: { type: Boolean, default: true } }, beforeCreate() { this.uid = `van-circle-gradient-${uid++}`; }, computed: { style() { const size = addUnit(this.size); return { width: size, height: size }; }, path() { return getPath(this.clockwise, this.viewBoxSize); }, viewBoxSize() { return 1000 + this.strokeWidth; }, layerStyle() { const offset = (PERIMETER * this.value) / 100; return { stroke: `${this.color}`, strokeWidth: `${this.strokeWidth + 1}px`, strokeDasharray: `${offset}px ${PERIMETER}px` }; }, hoverStyle() { return { fill: `${this.fill}`, stroke: `${this.layerColor}`, strokeWidth: `${this.strokeWidth}px` }; }, gradient() { return isObj(this.color); }, LinearGradient() { if (!this.gradient) { return; } const Stops = Object.keys(this.color) .sort((a, b) => parseFloat(a) - parseFloat(b)) .map((key, index) => ( )); return ( {Stops} ); } }, watch: { rate: { handler() { this.startTime = Date.now(); this.startRate = this.value; this.endRate = format(this.rate); this.increase = this.endRate > this.startRate; this.duration = Math.abs(((this.startRate - this.endRate) * 1000) / this.speed); if (this.speed) { cancelRaf(this.rafId); this.rafId = raf(this.animate); } else { this.$emit('input', this.endRate); } }, immediate: true } }, methods: { animate() { const now = Date.now(); const progress = Math.min((now - this.startTime) / this.duration, 1); const rate = progress * (this.endRate - this.startRate) + this.startRate; this.$emit('input', format(parseFloat(rate.toFixed(1)))); if (this.increase ? rate < this.endRate : rate > this.endRate) { this.rafId = raf(this.animate); } } }, render() { return (
{this.LinearGradient} {this.slots() || (this.text &&
{this.text}
)}
); } });