简体   繁体   English

通过改变css top在div动画中垂直滚动

[英]Vertical scrolling in div animation by changing css top

I'm trying to set up horizontal slider. 我正在尝试设置水平滑块。 I have div with overflow: hidden and inside I have 16 divs with height of 60px. 我有div overflow: hidden和内部我有16个高度为60px的div。 Parent div has height so you can see only 4 childs at the time. 父div具有高度,因此您当时只能看到4个孩子。

Now I want to change childs top: css to make them slide up and 4 new come from bottom. 现在我想改变孩子的top: css让他们向上滑动,4个新人来自底部。

Here's what I've done so far 这是我到目前为止所做的

lastAddedService.getLastAdded()
    .then(function (response) {
        $scope.lastAddedElements = response.data;

        var i = 0, g = 0, c = 0, p = 0;
        var k = 1, b = 1, h = 1;

        var slider = {
            step: 1,
            positionTop: 0,
            init: function (step) {
                var that = this;
                el[0].querySelectorAll('.a').forEach(function (element) {
                    if(step === 1) {
                        if(i < 16) {
                            that.positionTop = i * 60;
                            i++;
                            return angular.element(element).css('top', that.positionTop);
                        }
                    }
                    if(step === 2) {
                        if(i < 4) {
                            that.positionTop = k * 60 * -1;
                            i++; k++;
                            return angular.element(element).css('top', that.positionTop);
                        }
                        if(i >= 4) {
                            k = 0;
                            that.positionTop = g * 60;
                            i++; g++;
                            return angular.element(element).css('top', that.positionTop);
                        }
                    }
                    if(step === 3) {
                        if(i < 8) {
                            that.positionTop = b * 60 * -1;
                            i++; b++;
                            return angular.element(element).css('top', that.positionTop);
                        }
                        if(i >= 8) {
                            that.positionTop = c * 60;
                            i++; c++;
                            return angular.element(element).css('top', that.positionTop);
                        }
                    }
                    if(step === 4) {
                        if(i < 12) {
                            that.positionTop = h * 60 * -1;
                            i++; h++;
                            return angular.element(element).css('top', that.positionTop);
                        }
                        if(i >= 12) {
                            that.positionTop = p * 60;
                            i++; p++;
                            return angular.element(element).css('top', that.positionTop);
                        }
                    }
                });
            },
            changeSlide: function (step) {
                this.step = step;
                this.init(this.step);
            }
        };

        $timeout(function () {
            slider.changeSlide(1);
        });

        setTimeout(function () {
            setInterval(function () {
                var q = 1;
                q++;
                slider.changeSlide(q);
                if(q === 4) {
                    q = 1;
                }
            }, 5000);
        }, 5000);

    }, function (err) {
        console.log('error getting last added');
    });
}

So I'm gathering records from backend and then there is this slider object which has logic which I explained above. 所以我从后端收集记录然后有这个滑块对象,它具有我在上面解释过的逻辑。

Backend call works fine, I did console response and it's 16 records which I display in layout layer later on. 后端调用工作正常,我做了控制台响应,它是16条记录,我稍后在布局层中显示。 Question is mainly about the logic for this sliding object. 问题主要是关于这个滑动对象的逻辑。

I'm using $timeout to start code work because this code is indeed in angularJS directive and NodeList which I get by querySelectorAll would be empty otherwise because it's evaluated after async backend call finish and then DOM is fully loaded. 我正在使用$timeout来启动代码工作,因为这个代码确实在angularJS指令中,而我通过querySelectorAll得到的NodeList将是空的,否则因为它在async后端调用完成后进行评估,然后DOM被完全加载。 But it's not really relevant to real logic of this script, it's just additional info. 但它与这个脚本的真实逻辑并不真正相关,它只是附加信息。

  • This code looks very bad to me. 这段代码对我来说非常糟糕。 How I can improve it? 我怎么能改进它?
  • It's starting to update top after around 20 seconds and 1 div has 960px I don't know why. 它开始在大约20秒后更新顶部,1 div有960px我不知道为什么。
  • It's not reseting this variables values so it doesn't loop but it increase top further and further. 它不会重置这些变量值,因此它不会循环,但会进一步增加top

I add HTML from my directive if anyone want to reproduce issue 如果有人想要重现问题,我会从我的指令中添加HTML

<div class="col-lg-8 col-md-8 col-sm-12 col-xs-12">
    <div class="row u-no-margin">
        <div class="col-lg-11 col-xs-11">
            <h2 class="main__heading">
                Ostatnio dodane
            </h2>
            <div class="main__last-added-field">
                <div class="main__last-added a" data-ng-repeat="n in lastAddedElements">
                    <div class="row u-no-margin main__last-added-container">
                        <div class="col-lg-3 col-md-2 col-sm-2 col-xs-2">
                            <h4 class="main__last-added-heading">
                                {{ n.data.attributes.price }}
                            </h4>
                        </div>
                        <div class="col-lg-7 col-xs-8 u-no-padding">
                            <h4 class="main__last-added-heading u-no-padding">
                                {{ n.data.attributes.name }}
                            </h4>
                        </div>
                        <div class="col-lg-2 col-xs-2">
                            <button type="button" class="btn btn__primary">
                                Zobacz
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-lg-1 col-xs-1">
            <div class="main__last-added-dot-container">
                <span class="main__last-added-dot main__last-added-dot--active"></span>
                <span class="main__last-added-dot"></span>
                <span class="main__last-added-dot"></span>
                <span class="main__last-added-dot"></span>
            </div>
        </div>
    </div>
</div>

JS code is within directive link: function and the templateUrl is above HTML code. JS代码在指令link: function ,templateUrl在HTML代码之上。




** EDIT ** **编辑**


I update question I add plunker showing issue and I explain one more, step by step what I want to accomplish. 我更新问题我添加了plunker显示问题,我再一步解释,我想要完成的事情。

  • Step1: all element has top: x css so they are align vertically. Step1:所有元素都有top: x css所以它们是垂直对齐的。 I'm using overflow: hidden on parent so you see only 4 and 12 are hidden below like this 我正在使用overflow: hidden在父级上,所以你看到只有4和12这样隐藏在下面

ALT

  • Step2 I move first 4 element to top: -x so you don't see first 4 and element 5,6,7,8 take their place so elements 5,6,7,8 now slide to the top and first 4 are hidden. Step2我将前4个元素移到top: -x所以你看不到前4个元素和元素5,6,7,8取代它们所以元素5,6,7,8现在滑到顶部而前4个被隐藏。

  • step 3 same as Step2: elements 5,6,7,8 move to negative top and you now see elements 9,10,11,12 步骤3与步骤2相同:元素5,6,7,8移动到负顶部,您现在看到元素9,10,11,12

  • step 4 same as Step3: elements 9,10,11,12 move to negative top and you now see elements 13,14,15,16 步骤4与步骤3相同:元素9,10,11,12移动到负顶部,您现在看到元素13,14,15,16

here's demo 这是演示

I don't know why but in plunker it doesn't udpate css top of elements at all. 我不知道为什么,但在plunker它根本没有udpate css top of elements。

First of all I recommend that you use a bootstrap only solution for your html/css view because its responsive, tested and you will have cleaner code. 首先,我建议您为html / css视图使用仅限bootstrap的解决方案,因为它具有响应性,经过测试并且您将拥有更清晰的代码。

I have made some modification to your slider logic in a way that the logic is the as if your slider were a pagination directive. 我已经对滑块逻辑进行了一些修改,逻辑就像滑块是分页指令一样。

Basically, you divide your data into pages and then you keep track of the current page to be displayed on the view. 基本上,您将数据划分为页面,然后跟踪要在视图上显示的当前页面。

In your elements directive you use two filters on the data (startFrom, limitTo). 在您的elements指令中,您对数据使用两个过滤器(startFrom,limitTo)。 The 'limitTo' is a built-in filter in Angular and 'startFrom' is a custom filter that you have to create. 'limitTo'是Angular中的内置过滤器,'startFrom'是您必须创建的自定义过滤器。

<div class="" data-ng-repeat="n in elements | startFrom:currentPage*pageSize | limitTo:pageSize">

This is just an ideia that might help you refactor you code such that you won't need css positioning to determine which items will be displayed. 这只是一个可以帮助您重构代码的ideia,这样您就不需要css定位来确定将显示哪些项目。 Here is my demo: 这是我的演示:

https://plnkr.co/edit/IROsQWr5z4oYgZzmR2GF?p=preview https://plnkr.co/edit/IROsQWr5z4oYgZzmR2GF?p=preview

I hope this helps! 我希望这有帮助!

I've done it with this code: 我用这段代码完成了它:

<div class="main__last-added a"
     data-ng-repeat="n in lastAddedElements"
     data-order="{{ $index+1 }}">

(function () {
    'use strict';

    angular
        .module('igt')
        .directive('lastAdded', Directive);

    Directive.$inject = ['$timeout', 'lastAddedService'];

    function Directive($timeout, lastAddedService) {
        return {
            restrict: 'E',
            scope: {
                destiny: '='
            },
            templateUrl: 'html/directives/lastAdded.html',
            link: function ($scope, el) {
                lastAddedService.getLastAdded()
                    .then(function (response) {
                        $scope.lastAddedElements = response.data;
                        $scope.slider = {
                            increment: 0,
                            step: 1,
                            positionTop: 0,
                            init: function (step) {
                                var that = this;
                                var elements = el[0].querySelectorAll('.a');
                                if(step === 1) {
                                    console.log('run step 1 ..............');
                                    this.step = 1;
                                    elements.forEach(function (e) {
                                        var order = angular.element(e).attr('data-order');
                                        if(order <= 16) {
                                            that.positionTop = order * 60 - 60;
                                            return angular.element(e).css('top', that.positionTop);
                                        }
                                    });
                                }
                                if(step === 2) {
                                    console.log('run step 2 ..............');
                                    this.step = 2;
                                    elements.forEach(function (e) {
                                        var order = angular.element(e).attr('data-order');
                                        if (order <= 4) {
                                            that.positionTop = order * 60 * -1;
                                            return angular.element(e).css('top', that.positionTop);
                                        }
                                        if (order > 4) {
                                            that.positionTop = that.increment * 60;
                                            that.increment++;
                                            console.log(that.increment);
                                            if (that.increment === 12) {
                                                that.increment = 0;
                                                console.log('reset inc in step 2');
                                            }
                                            return angular.element(e).css('top', that.positionTop);
                                        }
                                    });
                                }
                                if(step === 3) {
                                    console.log('run step 3 ..............');
                                    this.step = 3;
                                    elements.forEach(function (e) {
                                        var order = angular.element(e).attr('data-order');
                                        if (order <= 8) {
                                            that.positionTop = order * 60 * -1;
                                            return angular.element(e).css('top', that.positionTop);
                                        }
                                        if (order > 8) {
                                            that.positionTop = that.increment * 60;
                                            that.increment++;
                                            console.log(that.increment);
                                            if (that.increment === 8) {
                                                that.increment = 0;
                                                console.log('reset inc in step 3');
                                            }
                                            return angular.element(e).css('top', that.positionTop);
                                        }
                                    });
                                }
                                if(step === 4) {
                                    console.log('run step 4 ..............');
                                    this.step = 4;
                                    elements.forEach(function (e) {
                                        var order = angular.element(e).attr('data-order');
                                        if (order <= 12) {
                                            that.positionTop = order * 60 * -1;
                                            return angular.element(e).css('top', that.positionTop);
                                        }
                                        if (order > 12) {
                                            that.positionTop = that.increment * 60;
                                            that.increment++;
                                            console.log(that.increment);
                                            if (that.increment === 4) {
                                                that.increment = 0;
                                                console.log('reset inc in step 4');
                                            }
                                            return angular.element(e).css('top', that.positionTop);
                                        }
                                    });
                                }
                            },
                            changeSlide: function (step) {
                                this.step = step;
                                this.init(this.step);
                            }
                        };

                        $timeout(function () {
                            var i = 1;
                            $scope.slider.changeSlide(i);
                            setInterval(function () {
                                i++; if(i === 5) i = 1;
                                $scope.slider.changeSlide(i);
                            }, 5000);
                        });

                    }, function (err) {
                        console.log('error getting last added: ' + err);
                    });
            }

        }
    }

})();

But this code still look very lame although it's a bit better than first version. 但是这个代码看起来仍然非常蹩脚,尽管它比第一个版本好一点。 I feel like it can be done in much much simplier way. 我觉得它可以用更简单的方式完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM