进度条组件完成重构
parent
3da409d97c
commit
15757f9f7a
|
@ -6,7 +6,18 @@
|
||||||
|
|
||||||
import { css, html, Component, styleMap } from 'wkit'
|
import { css, html, Component, styleMap } from 'wkit'
|
||||||
|
|
||||||
const RADIUS = 50
|
const TYPE_LINE = 'line'
|
||||||
|
const TYPE_CIRCLE = 'circle'
|
||||||
|
const TYPE_DASHBOARD = 'dashboard'
|
||||||
|
|
||||||
|
const RADIUS = 50 // 半径
|
||||||
|
const PERIMETER = 2 * Math.PI * RADIUS // 周长 2*兀*R
|
||||||
|
|
||||||
|
const OFFSET = { circle: 0, dashboard: (-0.25 * PERIMETER) / 2 + 'px' }
|
||||||
|
const DASH_ARRAY = {
|
||||||
|
circle: `${PERIMETER}px, ${PERIMETER}px`,
|
||||||
|
dashboard: `${PERIMETER * 0.75}px, ${PERIMETER}px`
|
||||||
|
}
|
||||||
|
|
||||||
class Progress extends Component {
|
class Progress extends Component {
|
||||||
static props = {
|
static props = {
|
||||||
|
@ -17,7 +28,7 @@ class Progress extends Component {
|
||||||
this.value = this.#fix(val)
|
this.value = this.#fix(val)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
type: 'line' // line/circle/dashboard
|
type: TYPE_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
|
@ -31,6 +42,8 @@ class Progress extends Component {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
--line-width: var(--wc-progress-line-width, 6px);
|
||||||
|
--base-color: var(--wc-progress-inactive-color, var(--color-plain-2));
|
||||||
|
|
||||||
&[step='1'] {
|
&[step='1'] {
|
||||||
--wc-progress-active-color: var(--wc-progress-active-color-1);
|
--wc-progress-active-color: var(--wc-progress-active-color-1);
|
||||||
|
@ -90,13 +103,13 @@ class Progress extends Component {
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--wc-progress-line-width, 6px);
|
height: var(--line-width);
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
background: var(--wc-progress-inactive-color, var(--color-plain-2));
|
background: var(--base-color);
|
||||||
|
|
||||||
.thumb {
|
.thumb {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: var(--wc-progress-line-width, 6px);
|
height: var(--line-width);
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
background: var(--wc-progress-active-color, var(--color-teal-1));
|
background: var(--wc-progress-active-color, var(--color-teal-1));
|
||||||
transition: 0.6s ease;
|
transition: 0.6s ease;
|
||||||
|
@ -110,45 +123,39 @@ class Progress extends Component {
|
||||||
:host([type='dashboard']) {
|
:host([type='dashboard']) {
|
||||||
width: var(--wc-progress-size, 128px);
|
width: var(--wc-progress-size, 128px);
|
||||||
height: var(--wc-progress-size, 128px);
|
height: var(--wc-progress-size, 128px);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
color: var(--wc-progress-active-color);
|
||||||
|
}
|
||||||
|
path {
|
||||||
|
fill: none;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-width: var(--line-width);
|
||||||
|
transition: stroke-dasharray 0.6s ease 0s, stroke 0.6s ease;
|
||||||
|
}
|
||||||
|
text {
|
||||||
|
font-size: calc(var(--line-width) * 4.5);
|
||||||
|
fill: currentColor;
|
||||||
|
text-anchor: middle;
|
||||||
|
alignment-baseline: middle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
]
|
]
|
||||||
// 周长
|
|
||||||
#perimeter = 2 * Math.PI * RADIUS
|
|
||||||
|
|
||||||
get trackPath() {
|
get #path() {
|
||||||
let isDashboard = this.type === 'dashboard'
|
let n = this.type === TYPE_CIRCLE ? -1 : 1
|
||||||
return `
|
return `
|
||||||
M 64 64
|
M 64 64
|
||||||
m 0 ${isDashboard ? '' : '-'}${RADIUS}
|
m 0 ${n * RADIUS}
|
||||||
a ${RADIUS} ${RADIUS} 0 1 1 0 ${isDashboard ? '-' : ''}${RADIUS * 2}
|
a ${RADIUS} ${RADIUS} 0 1 1 0 ${-2 * n * RADIUS}
|
||||||
a ${RADIUS} ${RADIUS} 0 1 1 0 ${isDashboard ? '' : '-'}${RADIUS * 2}
|
a ${RADIUS} ${RADIUS} 0 1 1 0 ${2 * n * RADIUS}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
get trailPathStyle() {
|
|
||||||
return styleMap({
|
|
||||||
strokeDasharray: `${this.#perimeter * this.rate}px, ${this.#perimeter}px`,
|
|
||||||
strokeDashoffset: this.strokeDashoffset
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
get strokeDashoffset() {
|
get #dasharray() {
|
||||||
let offset = (-1 * this.#perimeter * (1 - this.rate)) / 2
|
let rate = this.type === TYPE_CIRCLE ? 1 : 0.75
|
||||||
return `${offset}px`
|
return `${PERIMETER * rate * (this.value / 100)}px, ${PERIMETER}px`
|
||||||
}
|
|
||||||
|
|
||||||
get rate() {
|
|
||||||
return this.type === 'dashboard' ? 0.75 : 1
|
|
||||||
}
|
|
||||||
|
|
||||||
get circlePathStyle() {
|
|
||||||
return styleMap({
|
|
||||||
strokeDasharray: `${
|
|
||||||
this.#perimeter * this.rate * (this.value / 100)
|
|
||||||
}px, ${this.#perimeter}px`,
|
|
||||||
strokeDashoffset: this.strokeDashoffset,
|
|
||||||
transition: 'stroke-dasharray 0.6s ease 0s, stroke 0.6s ease'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#fix(val) {
|
#fix(val) {
|
||||||
|
@ -156,38 +163,37 @@ class Progress extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
#drawCircle() {
|
#drawCircle() {
|
||||||
|
let offset = OFFSET[this.type]
|
||||||
|
let dash = DASH_ARRAY[this.type]
|
||||||
|
let v = this.value
|
||||||
return html`
|
return html`
|
||||||
<svg viewBox="0 0 128 128">
|
<svg viewBox="0 0 128 128">
|
||||||
<path
|
<path
|
||||||
d=${this.trackPath}
|
d=${this.#path}
|
||||||
stroke="var(--wc-progress-inactive-color, var(--color-plain-2))"
|
stroke="var(--base-color)"
|
||||||
stroke-width="var(--wc-progress-line-width, 6px)"
|
stroke-dashoffset=${offset}
|
||||||
stroke-linecap="round"
|
stroke-dasharray=${dash}
|
||||||
fill="none"
|
|
||||||
style=${this.trailPathStyle}
|
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
d=${this.trackPath}
|
d=${this.#path}
|
||||||
stroke="var(--wc-progress-active-color, var(--color-teal-1))"
|
opacity=${v > 0 ? '' : 0}
|
||||||
stroke-linecap="round"
|
stroke="currentColor"
|
||||||
stroke-width="var(--wc-progress-line-width, 6px)"
|
stroke-dashoffset=${offset}
|
||||||
fill="none"
|
stroke-dasharray=${this.#dasharray}
|
||||||
style=${this.circlePathStyle}
|
|
||||||
/>
|
/>
|
||||||
|
<text x="64" y="64">${v}%</text>
|
||||||
</svg>
|
</svg>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
#drawLine() {
|
#drawLine() {
|
||||||
|
let v = this.value
|
||||||
return html`
|
return html`
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<mark
|
<mark class="thumb" style=${styleMap({ width: v + '%' })}></mark>
|
||||||
class="thumb"
|
|
||||||
style=${styleMap({ width: this.value + '%' })}
|
|
||||||
></mark>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-value" style=${styleMap({ left: this.value + '%' })}>
|
<div class="progress-value" style=${styleMap({ left: v + '%' })}>
|
||||||
${this.value + '%'}
|
${v}%
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
@ -196,7 +202,7 @@ class Progress extends Component {
|
||||||
let step = ~~(this.value / 20) || 1
|
let step = ~~(this.value / 20) || 1
|
||||||
return html`
|
return html`
|
||||||
<main class="container" step=${step}>
|
<main class="container" step=${step}>
|
||||||
${this.type === 'line' ? this.#drawLine() : this.#drawCircle()}
|
${this.type === TYPE_LINE ? this.#drawLine() : this.#drawCircle()}
|
||||||
</main>
|
</main>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue