4 changed files with 0 additions and 221 deletions
Split View
Diff Options
-
199components/circle/index.js
-
3components/circle/index.json
-
6components/circle/index.wxml
-
13components/circle/index.wxss
@ -1,199 +0,0 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
const toAngle = (a) => a / 180 * Math.PI |
|||
const percent = (a) => toAngle(a / 100 * 360) |
|||
const easeInOutCubic = (a, b, c, d) => { |
|||
a /= d / 2 |
|||
if (a < 1) return c / 2 * a * a * a + b |
|||
a -= 2 |
|||
return c / 2 * (a * a * a + 2) + b |
|||
} |
|||
|
|||
baseComponent({ |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-circle', |
|||
}, |
|||
percent: { |
|||
type: Number, |
|||
value: 0, |
|||
observer: 'redraw', |
|||
}, |
|||
strokeWidth: { |
|||
type: Number, |
|||
value: 10, |
|||
}, |
|||
size: { |
|||
type: Number, |
|||
value: 120, |
|||
observer: 'updateStyle', |
|||
}, |
|||
lineCap: { |
|||
type: String, |
|||
value: 'round', |
|||
}, |
|||
backgroundColor: { |
|||
type: String, |
|||
value: '#f3f3f3', |
|||
}, |
|||
color: { |
|||
type: String, |
|||
value: '#33cd5f', |
|||
}, |
|||
sAngle: { |
|||
type: Number, |
|||
value: 0, |
|||
observer(newVal) { |
|||
this.setData({ |
|||
beginAngle: toAngle(newVal), |
|||
}) |
|||
}, |
|||
}, |
|||
counterclockwise: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
speed: { |
|||
type: Number, |
|||
value: 2000, |
|||
}, |
|||
animate: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
background: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
}, |
|||
data: { |
|||
beginAngle: 0, |
|||
startAngle: 0, |
|||
endAngle: 0, |
|||
currentAngle: 0, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls', function(prefixCls) { |
|||
const wrap = classNames(prefixCls) |
|||
const inner = `${prefixCls}__inner` |
|||
|
|||
return { |
|||
wrap, |
|||
inner, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 更新样式 |
|||
*/ |
|||
updateStyle(size = this.data.size) { |
|||
const style = `width: ${size}px; height: ${size}px;` |
|||
|
|||
this.setData({ |
|||
style, |
|||
}) |
|||
}, |
|||
/** |
|||
* 着帧绘制 canvas |
|||
*/ |
|||
redraw(value = this.data.percent) { |
|||
const endAngle = percent(value) |
|||
const now = Date.now() |
|||
const decrease = this.data.currentAngle > endAngle |
|||
const startAngle = !decrease ? this.data.currentAngle : this.data.endAngle |
|||
|
|||
this.cancelNextCallback() |
|||
this.clearTimer() |
|||
|
|||
this.safeSetData({ startAngle, endAngle }, () => { |
|||
this.animate(now, now, decrease) |
|||
}) |
|||
}, |
|||
/** |
|||
* 绘制 canvas |
|||
*/ |
|||
draw(line = true) { |
|||
const { lineCap, backgroundColor, color, size, strokeWidth, counterclockwise, background } = this.data |
|||
const position = size / 2 |
|||
const radius = position - strokeWidth / 2 |
|||
const p = 2 * Math.PI |
|||
const startAngle = counterclockwise ? p - this.data.beginAngle : this.data.beginAngle |
|||
const endAngle = counterclockwise ? p - (this.data.beginAngle + this.data.currentAngle) : this.data.beginAngle + this.data.currentAngle |
|||
|
|||
// 创建 canvas 绘图上下文
|
|||
this.ctx = this.ctx || wx.createCanvasContext('circle', this) |
|||
|
|||
// 清除画布
|
|||
this.ctx.clearRect(0, 0, size, size) |
|||
|
|||
// 绘制背景
|
|||
if (background) { |
|||
this.ctx.beginPath() |
|||
this.ctx.arc(position, position, radius, 0, 2 * Math.PI) |
|||
this.ctx.setLineWidth(strokeWidth) |
|||
this.ctx.setStrokeStyle(backgroundColor) |
|||
this.ctx.stroke() |
|||
} |
|||
|
|||
// 绘制进度
|
|||
if (line) { |
|||
this.ctx.beginPath() |
|||
this.ctx.arc(position, position, radius, startAngle, endAngle) |
|||
this.ctx.setLineWidth(strokeWidth) |
|||
this.ctx.setStrokeStyle(color) |
|||
this.ctx.setLineCap(lineCap) |
|||
this.ctx.stroke() |
|||
} |
|||
|
|||
// 绘制完成
|
|||
this.ctx.draw(false, () => { |
|||
this.triggerEvent('change', { value: this.data.currentAngle }) |
|||
}) |
|||
}, |
|||
/** |
|||
* 开始动画 |
|||
*/ |
|||
animate(c, d, e) { |
|||
const now = Date.now() |
|||
const f = now - c < 1 ? 1 : now - c |
|||
const { animate, speed, startAngle, endAngle } = this.data |
|||
const isEnd = !e && 1000 * this.data.currentAngle <= Math.floor(1000 * endAngle) || e && 1000 * this.data.currentAngle >= Math.floor(1000 * endAngle) |
|||
|
|||
if (animate && c - d < 1.05 * speed && isEnd) { |
|||
const value = easeInOutCubic((c - d) / f, startAngle, endAngle - startAngle, speed / f) |
|||
const currentAngle = value < 0 ? 0 : value |
|||
|
|||
c = Date.now() |
|||
|
|||
this.safeSetData({ currentAngle }, () => { |
|||
this.draw(currentAngle !== 0) |
|||
this.timer = setTimeout(() => this.animate(c, d, e), 1000 / 60) |
|||
}) |
|||
} else { |
|||
this.safeSetData({ currentAngle: endAngle }, () => this.draw(endAngle !== 0)) |
|||
} |
|||
}, |
|||
/** |
|||
* 清除定时器 |
|||
*/ |
|||
clearTimer() { |
|||
if (this.timer) { |
|||
clearTimeout(this.timer) |
|||
this.timer = null |
|||
} |
|||
}, |
|||
}, |
|||
attached() { |
|||
this.updateStyle() |
|||
if (this.data.percent === 0) { |
|||
this.draw(false) |
|||
} |
|||
}, |
|||
detached() { |
|||
this.ctx = null |
|||
this.clearTimer() |
|||
}, |
|||
}) |
|||
@ -1,3 +0,0 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -1,6 +0,0 @@ |
|||
<view class="wux-class {{ classes.wrap }}" style="{{ style }}"> |
|||
<canvas style="{{ style }}" canvas-id="circle" /> |
|||
<view class="{{ classes.inner }}"> |
|||
<slot></slot> |
|||
</view> |
|||
</view> |
|||
@ -1,13 +0,0 @@ |
|||
.wux-circle { |
|||
display: inline-block; |
|||
position: relative |
|||
} |
|||
.wux-circle__inner { |
|||
width: 100%; |
|||
text-align: center; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 50%; |
|||
transform: translate3d(0,-50%,0); |
|||
line-height: 1 |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save