css实现多张图片旋转动画以及炫光效果
最近遇到一个需求,需要将动态的背景图片用css动画的方式替代。主要原因是因为动态背景图特别大,打包出来的体积非常大,而且无法压缩。最后决定将一个动态背景图拆分成几个静态图片,然后用css动画的方式实现旋转和炫光效果。要求根据不同的父组件的宽高都能居中显示。
效果展示
技术难点:
- 动画旋转的步骤不难,难得是怎么把几张图片都叠加在一起,并且刚好都是居中的,看起来像是一张图片呢?
- 炫光效果实现,简单研究了一下,发现还是用线性渐变实现局部炫光效果,整体的话让图片在一定的时间内实现由暗到明再到暗的效果。有技术的同学可以深入研究一下怎么实现无边框只在图片内容上显示渐变炫光。ps: 由于我觉得有div背景框的限制,炫光效果太丑了。v
css 图片居中对齐技巧
需要居中对齐,我发现只要父组件实现相对定位,子组件实现绝对定位就没什么问题,但是如何叠加呢,想要子组件再套子组件?属实没有必要,直接把几张图片放在用<di>
包裹的标签中,然后用一个大的组件一起包裹起来,用同样的css就能解决问题。
图片叠加旋转代码实现:
js
import "./styles.css";
export default function App() {
const imageStyle = {
position: 'absolute',
top: '60%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
};
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'start',
width: '95%',
height: '90%',
}}
>
<div style={imageStyle}>
<img src={bg} className={`bg`} />
</div>
<div style={imageStyle}>
<img src={outerBg} className={`outer-image`} />
</div>
<div style={imageStyle}>
<img src={innerBg} className={`inner-image`} />
</div>
</div>
);
}
css
@prefix: .td-lego-circular-solid-pie;
@{prefix}-bg {
animation: innerLoading 8s linear infinite;
}
@{prefix}-outer-image {
animation: outerLoading 5s linear infinite;
}
@{prefix}-inner-image {
animation: innerLoading 3s linear infinite;
}
@keyframes innerLoading {
/*以百分比来规定改变发生的时间 也可以通过"from"和"to",等价于0% 和 100%*/
0% {
/*rotate(2D旋转) scale(放大或者缩小) translate(移动) skew(翻转)*/
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes outerLoading {
/*以百分比来规定改变发生的时间 也可以通过"from"和"to",等价于0% 和 100%*/
0% {
/*rotate(2D旋转) scale(放大或者缩小) translate(移动) skew(翻转)*/
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
炫光技巧,这个就是css的线性渐变
问题了,有机会用径向渐变
实现更好的效果
炫光技巧代码实现
js
<div
className={`${prefixName}-container`}
style={{
...style,
width,
height,
}}
>
<div className={`${prefixName}-data-wrap`}>
<div className={`${prefixName}-title-wrap`}>
<div
className={`${prefixName}-title`}
style={{
...theme.typography.h3,
color: theme.colors.gray50,
lineHeight: '65px',
}}
>
{title}
</div>
</div>
<div className={`${prefixName}-total`} >
{data}
</div>
</div>
</div>
css
@{prefix}-container {
position: relative;
flex: 1;
overflow: hidden;
background-image: url('../assets/other_datashow_bg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
animation: breathe 3s linear infinite;
@{prefix}-data-wrap {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
@{prefix}-title-wrap {
flex: 1;
align-items: center;
justify-content: center;
width: 156px;
height: 65px;
background-image: url('./assets/rectangle.svg');
background-repeat: no-repeat;
background-size: 100% 100%;
@{prefix}-title {
text-align: center;
}
}
@{prefix}-total {
margin-top: 12px;
text-align: center;
}
}
@{prefix}-title-wrap:after {
position: absolute;
top: 0;
left: 0;
width: 156px;
height: 65px;
content: '';
background: linear-gradient(45deg, transparent 40%, rgba(255, 255, 255, 0.15) 50%, transparent 60%);
background-size: 300% 100%;
animation: shine 15s linear infinite;
}
@keyframes shine {
0% {
background-position-x: 400%;
}
50% {
background-position-x: 0%;
}
100% {
background-position-x: -400%;
}
}
@keyframes breathe {
0% {
opacity: 1;
}
50% {
filter: brightness(150%) saturate(140%);
}
100% {
opacity: 1;
}
}