[new feature] add Circle component (#608)

This commit is contained in:
neverland
2018-02-05 17:52:43 +08:00
committed by GitHub
parent 70ce3838a2
commit 41df4b4819
12 changed files with 460 additions and 1 deletions
+126
View File
@@ -0,0 +1,126 @@
<template>
<div class="van-circle" :style="style">
<svg viewBox="0 0 1060 1060">
<path class="van-circle__hover" :style="hoverStyle" :d="path" />
<path class="van-circle__layer" :style="layerStyle" :d="path" />
</svg>
<slot>
<div class="van-circle__text">{{ text }}</div>
</slot>
</div>
</template>
<script>
import { create } from '../utils';
import { raf, cancel } from '../utils/raf';
export default create({
name: 'van-circle',
props: {
text: String,
value: Number,
speed: Number,
size: {
type: String,
default: '100px'
},
fill: {
type: String,
default: 'none'
},
rate: {
type: Number,
default: 100
},
layerColor: {
type: String,
default: '#fff'
},
color: {
type: String,
default: '#38f'
},
strokeWidth: {
type: Number,
default: 40
},
clockwise: {
type: Boolean,
default: true
}
},
beforeCreate() {
this.perimeter = Math.PI * 1000;
this.path = 'M 530 530 m -500, 0 a 500, 500 0 1, 1 1000, 0 a 500, 500 0 1, 1 -1000, 0';
},
computed: {
style() {
return {
width: this.size,
height: this.size
};
},
layerStyle() {
let offset = this.perimeter * (100 - this.value) / 100;
offset = this.clockwise ? offset : this.perimeter * 2 - offset;
return {
stroke: `${this.color}`,
strokeDashoffset: `${offset}px`,
strokeWidth: `${this.strokeWidth + 1}px`
};
},
hoverStyle() {
return {
fill: `${this.fill}`,
stroke: `${this.layerColor}`,
strokeWidth: `${this.strokeWidth}px`
};
}
},
mounted() {
this.render();
},
watch: {
rate() {
this.render();
}
},
methods: {
render() {
this.startTime = Date.now();
this.startRate = this.value;
this.endRate = this.format(this.rate);
this.increase = this.endRate > this.startRate;
this.duration = Math.abs((this.startRate - this.endRate) * 1000 / this.speed);
if (this.speed) {
cancel(this.rafId);
this.rafId = raf(this.animate);
} else {
this.$emit('input', this.endRate);
}
},
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', this.format(parseFloat(rate.toFixed(1))));
if (this.increase ? rate < this.endRate : rate > this.endRate) {
this.rafId = raf(this.animate);
}
},
format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
}
});
</script>
+3
View File
@@ -12,6 +12,7 @@ import CellGroup from './cell-group';
import CellSwipe from './cell-swipe';
import Checkbox from './checkbox';
import CheckboxGroup from './checkbox-group';
import Circle from './circle';
import Col from './col';
import ContactCard from './contact-card';
import ContactEdit from './contact-edit';
@@ -77,6 +78,7 @@ const components = [
CellSwipe,
Checkbox,
CheckboxGroup,
Circle,
Col,
ContactCard,
ContactEdit,
@@ -149,6 +151,7 @@ export {
CellSwipe,
Checkbox,
CheckboxGroup,
Circle,
Col,
ContactCard,
ContactEdit,
+32
View File
@@ -0,0 +1,32 @@
@import './common/var.css';
.van-circle {
position: relative;
text-align: center;
display: inline-block;
svg {
top: 0;
left: 0;
width: 100%;
height: 100%;
position: absolute;
}
&__layer {
fill: none;
stroke-dasharray: 3140px;
stroke-dashoffset: 3140px;
transform: rotate(90deg);
transform-origin: 530px 530px;
}
&__text {
top: 50%;
left: 0;
width: 100%;
color: $text-color;
position: absolute;
transform: translateY(-50%);
}
}
+2 -1
View File
@@ -12,7 +12,7 @@
@import './badge.css';
@import './button.css';
@import './cell.css';
@import './card.css';
@import './circle.css';
@import './loading.css';
@import './nav-bar.css';
@import './notice-bar.css';
@@ -53,6 +53,7 @@
/* business components */
@import './address-edit.css';
@import './address-list.css';
@import './card.css';
@import './contact-card.css';
@import './contact-list.css';
@import './contact-edit.css';