diff --git a/src/circle/index.js b/src/circle/index.js
index 0f11ef480..c0970386a 100644
--- a/src/circle/index.js
+++ b/src/circle/index.js
@@ -1,11 +1,10 @@
+import { watch, computed } from 'vue';
import { createNamespace, isObject, 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) {
@@ -63,123 +62,122 @@ export default createComponent({
emits: ['update:currentRate'],
- beforeCreate() {
- this.uid = `van-circle-gradient-${uid++}`;
- },
+ setup(props, { emit, slots }) {
+ const id = `van-circle-${uid++}`;
- computed: {
- style() {
- const size = addUnit(this.size);
+ const viewBoxSize = computed(() => +props.strokeWidth + 1000);
+
+ const path = computed(() => getPath(props.clockwise, viewBoxSize.value));
+
+ const rootStyle = computed(() => {
+ const size = addUnit(props.size);
return {
width: size,
height: size,
};
- },
+ });
- path() {
- return getPath(this.clockwise, this.viewBoxSize);
- },
+ watch(
+ computed(() => props.rate),
+ (rate) => {
+ let rafId;
+ const startTime = Date.now();
+ const startRate = props.currentRate;
+ const endRate = format(rate);
+ const duration = Math.abs(((startRate - endRate) * 1000) / props.speed);
- viewBoxSize() {
- return +this.strokeWidth + 1000;
- },
+ const animate = () => {
+ const now = Date.now();
+ const progress = Math.min((now - startTime) / duration, 1);
+ const rate = progress * (endRate - startRate) + startRate;
- layerStyle() {
- const offset = (PERIMETER * this.currentRate) / 100;
+ emit('update:currentRate', format(parseFloat(rate.toFixed(1))));
- return {
- stroke: `${this.color}`,
- strokeWidth: `${+this.strokeWidth + 1}px`,
- strokeLinecap: this.strokeLinecap,
+ if (endRate > startRate ? rate < endRate : rate > endRate) {
+ rafId = raf(animate);
+ }
+ };
+
+ if (props.speed) {
+ cancelRaf(rafId);
+ rafId = raf(animate);
+ } else {
+ emit('update:currentRate', endRate);
+ }
+ }
+ );
+
+ const renderHover = () => {
+ const style = {
+ fill: props.fill,
+ stroke: props.layerColor,
+ strokeWidth: `${props.strokeWidth}px`,
+ };
+
+ return