起始
奖励自己个Taro骨架屏呗 自动生成的欧~
预览
组件
- Skeleton.ts
import React, { FC, useState, useEffect } from 'react'
import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'
import { SkeletonProps } from './data.d'
import './Skeleton.scss'
const Skeleton: FC<SkeletonProps> = props => {
const { selector = 'skeleton', loading = true } = props
const [radiusList, setRadiusList] = useState([])
const [rectList, setRectList] = useState([])
const [loadingTest, setLoadingTest] = useState(true)
/**
* 本地延迟模拟
*/
useEffect(() => {
setTimeout(() => {
setLoadingTest(false)
}, 2000)
}, [])
/**
* 等待父页面渲染后获取生成骨架屏
*/
Taro.eventCenter.once(Taro?.Current.router.onReady, () => {
initSkeleton()
})
/**
* 初始化请求
*/
const initSkeleton = () => {
getGraphList(selector, `${selector}-radius`).then((res: any) => {
setRadiusList(res)
})
getGraphList(selector, `${selector}-rect`).then((res: any) => {
setRectList(res)
})
}
/**
* 选择器获取节点
*/
const getGraphList = (ancestor, descendant) => {
return new Promise((resolve, reject) => {
if (process.env.TARO_ENV === 'weapp') {
Taro.createSelectorQuery().selectAll(`.${ancestor} >>> .${descendant}`)
.boundingClientRect().exec(rect => {
resolve(rect[0])
})
}
else {
Taro.createSelectorQuery().selectAll(`.${ancestor} .${descendant}`)
.boundingClientRect().exec(rect => {
resolve(rect[0])
})
}
})
}
return (
<View>
{loadingTest &&
<View className='SkeletonCmpt'>
{radiusList.map((radiusItem: any) =>
<View
className='skeleton skeleton-radius skeleton-animate-gradient'
style={{width: `${radiusItem.width}px`, height: `${radiusItem.height}px`, top: `${radiusItem.top}px`, left: `${radiusItem.left}px`}}
/>
)}
{rectList.map((rectItem: any) =>
<View
className='skeleton skeleton-animate-gradient'
style={{width: `${rectItem.width}px`, height: `${rectItem.height}px`, top: `${rectItem.top}px`, left: `${rectItem.left}px`}}
/>
)}
</View>
}
</View>
)
}
export default Skeleton
- Skeleton.scss
.SkeletonCmpt {
@include position-way-tl(absolute, 0, 0);
width: 100vw;
height: 100vh;
background-color: #fff;
overflow: hidden;
z-index: 1000;
.skeleton {
position: absolute;
background-color: #f2f3f5;
&-radius {
border-radius: 50%;
}
&-animate {
&-blink {
animation: skeleton-blink 1.5s ease-in-out infinite;
}
&-elastic {
animation: skeleton-elastic 2s ease-in-out infinite;
}
&-gradient {
background-image: linear-gradient(90deg, #f2f3f5 25%, #e6e6e6 37%, #f2f3f5 63%);
list-style: none;
background-size: 400% 100%;
background-position: 100% 50%;
animation: skeleton-gradient 1.8s ease-in-out infinite;
}
}
}
@keyframes skeleton-blink {
50% {
opacity: .6;
}
}
@keyframes skeleton-elastic {
50% {
transform: scaleX(.3);
}
}
@keyframes skeleton-gradient {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
}
- data.d.ts
/**
* Skeleton.props 参数类型
* @export
* @interface SkeletonProps
*/
export interface SkeletonProps {
selector?: string
loading: boolean
}
使用
<Skeleton selector='skeleton' loading={loading} />
<View className='skeleton'>
<View className='mainBox'>
<Image className='avatar skeleton-radius' src={homeInfo.avatar} />
<Text className='name skeleton-rect'>{homeInfo.name}</Text> // 文字可以设置name.skeleton-rect{min-width: 属性占位}
<View className='box skeleton-rect'></View>
<Test /> // 组件中也可以添加className='skeleton-rect'
</View>
</View>
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!