Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

年终活动h5动画总结 #1

Open
hytStart opened this issue Feb 19, 2019 · 0 comments
Open

年终活动h5动画总结 #1

hytStart opened this issue Feb 19, 2019 · 0 comments

Comments

@hytStart
Copy link
Owner

年终活动h5动画总结

戳这里----♂--github--

css3 + react-id-swiper + react + redux + saga
采用postcss的Autoprefixer插件,即可满足大多数oppo,vivo手机的兼容性问题。

1. 动画相关主要内容:

  1. 流星
  2. 闪烁星星
  3. 字的晃动
  4. 人的移动(动画 + 监听动画结束时间)
  5. 桥的铺垫
  6. 开启旅程按钮缩放
  7. 旋转(+ 兼容)
  8. react-id-swiper
  9. swiper配合css3实现切换

2. css3动画语法

  • animation
animation-name
animation-duration
animation-timing-function  速度曲线
animation-delay
animation-iteration-count
animation-direction
play-state	
fill-mode  
  • transform

transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。
其中 transform-origin (属性改变被转换元素的中心)。

  • transition

三者区别: animation 动画,关键帧,往复性。 transition 过渡, 属性,触发动作,一过性。 transform 变换, 复杂的变换参数。

3. 示例 https://github.com/hytStart/React_chouchou/blob/master/src/components/home/ui/action/action.scss

  • 流星

改变位置translate3d,透明度opacity和大小scale
流星尾巴采用伪元素元素:after旋转-45deg(旋转基点为左transform-origin: left;);采用border可以实现,靠近头部越亮,靠近尾部越暗。

图一 流星

.star {
    display: block;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #FFF;
    top: 10px;
    left: 200px;
    position: relative;
    animation: star-ani 6s infinite ease-out;
    box-shadow: 0 0 5px 5px rgba(255, 255, 255, .3);
    opacity: 1;
}
.star:after {
    content: '';
    display: block;
    top: 0px;
    left: 40%;
    border: 0px solid #fff;
    border-width: 0px 90px 2px 90px;
    border-color: transparent transparent transparent rgba(255, 255, 255, .3);
    transform: rotate(-45deg) translate3d(1px, 3px, 0);
    box-shadow: 0 0 1px 0 rgba(255, 255, 255, .1);
    transform-origin: left;
}

@keyframes star-ani {
    0% {
        opacity: 0;
        transform: scale(0) rotate(0) translate3d(0, 0, 0);
    }
    50% {
        opacity: 1;
        transform: scale(1) rotate(0) translate3d(-100px, 100px, 0);
    }
    100% {
        opacity: 0;
        transform: scale(1) rotate(0) translate3d(-200px, 200px, 0);
    }
}
  • 闪烁星星

改变透明度

.shine {
    background: url('../../../../images/action/icon-star1.png') no-repeat center;
    background-size: 100%;
    width: 30px;
    height: 40px;
    position: absolute;
    top: 90px;
    left: 100px;
    opacity: 0;
    animation: opacity-change 0.5s ease-in-out infinite;
}

@keyframes opacity-change {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

分为两段动画,下降和上升。translateY改变即可。

.text-item-0 {
    position: absolute;
    width: 25px;
    height: 75px;
    top: 60px;
    left: 100px;
    background: url('../../../../images/action/S-start.png') no-repeat center;
    background-size: 100%;
    animation: letter-0 1.5s ease-in-out both, letter-0-1 2.0s ease-in-out 1.5s both;
}

@keyframes letter-0 {
    0% {
        transform: translateY(0)
    }
    50% {
        transform: translateY(80px)
    }
    100% {
        transform: translateY(0px)
    }
}
@keyframes letter-0-1 {
    0% {
        opacity: 1;
    }
    100% {
        top: -80px;
        opacity: 0;
    }
}
  • 人移动

切换dom,添加类控制移动和暂停,以及切换背景人物。监听animationend事件。

jsx
{
    peopleMove ?
        <div
            className={`${style.people_move} ${!pausedState && style.people_paused}`}
            ref={start2 => { this.start2 = start2 }}
        />
        :
        <div className={style.people} />
}
css
.people {
    width: 20px;
    height: 64px;
    position: absolute;
    left: 10px;
    top: 130px;
    background: url('../../../../images/action/people.png') no-repeat center;
    background-size: 100%; 
    opacity: 0;
    animation: peopleUp 1s ease-in-out 0.5s both;
}
.people_move {
    background: url('../../../../images/action/people_moveleft.gif');
    background-size: 100% 100%;
    background-position: center;
    background-repeat: no-repeat;
    width: 20px;
    height: 64px;
    position: absolute;
    left: 10px;
    top: 130px;
    opacity: 1;
    animation: PeopleMove 1.5s linear 0s both;
}
.people_paused {
    width: 20px;
    height: 64px;
    background: url('../../../../images/action/people.png');
    background-size: 100% 100%;
    background-position: center;
    background-repeat: no-repeat;
    animation-play-state: paused;
}

@keyframes peopleUp {
    0% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}
@keyframes PeopleMove {
    0% {
        left: 10px;
        top: 130px;
    }
    100% {
        top: 20px;
        left: 180px;
        background-size: 100% 100%;
        background-position: center;
        background-repeat: no-repeat;
    }
}

// 监听动画结束时机
componentDidUpdate() {
    const { peopleMove } = this.state
    if (peopleMove) {
        this.start2.addEventListener('animationend', this.end)
        this.start2.addEventListener('webkitAnimationEnd', this.end)
        this.start2.addEventListener('mozAnimationEnd', this.end)
        this.start2.addEventListener('oAnimationEnd', this.end)
    }
}
  • 桥的出现

配合background-size: cover;属性实现。

.brige {
    width: 0px;
    background: url('../../../../images/action/bridge.png');
    background-size: cover;
    background-repeat: no-repeat;
    height: 100px;
    position: absolute;
    top: 40px;
    left: 30px;
    animation: BridgeFadeIn 3s linear both;
    opacity: 0;
}

@keyframes BridgeFadeIn {
    0% {
        width: 0px;
        opacity: 0;
    }
    100% {
        width: 200px;
        opacity: 1;
    }
}
  • 渐变大(开始旅程)

利用transform scale2D 缩放转换。

.icon-ciecle {
    display: block;
    position: absolute;
    left: 100px;
    top: 80px;
    width: 30px;
    height: 30px;
    background: url('../../../../images/action/icon-light.png') no-repeat center;
    background-size: 100%; 
    animation: warn 1.2s ease-in-out 0s infinite both;
}

@keyframes warn {
    0% {
        transform: scale(0.1);
        opacity: 0.0;
    }
    25% {
        transform: scale(0.2);
        opacity: 0.3;
    }
    50% {
        transform: scale(0.4);
        opacity: 0.5;
    }
    75% {
        transform: scale(0.6);
        opacity: 0.7;
    }
    100% {
        transform: scale(0.8);
        opacity: 0.0;
    }
}
  • 旋转

ios的animation-play-state: paused;不起作用,且animation动画不可写在新增类里,必须写在一个类里。(测试中发现,这里有疑问。)

.music_img {
    width: 40px;
    height: 40px;
    display: block;
    position: absolute;
    left: 100px;
    top: 80px;
    animation: rotating 3s linear infinite;
    animation-play-state: running;
}
.rotate-pause {
    animation-play-state: paused;
}

@keyframes rotating {
    0% {
    	transform: rotate(0deg);
     }
    100% { 
	transform: rotate(360deg);
     }
}
  • react-id-swiper

Swiper的react版本,基本api都支持,具实验目测相当于Swiper v4。

  1. 不一定通过api。也可以通过重写css实现。
  2. 重写css切换效果的话,会影响它本身的动画效果,所以可通过添加不可滑动来控制。
1. 
.swiper-wrapper {
    transition-delay: 1.6s;
}
2. 
noSwiping: true,
noSwipingClass: 'stop-swiping',
  • Swiper实现的迷宫切换

1.swiper的effect属性与控制背景图片的opacity,利用时间差实现最终效果。包括迷宫的切换,背包男的出现与消失,弹窗的出现与消失。
2.swiper属性的activeIndex,可以得到滑动到第几页,通过改变dom或者改变类,控制第几页动画的发生。

// 根据activeIndex拿到的页数,控制该页数state的改变,通过切换dom和添加类的方式,达到进场与退场的动画效果。
// 添加类stop-swiping控制不可滑动,动画完成后,才可继续滑动下一页。
const mazeStyle = classNames({
    [styles['maze-1']]: true,
    [styles['maze-out']]: firstMazeOut,
})
const peopleStyle = classNames({
    [styles['people-1']]: true,
    [styles['people-out']]: firstMazeOut,
})
const popCardStyle = classNames({
    [styles['pop-card-container']]: true,
    [styles['pop-card-out']]: firstMazeOut,
})
{
    firstMazeIn ?
        <div className={!isSlideFirst && "stop-swiping"}>
            <div className={styles['maze-container']}>
                <div className={mazeStyle} />
                <div className={peopleStyle} />
            </div>
            <div className={popCardStyle}>
                <ModalScene {...this.props} />
            </div>
        </div>
        :
        <div />    // 不添加会影响swiper自身页数的判断
}

4. 动画总结

别人写的真牛X,自己只会opacity,translate

5. 待完善

  • html2canvas
  • 资源加载
  • jsbridge使用与注意事项
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant