鸿蒙OS&UniApp动效进度组件:打造流畅的用户体验#三方框架 #Uniapp
·
UniApp动效进度组件:打造流畅的用户体验
在移动应用开发中,进度展示是一个常见的交互需求。无论是文件上传、数据加载,还是步骤引导,都需要通过进度条来提供及时的反馈。本文将深入探讨如何在UniApp中实现一个动效丰富的进度组件,并融入鸿蒙设计理念,打造出专业的用户体验。
设计思路
在开发进度组件之前、我们需要考虑以下关键点:
-
功能需求
- 基础进度展示
- 动画过渡效果
- 自定义样式
- 多种展示模式
-
交互体验
- 平滑的动画
- 状态反馈
- 手势操作
- 实时更新
-
性能优化
- 动画性能
- 渲染效率
- 内存管理
组件实现
首先创建components/AnimProgress.vue组件:
<template>
<view
class="anim-progress"
:class="[
`progress-${type}`,
{
'progress-active': active,
'progress-vertical': vertical
}
]"
:style="containerStyle"
>
<!-- 进度轨道 -->
<view
class="progress-track"
:style="trackStyle"
>
<!-- 进度条 -->
<view
class="progress-bar"
:style="barStyle"
>
<!-- 条纹效果 -->
<view
v-if="stripe"
class="progress-stripe"
/>
<!-- 进度文本 -->
<text
v-if="showText && !vertical"
class="progress-text"
:style="textStyle"
>
{{ progressText }}
</text>
</view>
</view>
<!-- 垂直模式文本 -->
<text
v-if="showText && vertical"
class="progress-text vertical"
:style="textStyle"
>
{{ progressText }}
</text>
</view>
</template>
<script>
const DEFAULT_DURATION = 200
export default {
name: 'AnimProgress',
props: {
// 进度值(0-100)
value: {
type: Number,
default: 0,
validator: val => val >= 0 && val <= 100
},
// 进度条类型
type: {
type: String,
default: 'primary',
validator: val => [
'primary',
'success',
'warning',
'error'
].includes(val)
},
// 是否垂直模式
vertical: {
type: Boolean,
default: false
},
// 是否显示条纹
stripe: {
type: Boolean,
default: false
},
// 是否激活动画
active: {
type: Boolean,
default: false
},
// 是否显示进度文本
showText: {
type: Boolean,
default: true
},
// 进度文本格式
format: {
type: Function,
default: value => `${value}%`
},
// 进度条高度
strokeWidth: {
type: [Number, String],
default: 12
},
// 进度条颜色
color: {
type: String,
default: ''
},
// 轨道颜色
trackColor: {
type: String,
default: ''
},
// 文本颜色
textColor: {
type: String,
default: ''
},
// 动画持续时间
duration: {
type: Number,
default: DEFAULT_DURATION
}
},
data() {
return {
currentValue: 0
}
},
computed: {
// 容器样式
containerStyle() {
const style = {}
if (this.vertical) {
style.height = typeof this.strokeWidth === 'number'
? `${this.strokeWidth}rpx`
: this.strokeWidth
style.width = '12rpx'
} else {
style.height = '12rpx'
style.width = typeof this.strokeWidth === 'number'
? `${this.strokeWidth}rpx`
: this.strokeWidth
}
return style
},
// 轨道样式
trackStyle() {
return {
backgroundColor: this.trackColor || ''
}
},
// 进度条样式
barStyle() {
const style = {
backgroundColor: this.color || '',
transition: `all ${this.duration}ms cubic-bezier(0.4, 0, 0.2, 1)`
}
if (this.vertical) {
style.height = `${this.currentValue}%`
style.width = '100%'
} else {
style.width = `${this.currentValue}%`
style.height = '100%'
}
return style
},
// 文本样式
textStyle() {
return {
color: this.textColor || ''
}
},
// 进度文本
progressText() {
return this.format(Math.round(this.currentValue))
}
},
watch: {
value: {
handler(val) {
this.updateProgress(val)
},
immediate: true
}
},
methods: {
// 更新进度
updateProgress(value) {
if (this.currentValue === value) return
// 触发过渡开始事件
this.$emit('transitionstart')
this.currentValue = value
// 设置过渡结束监听
clearTimeout(this._timer)
this._timer = setTimeout(() => {
this.$emit('transitionend')
}, this.duration)
}
},
beforeDestroy() {
clearTimeout(this._timer)
}
}
</script>
<style lang="scss">
.anim-progress {
position: relative;
border-radius: 100rpx;
background-color: #f5f5f5;
transition: all 0.3s;
// 垂直模式
&.progress-vertical {
width: 12rpx;
.progress-track {
height: 100%;
.progress-bar {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
min-height: 0;
.progress-stripe {
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-size: 20rpx 20rpx;
}
}
}
.progress-text {
position: absolute;
left: 24rpx;
top: 50%;
transform: translateY(-50%);
white-space: nowrap;
}
}
// 水平模式
&:not(.progress-vertical) {
height: 12rpx;
.progress-track {
width: 100%;
.progress-bar {
height: 100%;
min-width: 0;
.progress-stripe {
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-size: 20rpx 20rpx;
}
.progress-text {
position: absolute;
right: 8rpx;
top: 50%;
transform: translateY(-50%);
color: #fff;
font-size: 24rpx;
}
}
}
}
// 进度轨道
.progress-track {
position: relative;
width: 100%;
height: 100%;
border-radius: inherit;
overflow: hidden;
// 进度条
.progress-bar {
position: relative;
border-radius: inherit;
transition: inherit;
// 条纹效果
.progress-stripe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
}
// 主题变体
&.progress-primary .progress-bar {
background-color: #2196f3;
}
&.progress-success .progress-bar {
background-color: #4caf50;
}
&.progress-warning .progress-bar {
background-color: #ff9800;
}
&.progress-error .progress-bar {
background-color: #f44336;
}
// 激活动画
&.progress-active {
.progress-stripe {
animation: progress-stripe 1s linear infinite;
}
}
}
// 条纹动画
@keyframes progress-stripe {
from {
background-position: 0 0;
}
to {
background-position: 20rpx 0;
}
}
</style>
使用示例
在页面中使用进度组件:
<template>
<view class="demo-page">
<!-- 基础用法 -->
<view class="demo-section">
<view class="section-title">基础用法</view>
<anim-progress :value="50" />
</view>
<!-- 主题类型 -->
<view class="demo-section">
<view class="section-title">主题类型</view>
<anim-progress
type="primary"
:value="progress.primary"
/>
<anim-progress
type="success"
:value="progress.success"
/>
<anim-progress
type="warning"
:value="progress.warning"
/>
<anim-progress
type="error"
:value="progress.error"
/>
</view>
<!-- 条纹动画 -->
<view class="demo-section">
<view class="section-title">条纹动画</view>
<anim-progress
:value="70"
stripe
active
/>
</view>
<!-- 垂直方向 -->
<view class="demo-section">
<view class="section-title">垂直方向</view>
<view class="vertical-demo">
<anim-progress
v-for="type in types"
:key="type"
:type="type"
:value="progress[type]"
vertical
stripe
active
/>
</view>
</view>
<!-- 自定义样式 -->
<view class="demo-section">
<view class="section-title">自定义样式</view>
<anim-progress
:value="85"
stroke-width="40"
color="#722ed1"
track-color="#f0f0f0"
text-color="#722ed1"
:format="val => `完成度 ${val}%`"
/>
</view>
</view>
</template>
<script>
import AnimProgress from '@/components/AnimProgress.vue'
export default {
components: {
AnimProgress
},
data() {
return {
types: ['primary', 'success', 'warning', 'error'],
progress: {
primary: 90,
success: 75,
warning: 60,
error: 45
}
}
}
}
</script>
<style lang="scss">
.demo-page {
padding: 30rpx;
.demo-section {
margin-bottom: 40rpx;
.section-title {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.anim-progress {
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
}
.vertical-demo {
height: 400rpx;
display: flex;
justify-content: center;
gap: 60rpx;
}
}
</style>
功能说明
1. 基础功能
组件支持以下基础功能:
<!-- 基础进度条 -->
<anim-progress :value="50" />
<!-- 不同主题 -->
<anim-progress type="success" :value="75" />
<!-- 条纹动画 -->
<anim-progress
:value="70"
stripe
active
/>
<!-- 垂直方向 -->
<anim-progress
:value="80"
vertical
/>
2. 自定义样式
支持多种样式定制:
<anim-progress
:value="85"
stroke-width="40"
color="#722ed1"
track-color="#f0f0f0"
text-color="#722ed1"
:format="val => `完成度 ${val}%`"
/>
3. 动画效果
实现平滑的过渡动画:
// 进度条样式
barStyle() {
return {
transition: `all ${this.duration}ms cubic-bezier(0.4, 0, 0.2, 1)`,
width: `${this.currentValue}%`
}
}
// 更新进度
updateProgress(value) {
if (this.currentValue === value) return
this.$emit('transitionstart')
this.currentValue = value
clearTimeout(this._timer)
this._timer = setTimeout(() => {
this.$emit('transitionend')
}, this.duration)
}
性能优化
1. 动画优化
使用CSS3动画提升性能:
// 条纹动画
@keyframes progress-stripe {
from {
background-position: 0 0;
}
to {
background-position: 20rpx 0;
}
}
// 使用transform代替位置动画
.progress-text {
transform: translateY(-50%);
}
2. 渲染优化
合理使用计算属性:
computed: {
progressText() {
return this.format(Math.round(this.currentValue))
}
}
最佳实践
-
样式定制
- 提供丰富的样式属性
- 支持主题定制
- 保持样式一致性
-
动画效果
- 使用CSS3动画
- 平滑的过渡效果
- 适当的动画时长
-
代码组织
- 组件化封装
- 样式模块化
- 逻辑解耦
总结
通过以上实现,我们完成了一个功能完备的进度组件。该组件不仅实现了基础的进度展示功能,还融入了鸿蒙OS的设计理念,提供了丰富的动画效果和流畅的交互体验。在实际开发中,我们可以根据具体需求对组件进行定制和扩展,例如:
- 添加更多动画效果
- 扩展交互方式
- 优化性能表现
- 增强可定制性
希望这篇文章能够帮助大家更好地理解和实现UniApp中的进度组件,同时也能够在实际开发中应用这些技巧,打造出更好的用户界面。
更多推荐


所有评论(0)