我正在尝试使用React和React.addons.CSSTransitionGroup创建一个带有动画的水平滚动页面导航.目前我可以进行水平滚动(使用flexBox),页面打开/关闭,动画进入和离开.但动画并不是我想要的.
看看this example(jsfiddle).
当您单击上一页上的按钮时,它当前会将离开屏幕的页面向右推.虽然正确的结果是在同一个地方动画离开页面.我不知道如何使用CSSTransitionGroup实现这种效果,或者知道它是否可以使用它.
function generateId() {
var r = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 10; i += 1) {
r += possible.charAt(Math.floor(Math.random() * possible.length));
}
return r;
}
var PageList = {
pages: [],listener: function(newpages) {},open: function(caption,index) {
if (index != null) {
this.pages = this.pages.slice(0,index + 1);
}
this.pages.push({
id: generateId(),caption: caption,width: (150 + Math.random() * 50) | 0
});
this.listener(this.pages);
}
};
PageList.open("Main");
var PageLink = React.createClass({
render: function() {
var self = this;
return React.DOM.button({
className: "pagelink",onClick: function() {
PageList.open(self.props.caption,self.props.pageIndex);
}
},self.props.caption);
}
});
var Page = React.createClass({
render: function() {
return React.DOM.article({
className: "page",style: {
width: this.props.page.width + "px"
}
},React.DOM.h1({},this.props.page.caption),React.createElement(PageLink,{
caption: "Alpha",pageIndex: this.props.index
}),{
caption: "Beta",{
caption: "Gamma",pageIndex: this.props.index
})
);
}
});
var Pages = React.createClass({
componentDidMount: function() {
var self = this;
PageList.listener = function(pages) {
self.setState({
pages: pages
});
};
},getInitialState: function() {
return {
pages: PageList.pages
};
},render: function() {
var pages = this.state.pages.map(function(page,index) {
return React.createElement(Page,{
key: page.id,index: index,page: page
});
});
return React.createElement(
React.addons.CSSTransitionGroup,{
component: "section",className: "pages",transitionName: "fall"
},pages);
}
});
React.initializeTouchEvents(true);
React.render(
React.createElement(Pages),document.getElementById("main")
);
/* animation */
.fall-enter {
transform: translate(0,-100%);
transform: translate3d(0,-100%,0);
}
.fall-enter.fall-enter-active {
transform: translate(0,0);
transform: translate3d(0,0);
transition: transform 1s ease-out;
}
.fall-leave {
index: -1;
transform: translate(0,0);
transition: transform 1s ease-in;
}
.fall-leave.fall-leave-active {
transform: translate(0,100%);
transform: translate3d(0,100%,0);
}
/* other */
* {
Box-sizing: border-Box;
}
.pagelink {
padding: 5px;
margin: 5px 0px;
width: 100%;
}
.pages {
display: flex;
flex-flow: row;
overflow-x: scroll;
overflow-y: hidden;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #ddd;
}
.pages:after {
flex: none;
-webkit-flex: none;
display: block;
content: " ";
width: 100px;
}
.page {
flex: none;
-webkit-flex: none;
margin: 8px;
padding: 10px 31px;
background: #fff;
overflow: auto;
Box-shadow: 2px 1px 4px rgba(0,0.2);
border-radius: 3px;
}
PS:如果它只适用于最新的浏览器,那就没关系了.
要获得您正在寻找的页面的垂直阵容,我们将不得不更改HTML以添加额外的图层.这个额外的图层将是文章上下滑动的垂直通道.现在,新的图层被推到一边,因为没有父图层来包含它们.
第二个问题是所有HTML都是由React动态创建的.试图进入并更改库/插件并不是一个好主意,所以我尝试用jQuery创建你想要的效果.
可能解决方案
HTML结构
我做的第一件事是草拟一个理想的布局.我们在整个父级中需要三个层:
Parent
Cell
Innercell (doubles in height to contain two articles)
Article
草图中的虚线是Innercell,Page矩形是文章
CSS
在大多数情况下,我使用你原来的造型.主要区别在于细胞和物品之间的额外层.细胞保持高度固定在100%,然后内细胞高度:200%.它也绝对定位,底部:0.这很重要,因为它意味着额外的间距高于父母而不是下面.我们还确保文章本身绝对定位,底部为:0.这将其置于内细胞的下半部分.
JS
这里要做的第一件事就是弄清楚我们希望事情发生的顺序.单击按钮时,我们可以使用三种可能的路径.
>如果单击最右边的按钮,我们要添加一个新单元格,然后在文章中滑动.
>如果单击第二个到最右边的按钮,我们只想在新文章中滑动.
>如果单击任何其他按钮,我们希望向右滑动单元格中的新文章,并且所有其他右侧单元格应向下滑动而不进行替换.
在更改文章圈内,我们需要:
1从模板创建新文章,插入所有可变数据,并将其放在innercell顶部的空白区域中.
2我们需要向下滑动内部细胞.
最终守则
var cellTemplate = ' |
/* other */
* {
Box-sizing: border-Box;
}
section {
display: flex;
flex-flow:row;
overflow-x: scroll;
overflow-y: hidden;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #ddd;
}
cell {
flex: none;
-webkit-flex: none;
display:block;
height:100%;
float:left;
position:relative;
width:166px;
}
innercell {
display:block;
height:200%;
width:100%;
position:absolute;
left:0;
bottom:0;
}
.animating {
transition: bottom 1s ease-out;
}
article {
display:block;
padding:8px;
height:50%;
position:absolute;
left:0;
bottom:0;
}
article.new {
bottom:auto;
top:0;
}
innerarticle {
display:block;
padding: 10px 31px;
background: #fff;
overflow: auto;
Box-shadow: 2px 1px 4px rgba(0,0.2);
border-radius: 3px;
height:100%;
}
innerarticle button {
padding: 5px;
margin: 5px 0px;
width: 100%;
}
笔记
我最后添加了第四层,我称之为innerarticle.这是因为你的文章有8px的保证金.由于两个物品在垂直方向上彼此叠加,因此边缘会折叠并且不会堆叠.添加一个innerarticle,然后给文章一个填充:8px,我可以确保它堆栈.
此外,您可能已经注意到我使用了很多自定义元素名称.我之所以这样做,是因为它有效,让您轻松了解正在做什么.您可以随意将它们全部更改为< div class =“INSERTCURRENTELEMENT”>