我正在尝试开发以下旋转木马。
http://jsfiddle.net/2kLanjwn/2/
它应该以这种方式工作。
我无法在相反的情况下应用相同的逻辑,因此当我单击按钮UP时,我需要收缩中央div,然后向上滑动。
我很高兴你做错了,如果你能在jsfiddle上解决它。 此外,我想知道是否有更好的方法来实现相同的效果或可以重复使用的组件。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Scroll text box example</title>
<style>
#btn-up, #btn-down {
position: absolute;
top: 600px;
}
#btn-up {
left: 0px;
}
#btn-down {
left: 50px;
}
#btn-up, #btn-down {
width: 50px;
height: 50px;
background-color: yellow;
outline: 1px solid black;
}
#content-scroll-container {
position: absolute;
top: 0;
left: 0px;
width: 500px;
height: 250px; /* MASK HEIGHT real mask would be 200*/
overflow: hidden;
}
#content-scroll-inner {
position: absolute;
}
.cnt {
height: 100px;
width: 500px;
background-color: red;
}
.cnt:nth-child(even) {
height: 100px;
background-color: pink;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var scroller = {
config: {
curPos: 0, // position
canExpand: false,
el: 'content-scroll-container', // visible area (container)
elInner: 'content-scroll-inner', // inner content
cntPosY: null, // content top-left corner (0 position)
cntHeight: null, // content lenght
maskHeight: null, // visible area (rest is masked out)
canMoveUp: null, // true jquery can slide up content
canMoveDown: null, // true jquery can slide down content
increment: 100, // slide of x pixel when user perfom an action
incrementOf: 0, // how much we have slided the contnt
animationSpeed: 500, // jquery animation speed, use 0 for no animation
isAnimationOn: false, // true when jquery is performing animation
},
data: '<div id="cnt-0" class="cnt">0</div><div id="cnt-1" class="cnt">1</div><div id="cnt-2" class="cnt">2</div><div id="cnt-3" class="cnt">3</div><div id="cnt-4" class="cnt">4</div><div id="cnt-5" class="cnt">5 empty</div>',
getCntPosition: function () {
// get y position of content
var elm = document.getElementById(this.config.elInner);
this.config.cntPosY = elm.offsetTop;
},
getCntSize: function () {
// get height for content
var elm = document.getElementById(this.config.elInner);
this.config.cntHeight = elm.clientHeight;
},
getMaskSize: function () {
// get height visible area
var elm = document.getElementById(this.config.el);
this.config.maskHeight = elm.clientHeight;
},
updateData: function () {
// refresh state
this.getMaskSize();
this.getCntPosition();
this.getCntSize();
this.canMoveUpCheck();
this.canMoveDownCheck();
//console.clear();
console.log(this.config);
},
canMoveUpCheck: function () {
// set flags allowing sliding up (in case we have enought content to show)
var lastScreenY = (this.config.cntHeight - this.config.maskHeight); // last screen visible
if ((this.config.incrementOf * -1) < lastScreenY)
this.config.canMoveUp = true;
else
this.config.canMoveUp = false;
},
canMoveDownCheck: function () {
// set flags allowing sliding down (in case we have enought content to show)
if (this.config.cntPosY >= 0)
this.config.canMoveDown = false; // cannot move more up if content is on start position (0 position)
else
this.config.canMoveDown = true;
},
goUp: function () {
// user want to read previose content
//this.updateData();
if (this.config.canMoveDown == true && this.config.isAnimationOn == false) {
this.moveCnt('down'); // content go down
}
},
goDown: function () { //**************************
// user want to read next content
//this.updateData();
if (this.config.canMoveUp == true && this.config.isAnimationOn == false) {
// check newPos
var newPos = this.config.curPos + 1;
if (newPos > 0) { // special case
if (this.config.canExpand == true)
this.config.increment = 150;
this.config.canExpand = true;
this.moveCnt('up');
}
}
},
moveCnt: function (direction) {
// do the actual animation
var moveOf;
this.isAnimationOn = true;
if (direction == 'up') {
this.config.curPos++;
if (this.config.cntPosY == 0) { // special case for first item
moveOf = '-=' + (this.config.increment / 2);
}
else {
moveOf = '-=' + this.config.increment;
}
var target = '#' + this.config.elInner + ':not(:animated)';
$(target).animate({ 'top': moveOf }, this.animationSpeed, this.cbEndAnimation.bind(this, direction));
} else if (direction == 'down') {
this.config.curPos++;
var distanceToFp = (this.config.increment / 2); // height to reach first page (special page)
var distanceToFp = 50;
if (this.config.cntPosY == (distanceToFp * -1)) {
moveOf = '+=' + distanceToFp;
// i need to contract only the firs tone
$('cnt-1').css({ height: '100px' }, 500, this.cbEndAnimationExpand.bind(this));
} else {
moveOf = '+=' + this.config.increment;
}
var target = '#' + this.config.elInner + ':not(:animated)';
$(target).animate({ 'top': moveOf }, this.animationSpeed, this.cbEndAnimation.bind(this));
}
//var target = '#' + this.config.elInner + ':not(:animated)';
//$(target).animate({ 'top': moveOf }, this.animationSpeed, this.cbEndAnimation.bind(this, direction));
},
cbEndAnimation: function (direction) {
// runs when animation end
this.config.isAnimationOn = false;
if (direction == 'up') {
this.config.incrementOf -= this.config.increment;
if (this.config.canExpand == true) { // expand
this.logicExpand();
} else {
// do nothing
}
}
else if (direction == 'down') {
this.config.incrementOf += this.config.increment;
}
this.updateData(); // refresh state has element has just moved
this.logicShowHideArrows();
},
logicExpand: function () {
// take contenf and expand it
var elm = document.getElementById('cnt-' + this.config.curPos);
$(elm).animate({ height: '150px' }, 500, this.cbEndAnimationExpand.bind(this));
},
cbEndAnimationExpand: function () {
console.log('end anim expand');
},
logicContract: function () {
var elm = document.getElementById('cnt-' + this.config.curPos);
$(elm).animate({ height: '-=50px' }, 500, this.cbEndAnimationContract.bind(this));
},
logicShowHideArrows: function () {
// reset first
this.hideArrow('btn-up');
this.hideArrow('btn-down');
if (this.config.canMoveUp == true)
this.showArrow('btn-down');
if (this.config.canMoveDown == true)
this.showArrow('btn-up');
},
cbEndAnimationContract: function () {
this.config.isAnimationOn = false;
this.moveCnt('down'); // content go down
},
showArrow: function (elmName) {
var elm = document.getElementById(elmName);
elm.style.display = '';
},
hideArrow: function (elmName) {
var elm = document.getElementById(elmName);
elm.style.display = 'none';
},
setEventHandler: function () {
// envet handlers for arrows
var btnUp = document.getElementById('btn-up');
btnUp.addEventListener('click', this.goUp.bind(this), false);
var btnDown = document.getElementById('btn-down');
btnDown.addEventListener('click', this.goDown.bind(this), false);
},
renderData: function () {
// render data content to slide
var elm = document.getElementById(this.config.elInner);
elm.innerHTML = this.data;
},
start: function () {
this.renderData();
this.updateData();
this.setEventHandler();
this.logicShowHideArrows(); // at start set arrows visibility
}
};
</script>
</head>
<body onload="scroller.start();">
<div id="content-scroll-container">
<div id="content-scroll-inner">
</div>
</div>
<div id="btn-up">UP</div>
<div id="btn-down">DOWN</div>
</body>
</html>
答案 0 :(得分:1)
我无法找到代码中的错误,但我对其进行了一些更改,并且有效。这是代码
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Scroll text box example</title>
<style>
#btn-up, #btn-down {
position: absolute;
top: 400px;
}
#btn-up {
left: 0px;
}
#btn-down {
left: 50px;
}
#btn-up, #btn-down {
width: 50px;
height: 50px;
background-color: yellow;
outline: 1px solid black;
}
#content-scroll-container {
position: absolute;
top: 0;
left: 0px;
width: 500px;
height: 250px; /* MASK HEIGHT real mask would be 200*/
overflow: hidden;
}
#content-scroll-inner {
position: absolute;
}
.cnt {
height: 100px;
width: 500px;
background-color: red;
}
.cnt:nth-child(even) {
height: 100px;
background-color: pink;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var scroller = {
config: {
curPos: 0, // position
el: 'content-scroll-container', // visible area (container)
elInner: 'content-scroll-inner', // inner content
cntPosY: null, // content top-left corner (0 position)
cntHeight: null, // content lenght
maskHeight: null, // visible area (rest is masked out)
animationSpeed: 500, // jquery animation speed, use 0 for no animation
isAnimationOn: false, // true when jquery is performing animation
},
data: '<div id="cnt-0" class="cnt">0</div><div id="cnt-1" class="cnt">1</div><div id="cnt-2" class="cnt">2</div><div id="cnt-3" class="cnt">3</div><div id="cnt-4" class="cnt">4</div><div id="cnt-5" class="cnt">5 empty</div>',
getCntPosition: function () {
// get y position of content
var elm = document.getElementById(this.config.elInner);
this.config.cntPosY = elm.offsetTop;
},
getCntSize: function () {
// get height for content
var elm = document.getElementById(this.config.elInner);
this.config.cntHeight = elm.clientHeight;
},
getMaskSize: function () {
// get height visible area
var elm = document.getElementById(this.config.el);
this.config.maskHeight = elm.clientHeight;
},
updateData: function () {
// refresh state
this.getMaskSize();
this.getCntPosition();
this.getCntSize();
//console.clear();
console.log(this.config);
},
logicShowHideArrows: function () {
if(this.config.curPos<1) {
$('#btn-up').hide();
} else {
$('#btn-up').show();
}
if(this.config.curPos>=4) {
$('#btn-down').hide();
} else {
$('#btn-down').show();
}
},
goUp: function () {
if(this.config.curPos<4 && scroller.config.isAnimationOn ==false) {
scroller.config.isAnimationOn = true;
scroller.config.curPos++;
if(scroller.config.curPos==1) {
$('#content-scroll-inner').animate({'top':'-=50px'},500,function(){
$('#cnt-'+scroller.config.curPos).animate({'height':'+=50px'},500);
scroller.logicShowHideArrows();
scroller.config.isAnimationOn = false;
});
this.config.incrementOf-=50;
$('#btn-up').show();
}
else {
$('#content-scroll-inner').animate({'top':'-=150px'},500,function(){
$('#cnt-'+scroller.config.curPos).animate({'height':'+=50px'},500);
scroller.logicShowHideArrows();
scroller.config.isAnimationOn = false;
});
this.config.incrementOf-=150;
}
this.updateData();
}
},
goDown: function () { //**************************
// user want to read next content
//this.updateData();
if(this.config.curPos>0 && scroller.config.isAnimationOn ==false) {
scroller.config.isAnimationOn = true;
if(this.config.curPos==1) {
$('#cnt-'+scroller.config.curPos).animate({'height':'-=50px'},500,function(){
$('#content-scroll-inner').animate({'top':'+=50px'},500);
scroller.logicShowHideArrows();
scroller.config.isAnimationOn = false;
});
scroller.config.curPos--;
this.config.incrementOf+=150;
this.updateData();
}
else {
$('#cnt-'+scroller.config.curPos).animate({'height':'-=50px'},500,function(){
$('#content-scroll-inner').animate({'top':'+=150px'},500);
scroller.logicShowHideArrows();
scroller.config.isAnimationOn = false;
});
scroller.config.curPos--;
this.config.incrementOf+=150;
this.updateData();
}
}
},
setEventHandler: function () {
$('#btn-up').click(function() {
scroller.goDown();
});
$('#btn-down').click(function() {
scroller.goUp();
});
},
renderData: function () {
// render data content to slide
var elm = document.getElementById(this.config.elInner);
elm.innerHTML = this.data;
},
start: function () {
this.renderData();
this.updateData();
this.setEventHandler();
this.logicShowHideArrows();
}
};
</script>
</head>
<body onload="scroller.start();">
<div id="content-scroll-container">
<div id="content-scroll-inner">
</div>
</div>
<div id="btn-up">UP</div>
<div id="btn-down">DOWN</div>
</body>
</html>