ren*_*q19 5 javascript css sass css-animations reactjs
我已经在 React 中实现了我自己的响应式手风琴,但我无法让它为 fold 的打开设置动画。
这特别奇怪,因为我可以在标题之前获得图标来上下动画,而且除了图标是伪元素之外,我似乎看不出两者之间的区别。
JS:
class Accordion extends React.Component {
constructor(props) {
super(props);
this.state = {
active: -1
};
}
/***
* Selects the given fold, and deselects if it has been clicked again by setting "active to -1"
* */
selectFold = foldNum => {
const current = this.state.active === foldNum ? -1 : foldNum;
this.setState(() => ({ active: current }));
};
render() {
return (
<div className="accordion">
{this.props.contents.map((content, i) => {
return (
<Fold
key={`${i}-${content.title}`}
content={content}
handle={() => this.selectFold(i)}
active={i === this.state.active}
/>
);
})}
</div>
);
}
}
class Fold extends React.Component {
render() {
return (
<div className="fold">
<button
className={`fold_trigger ${this.props.active ? "open" : ""}`}
onClick={this.props.handle}
>
{this.props.content.title}
</button>
<div
key="content"
className={`fold_content ${this.props.active ? "open" : ""}`}
>
{this.props.active ? this.props.content.inner : null}
</div>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
CSS:
$line-color: rgba(34, 36, 38, 0.35);
.accordion {
width: 100%;
padding: 1rem 2rem;
display: flex;
flex-direction: column;
border-radius: 10%;
overflow-y: auto;
}
.fold {
.fold_trigger {
&:before {
font-family: FontAwesome;
content: "\f107";
display: block;
float: left;
padding-right: 1rem;
transition: transform 400ms;
transform-origin: 20%;
color: $line-color;
}
text-align: start;
width: 100%;
padding: 1rem;
border: none;
outline: none;
background: none;
cursor: pointer;
border-bottom: 1px solid $line-color;
&.open {
&:before {
transform: rotateZ(-180deg);
}
}
}
.fold_content {
display: none;
max-height: 0;
opacity: 0;
transition: max-height 400ms linear;
&.open {
display: block;
max-height: 400px;
opacity: 1;
}
}
border-bottom: 1px solid $line-color;
}
Run Code Online (Sandbox Code Playgroud)
这是 CodePen:https ://codepen.io/renzyq19/pen/bovZKj
如果您想要平滑过渡,我不会有条件地呈现内容。这将使动画幻灯片特别棘手。
我会改变这个:
{this.props.active ? this.props.content.inner : null}
Run Code Online (Sandbox Code Playgroud)
对此:
{this.props.content.inner}
Run Code Online (Sandbox Code Playgroud)
并使用这个scss:
.fold_content {
max-height: 0;
overflow: hidden;
transition: max-height 400ms ease;
&.open {
max-height: 400px;
}
}
Run Code Online (Sandbox Code Playgroud)
试试下面的代码片段或查看分叉的CodePen 演示。
class Accordion extends React.Component {
constructor(props) {
super(props);
this.state = {
active: -1
};
}
/***
* Selects the given fold, and deselects if it has been clicked again by setting "active to -1"
* */
selectFold = foldNum => {
const current = this.state.active === foldNum ? -1 : foldNum;
this.setState(() => ({ active: current }));
};
render() {
return (
<div className="accordion">
{this.props.contents.map((content, i) => {
return (
<Fold
key={`${i}-${content.title}`}
content={content}
handle={() => this.selectFold(i)}
active={i === this.state.active}
/>
);
})}
</div>
);
}
}
class Fold extends React.Component {
render() {
return (
<div className="fold">
<button
className={`fold_trigger ${this.props.active ? "open" : ""}`}
onClick={this.props.handle}
>
{this.props.content.title}
</button>
<div
key="content"
className={`fold_content ${this.props.active ? "open" : ""}`}
>
{this.props.content.inner}
</div>
</div>
);
}
}
const pictures = [
"http://unsplash.it/200",
"http://unsplash.it/200",
"http://unsplash.it/200",
];
var test = (title, text, imageURLs) => {
const images=
<div className='test-images' >
{imageURLs.map((url,i) => <img key={i} src={url} />)}
</div>;
const inner =
<div className='test-content' >
<p>{text} </p>
{images}
</div>;
return {title, inner};
};
const testData = [
test('Title', 'Content',pictures ),
test('Title', 'Content',pictures ),
test('Title', 'Content',pictures ),
test('Title', 'Content',pictures ),
test('Title', 'Content',pictures ),
];
ReactDOM.render(<Accordion contents={testData} />, document.getElementById('root'));Run Code Online (Sandbox Code Playgroud)
.accordion {
width: 100%;
padding: 1rem 2rem;
display: flex;
flex-direction: column;
border-radius: 10%;
overflow-y: auto;
}
.fold {
border-bottom: 1px solid rgba(34, 36, 38, 0.35);
}
.fold .fold_trigger {
text-align: start;
width: 100%;
padding: 1rem;
border: none;
outline: none;
background: none;
cursor: pointer;
border-bottom: 1px solid rgba(34, 36, 38, 0.35);
}
.fold .fold_trigger:before {
font-family: FontAwesome;
content: "\f107";
display: block;
float: left;
padding-right: 1rem;
transition: transform 400ms;
transform-origin: 20%;
color: rgba(34, 36, 38, 0.35);
}
.fold .fold_trigger.open:before {
transform: rotateZ(-180deg);
}
.fold .fold_content {
max-height: 0;
overflow: hidden;
transition: max-height 400ms ease;
}
.fold .fold_content.open {
max-height: 400px;
}Run Code Online (Sandbox Code Playgroud)
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<div id='root'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>Run Code Online (Sandbox Code Playgroud)
笔记:
我使用ease而不是linear在过渡上,因为我认为这是一个更好的效果。但这只是个人口味。linear也会起作用。
此外,您可以继续有条件地呈现内容。向下滑动动画是可能的,但无法轻松实现向上滑动。您也可以探索一些过渡库。
但是,我认为将状态仅用于条件类是最简单的(就像您对open类所做的那样)。我认为如果您尝试制作 CSS 动画,有条件地将内容渲染到 DOM 会使您的生活变得困难。
| 归档时间: |
|
| 查看次数: |
2974 次 |
| 最近记录: |