CSS 动画: 渐进显示或隐藏、旋转
1. html + css + js
js事件基础
<body>
<button onclick="handle(this)">alter</button>
</body>
<script>
function handle(ele){
// <button οnclick="handle(this)">alter</button>
console.info(ele);
}
</script>
DOM 0级事件
<body>
<button id="but">alter</button>
</body>
<script>
let button = document.getElementById('but');
button.onclick = function(ele){
// MouseEvent {isTrusted: true, screenX: 726, screenY: 146,
// clientX: 726, clientY: 44, …}
console.info(ele);
}
</script>
DOM 2级事件
<body>
<div>It is a div html label.</div>
<button id="but">alter</button>
</body>
<script>
let button = document.getElementById('but');
button.addEventListener('click', function(ele){
// MouseEvent {isTrusted: true, screenX: 726, screenY: 146,
// clientX: 726, clientY: 44, …}
console.info(ele);
}, true); // true: 捕获阶段, false: 冒泡阶段
</script>
正文
渐进显示和隐藏
<head>
<style>
body{
text-align: center;
}
.show{
opacity: 1;
}
.hide{
opacity: 0;
}
.show, .hide{
transition: all 2s ease-in;
}
</style>
</head>
<body>
<div class="show">It is a div html label.</div>
<button id="alter">alter</button>
</body>
<script>
let button = document.getElementById('alter');
button.addEventListener('click', function(){
const divClassName = document.getElementsByTagName('div')[0].className;
document.getElementsByTagName('div')[0].className =
divClassName === 'show' ? 'hide' : 'show';
}, true);
</script>
或者
<head>
<style>
body{
text-align: center;
}
.show {
animation: show-detail 3s ease-in forwards;
}
.hide {
animation: hide-detail 3s ease-in forwards;
}
@keyframes show-detail {
0% {
opacity: 0;
color: red;
}
50% {
opacity: 0.5;
color: green;
}
100% {
opacity: 1;
color: blue;
}
}
@keyframes hide-detail {
0% {
opacity: 1;
color: red;
}
50% {
opacity: 0.5;
color: green;
}
100% {
opacity: 0;
color: blue;
}
}
</style>
</head>
<body>
<div class="show">It is a div html label.</div>
<button id="alter">alter</button>
</body>
<script>
let button = document.getElementById('alter');
button.addEventListener('click', function(){
const divClassName = document.getElementsByTagName('div')[0].className;
document.getElementsByTagName('div')[0].className =
divClassName === 'show' ? 'hide' : 'show';
}, true);
</script>
2. React
相比使用js,React与其本质上都是一样的:获取元素,修改其类名。
// index.js
import React from 'react';
import { Component, Fragment } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
class Apps extends Component{
constructor(props) {
super(props);
this.state = {
classStyle: 'hide',
};
this.handleBut = this.handleBut.bind(this)
}
handleBut () {
this.setState({
classStyle: this.state.classStyle === 'show' ? 'hide' : 'show'
})
}
render() {
return (
<Fragment>
<div className={this.state.classStyle}>
It is a div html label.
</div>
<button onClick={this.handleBut}>display</button>
</Fragment>
)
}
}
ReactDOM.render(<Apps />, document.getElementById('root'));
/* index.css */
body {
text-align: center;
}
div {
font: normal bold normal 24px/26px "MicroYaHei";
}
button {
width: 80px;
height: 30px;
}
/* 过渡 */
/*.show, .hide {*/
/* transition: all 0.5s ease-in;*/
/* color: red;*/
/*}*/
/*.show {*/
/* opacity: 1;*/
/*}*/
/*.hide {*/
/* opacity: 0;*/
/*}*/
/* 动画 */
.show {
/* forwards: 保存动画最后的效果 */
animation: show-detail 3s ease-in forwards;
}
.hide {
animation: hide-detail 3s ease-in forwards;
}
@keyframes show-detail {
0% {
opacity: 0;
color: red;
}
50% {
opacity: 0.5;
color: green;
}
100% {
opacity: 1;
color: blue;
}
}
@keyframes hide-detail {
0% {
opacity: 1;
color: red;
}
50% {
opacity: 0.5;
color: green;
}
100% {
opacity: 0;
color: blue;
}
}
3. React-transition-group
模块安装: https://reactcommunity.org/react-transition-group/
import React from 'react';
import { Component, Fragment } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { CSSTransition } from "react-transition-group";
class Apps extends Component{
constructor(props) {
super(props);
this.state = {
flag: true,
butContent: '隐藏',
};
this.handleBut = this.handleBut.bind(this)
}
handleBut () {
this.setState({
flag: this.state.flag !== true,
})
}
render() {
return (
<Fragment>
<CSSTransition
in={ this.state.flag }
timeout={ 1000 }
classNames='fade'
unmountOnExit
onExited={(ele) => {
console.info(ele);
this.setState({ butContent: '展示' })
}}
onEnter={(ele) => {
this.setState({ butContent: '隐藏' })
}}
>
<div>It is a div html label.</div>
</CSSTransition>
<button onClick={this.handleBut}>{ this.state.butContent }</button>
</Fragment>
)
}
}
ReactDOM.render(<Apps />, document.getElementById('root'));
.fade-enter, .fade-appear {
opacity: 0;
}
.fade-enter-active, .fade-appear-active {
opacity: 0.5;
transition: opacity 1s ease-in;
}
.fade-enter-done {
opacity: 1;
}
.fade-exit{
opacity: 1;
}
.fade-exit-active {
opacity: 0.5;
transition: opacity 1s ease-in;
}
.fade-exit-done {
opacity: 0;
}
在这里有一个问题:.fade-appear
和.fade-appear-active
未起作用,有待解决。
上面的这个只对单个元素有效,使用TransitionGroup
可以作用于多个元素。
import React from 'react';
import { Component, Fragment } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { CSSTransition, TransitionGroup } from "react-transition-group";
class Apps extends Component{
constructor(props) {
super(props);
this.state = {
data: [],
};
this.handleBut = this.handleBut.bind(this)
}
handleBut () {
this.setState({
data: [...this.state.data, 'new item']
})
}
render() {
return (
<Fragment>
<TransitionGroup>
{
this.state.data.map((item, index) => {
const itemCon = { item }.item;
return (
<CSSTransition
in={ this.state.flag }
timeout={ 1000 }
classNames='fade'
unmountOnExit
onEnter={(ele) => {
ele.style.backgroundColor = 'blue';
ele.style.color = 'white';
}}
onEntering={(ele) => {
ele.innerHTML = '正在生成节点';
}}
onEntered={(ele) => {
ele.style.backgroundColor = '';
ele.innerHTML = itemCon;
ele.style.color = 'black';
}}
key={index}
>
<div>itemCon</div>
</CSSTransition>
)
})
}
</TransitionGroup>
<button onClick={this.handleBut}>AddItem</button>
</Fragment>
)
}
}
ReactDOM.render(<Apps />, document.getElementById('root'));
4. 旋转
这里使用的资源源于https://www.iconfont.cn/
<style>
@font-face { *** }
.iconfont { *** }
div {
position: relative;
}
.zoom {
position: absolute;
display: block;
font-size: 200px;
transition: all 0.3s ease-in;
transform-origin: center center;
}
</style>
<div>
<span class="iconfont zoom"></span>
</div>
<script>
const obj = document.getElementsByTagName('div')[0],
icon = document.getElementsByTagName('span')[0];
obj.addEventListener('click', function(){
let curAngle = icon.style.transform;
curAngle = curAngle.replace(/[^0-9]/ig, '');
curAngle = curAngle ? parseInt(curAngle, 10)+360 : 0;
icon.style.transform = 'rotate('+curAngle+'deg)';
}, true);
</script>