应使用v-show而非v-if控制显隐,以避免dom重建导致动画重置;通过props.color动态设置border-top-color实现颜色定制,配合border-radius:50%、transform-origin:center和小写@keyframes确保圆环正圆居中旋转。

直接用 CSS 写一个带 props.color 控制的 .loading 元素,别碰 v-if 和全局 API,否则颜色变不了、动画会重置。
为什么不能用 uni.showLoading 实现自定义颜色
uni.showLoading 是原生层弹窗,所有平台都只支持 title 和 mask 两个参数,color、size、icon 全部不生效。Android 上甚至会强制套一层灰色遮罩,CSS 根本无法穿透。
常见错误现象:uni.showLoading({ title: '加载中', mask: true }) 调用后,iOS 显示白底黑字、Android 显示灰底白字,改 app-plus 配置也没用——因为压根没开放样式接口。
真正可控的方式只有一种:自己写一个 CustomLoading.vue 组件,用 v-show 控制显隐,用 props 接收颜色和尺寸。
border-top-color + border-radius: 50% 是最稳的旋转圆环写法
要让圆环是正圆、旋转中心居中、颜色可单独控制,必须满足三个条件:
-
border: 10upx solid transparent(不能写rgba(0,0,0,0),小程序不认) -
border-top-color: v-bind(color)(其他三边保持透明,只让顶部有颜色) -
border-radius: 50%(缺了这句,某些安卓 WebView 会渲染成椭圆)
示例关键样式:
.loading {
width: 60upx;
height: 60upx;
border: 10upx solid transparent;
border-top-color: v-bind(color);
border-radius: 50%;
animation: spin 0.6s linear infinite;
transform-origin: center;
}
注意:transform-origin: center 必须显式写,否则华为/小米部分机型旋转会偏移;animation 时长设为 0.6s,和 uni.showLoading 原生节奏一致,切换时不突兀。
v-show 而不是 v-if,否则颜色变更会重置动画
如果用 v-if="visible",每次 visible 切换,DOM 节点就会销毁重建,animation 从头开始播,用户看到的是“闪一下再转”,而不是持续旋转。
正确做法是用 v-show + opacity 或 visibility 控制显隐,同时加 pointer-events: none 防点击穿透:
-
v-show保证 DOM 始终存在,props.color更新时,CSS 变量或内联样式能立即生效 - 外层容器加
pointer-events: none,内部按钮/文字加pointer-events: auto(如有交互需求) - 避免用
opacity: 0单独隐藏,必须配visibility: hidden,否则仍可能响应事件
封装建议:把 color、size、text 全部设为 props,默认值写死在 defineProps 里,调用时像这样:<customloading :color="'#ff6b6b'" :size="80" text="提交中..."></customloading>
小程序平台要注意动画名必须小写 + scoped 样式隔离失效问题
微信/支付宝小程序编译时会把 @keyframes spin 自动转成小写,但如果你写的是 @keyframes Spin(首字母大写),动画就直接不跑。必须统一用小写字母命名动画。
另外,<style scoped></style> 在小程序里对 @keyframes 无效,动画定义必须写在非 scoped 样式块里,或者提成独立 .css 文件引入。
容易踩的坑:
- 在
<style scoped></style>里写@keyframes spin→ 微信小程序不识别 - 用
background: url(./spin.gif)→ 小程序不支持 GIF 动画,只静帧 - 用
transform: rotateZ()→ 某些旧版安卓 WebView 不兼容,坚持用rotate()
真正稳定的做法:纯 CSS 圆环 + 小写动画名 + 非 scoped @keyframes 定义 + v-show 控制开关。复杂点在于动画命名和作用域,不是颜色逻辑本身。











