mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-23 18:00:27 +08:00
refactor(Circle): use composition api
This commit is contained in:
parent
8f978addd4
commit
ded5aa431e
@ -1,11 +1,10 @@
|
|||||||
|
import { watch, computed } from 'vue';
|
||||||
import { createNamespace, isObject, addUnit } from '../utils';
|
import { createNamespace, isObject, addUnit } from '../utils';
|
||||||
import { raf, cancelRaf } from '../utils/dom/raf';
|
import { raf, cancelRaf } from '../utils/dom/raf';
|
||||||
import { BLUE, WHITE } from '../utils/constant';
|
import { BLUE, WHITE } from '../utils/constant';
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('circle');
|
const [createComponent, bem] = createNamespace('circle');
|
||||||
|
|
||||||
const PERIMETER = 3140;
|
|
||||||
|
|
||||||
let uid = 0;
|
let uid = 0;
|
||||||
|
|
||||||
function format(rate) {
|
function format(rate) {
|
||||||
@ -63,123 +62,122 @@ export default createComponent({
|
|||||||
|
|
||||||
emits: ['update:currentRate'],
|
emits: ['update:currentRate'],
|
||||||
|
|
||||||
beforeCreate() {
|
setup(props, { emit, slots }) {
|
||||||
this.uid = `van-circle-gradient-${uid++}`;
|
const id = `van-circle-${uid++}`;
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
const viewBoxSize = computed(() => +props.strokeWidth + 1000);
|
||||||
style() {
|
|
||||||
const size = addUnit(this.size);
|
const path = computed(() => getPath(props.clockwise, viewBoxSize.value));
|
||||||
|
|
||||||
|
const rootStyle = computed(() => {
|
||||||
|
const size = addUnit(props.size);
|
||||||
return {
|
return {
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
|
|
||||||
path() {
|
watch(
|
||||||
return getPath(this.clockwise, this.viewBoxSize);
|
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() {
|
const animate = () => {
|
||||||
return +this.strokeWidth + 1000;
|
const now = Date.now();
|
||||||
},
|
const progress = Math.min((now - startTime) / duration, 1);
|
||||||
|
const rate = progress * (endRate - startRate) + startRate;
|
||||||
|
|
||||||
layerStyle() {
|
emit('update:currentRate', format(parseFloat(rate.toFixed(1))));
|
||||||
const offset = (PERIMETER * this.currentRate) / 100;
|
|
||||||
|
|
||||||
return {
|
if (endRate > startRate ? rate < endRate : rate > endRate) {
|
||||||
stroke: `${this.color}`,
|
rafId = raf(animate);
|
||||||
strokeWidth: `${+this.strokeWidth + 1}px`,
|
}
|
||||||
strokeLinecap: this.strokeLinecap,
|
};
|
||||||
|
|
||||||
|
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 <path class={bem('hover')} style={style} d={path.value} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderLayer = () => {
|
||||||
|
const PERIMETER = 3140;
|
||||||
|
const { color, strokeWidth, currentRate, strokeLinecap } = props;
|
||||||
|
const offset = (PERIMETER * currentRate) / 100;
|
||||||
|
const style = {
|
||||||
|
stroke: `${color}`,
|
||||||
|
strokeWidth: `${+strokeWidth + 1}px`,
|
||||||
|
strokeLinecap,
|
||||||
strokeDasharray: `${offset}px ${PERIMETER}px`,
|
strokeDasharray: `${offset}px ${PERIMETER}px`,
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
|
||||||
hoverStyle() {
|
return (
|
||||||
return {
|
<path
|
||||||
fill: `${this.fill}`,
|
d={path.value}
|
||||||
stroke: `${this.layerColor}`,
|
style={style}
|
||||||
strokeWidth: `${this.strokeWidth}px`,
|
class={bem('layer')}
|
||||||
};
|
stroke={isObject(color) ? `url(#${id})` : color}
|
||||||
},
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
gradient() {
|
const renderGradient = () => {
|
||||||
return isObject(this.color);
|
const { color } = props;
|
||||||
},
|
|
||||||
|
|
||||||
LinearGradient() {
|
if (!isObject(color)) {
|
||||||
if (!this.gradient) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Stops = Object.keys(this.color)
|
const Stops = Object.keys(color)
|
||||||
.sort((a, b) => parseFloat(a) - parseFloat(b))
|
.sort((a, b) => parseFloat(a) - parseFloat(b))
|
||||||
.map((key, index) => (
|
.map((key, index) => (
|
||||||
<stop key={index} offset={key} stop-color={this.color[key]} />
|
<stop key={index} offset={key} stop-color={color[key]} />
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id={this.uid} x1="100%" y1="0%" x2="0%" y2="0%">
|
<linearGradient id={id} x1="100%" y1="0%" x2="0%" y2="0%">
|
||||||
{Stops}
|
{Stops}
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
const renderText = () => {
|
||||||
rate: {
|
if (slots.default) {
|
||||||
handler(rate) {
|
return slots.default();
|
||||||
this.startTime = Date.now();
|
|
||||||
this.startRate = this.currentRate;
|
|
||||||
this.endRate = format(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('update:currentRate', 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('update:currentRate', format(parseFloat(rate.toFixed(1))));
|
|
||||||
|
|
||||||
if (this.increase ? rate < this.endRate : rate > this.endRate) {
|
|
||||||
this.rafId = raf(this.animate);
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
if (props.text) {
|
||||||
return (
|
return <div class={bem('text')}>{props.text}</div>;
|
||||||
<div class={bem()} style={this.style}>
|
}
|
||||||
<svg viewBox={`0 0 ${this.viewBoxSize} ${this.viewBoxSize}`}>
|
};
|
||||||
{this.LinearGradient}
|
|
||||||
<path class={bem('hover')} style={this.hoverStyle} d={this.path} />
|
return () => (
|
||||||
<path
|
<div class={bem()} style={rootStyle.value}>
|
||||||
d={this.path}
|
<svg viewBox={`0 0 ${viewBoxSize.value} ${viewBoxSize.value}`}>
|
||||||
class={bem('layer')}
|
{renderGradient()}
|
||||||
style={this.layerStyle}
|
{renderHover()}
|
||||||
stroke={this.gradient ? `url(#${this.uid})` : this.color}
|
{renderLayer()}
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{this.$slots.default
|
{renderText()}
|
||||||
? this.$slots.default()
|
|
||||||
: this.text && <div class={bem('text')}>{this.text}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user