[new feature] Circle: support gradient color (#4157)

This commit is contained in:
neverland
2019-08-20 10:27:14 +08:00
committed by GitHub
parent a3712f7c5b
commit b7244f8fa9
8 changed files with 346 additions and 64 deletions
+53 -9
View File
@@ -1,15 +1,22 @@
import { createNamespace } from '../utils';
import { createNamespace, isObj } from '../utils';
import { raf, cancelRaf } from '../utils/dom/raf';
import { BLUE, WHITE } from '../utils/constant';
const [createComponent, bem] = createNamespace('circle');
const PERIMETER = 3140;
const PATH = 'M 530 530 m -500, 0 a 500, 500 0 1, 1 1000, 0 a 500, 500 0 1, 1 -1000, 0';
let uid = 0;
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
function getPath(clockwise) {
const sweepFlag = clockwise ? 1 : 0;
return `M 530 530 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,
@@ -38,7 +45,7 @@ export default createComponent({
default: WHITE
},
color: {
type: String,
type: [String, Object],
default: BLUE
},
strokeWidth: {
@@ -51,6 +58,10 @@ export default createComponent({
}
},
beforeCreate() {
this.uid = `van-circle-gradient-${uid++}`;
},
computed: {
style() {
return {
@@ -59,14 +70,17 @@ export default createComponent({
};
},
path() {
return getPath(this.clockwise);
},
layerStyle() {
let offset = (PERIMETER * (100 - this.value)) / 100;
offset = this.clockwise ? offset : PERIMETER * 2 - offset;
const offset = (PERIMETER * this.value) / 100;
return {
stroke: `${this.color}`,
strokeDashoffset: `${offset}px`,
strokeWidth: `${this.strokeWidth + 1}px`
strokeWidth: `${this.strokeWidth + 1}px`,
strokeDasharray: `${offset}px ${PERIMETER}px`
};
},
@@ -76,6 +90,30 @@ export default createComponent({
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) => (
<stop key={index} offset={key} stop-color={this.color[key]} />
));
return (
<defs>
<linearGradient id={this.uid} x1="100%" y1="0%" x2="0%" y2="0%">
{Stops}
</linearGradient>
</defs>
);
}
},
@@ -116,8 +154,14 @@ export default createComponent({
return (
<div class={bem()} style={this.style}>
<svg viewBox="0 0 1060 1060">
<path class={bem('hover')} style={this.hoverStyle} d={PATH} />
<path class={bem('layer')} style={this.layerStyle} d={PATH} />
{this.LinearGradient}
<path class={bem('hover')} style={this.hoverStyle} d={this.path} />
<path
d={this.path}
class={bem('layer')}
style={this.layerStyle}
stroke={this.gradient ? `url(#${this.uid})` : this.color}
/>
</svg>
{this.slots() || (this.text && <div class={bem('text')}>{this.text}</div>)}
</div>