Javascript 将粘性标题设置为“;“俯卧撑”;,像Instagram';使用CSS和jQuery的iPhone应用程序

Javascript 将粘性标题设置为“;“俯卧撑”;,像Instagram';使用CSS和jQuery的iPhone应用程序,javascript,html,css,instagram,sticky,Javascript,Html,Css,Instagram,Sticky,Instagram应用程序有一个很好的粘性头,可以将当前的头推到新的头上。我发现了一个很好的教程,介绍了如何在安卓系统上实现这一点,但我希望用JavaScript和CSS实现这一点 我能够让我的头切换到一个新的头,但我似乎找不到一种方法来模仿Instagram的方式。非常感谢您的帮助 *编辑:当使用所指注释中的航路点作为Cj滚动时,我能够将标题粘贴到页面顶部。(). 我面临的主要问题是instagram在iPhone手机应用程序中使用的“俯卧撑”效果。我会链接到一个示例,但我以前从未见过使用它。

Instagram应用程序有一个很好的粘性头,可以将当前的头推到新的头上。我发现了一个很好的教程,介绍了如何在安卓系统上实现这一点,但我希望用JavaScript和CSS实现这一点

我能够让我的头切换到一个新的头,但我似乎找不到一种方法来模仿Instagram的方式。非常感谢您的帮助

*编辑:当使用所指注释中的航路点作为Cj滚动时,我能够将标题粘贴到页面顶部。(). 我面临的主要问题是instagram在iPhone手机应用程序中使用的“俯卧撑”效果。我会链接到一个示例,但我以前从未见过使用它。*

**编辑2:使用@Chris提供的部分代码笔,我能够使标题保持不变。然后我添加了一个.slideUp效果。我现在的问题是,只有在到达下一个标题时,才会出现.slideUp效果。现在效果在滚动时激活

代码如下:

(function() {
function stickyTitles(stickies) {
    this.load = function() {
        stickies.each(function(){
            var thisSticky = jQuery(this);
            jQuery.data(thisSticky[0], 'pos', thisSticky.offset().top);
        });
    }
    this.scroll = function() {      
        stickies.each(function(){           
            var thisSticky = jQuery(this),          
                pos = jQuery.data(thisSticky[0], 'pos');
            if (pos <= jQuery(window).scrollTop()) {
                thisSticky.addClass("fixed");
                // added this 
                 $(".followMeBar:parent").slideUp();

            } else {
                thisSticky.removeClass("fixed");
            }
        });         
    }
}
jQuery(document).ready(function(){
    var newStickies = new stickyTitles(jQuery(".followMeBar"));
    newStickies.load();
    jQuery(window).on("scroll", function() {
        newStickies.scroll();

    }); 
});
(函数(){
功能粘滞标题(粘滞){
this.load=函数(){
粘滞物。每个(函数(){
var thisticky=jQuery(this);
jQuery.data(thisticky[0],'pos',thisticky.offset().top);
});
}
this.scroll=函数(){
stickies.each(函数(){
var thisticky=jQuery(this),
pos=jQuery.data(thisticky[0],'pos');

如果(pos没有一个快速或简单的答案,但是通过一点创造性的哄骗,我们可以模仿相同的功能

我们需要的是一系列可以识别、循环并设置的元素,这样当我们在页面上找到它们的位置时,上一个项目就会被推上,新项目就会固定。我们需要使用jQuery的
offset()检索元素的初始位置.top
方法,并将其存储在
数据
标记中,以便我们以后可以引用它。然后,在滚动时将计算其余部分

这应该可以做到:

var stickyHeaders=(函数(){
变量$window=$(window),
$stickies;
var负载=功能(胶粘物){
if(typeof stickies===“object”&&stickies实例jQuery&&stickies.length>0){
$stickies=stickies.each(函数(){
var$thisticky=$(this.wrap(“”);
$thisticky
.data('originalPosition',$thisticky.offset().top)
.data('originalHeight',$thisticky.outerHeight())
.parent()
.height($thisticky.outerHeight());
});
$window.off(“scroll.stickies”).on(“scroll.stickies”,function()){
_当滚动时();
});
}
};
var_whenScrolling=函数(){
$stickies.每个(函数(i){
变量$thisticky=$(此),
$stickyPosition=$ThistSticky.data('originalPosition');
如果($stickyPosition 0&&$ThistSticky.offset().top>=$nextStickyPosition){
$thiststicky.addClass(“绝对”).css(“顶部”,$nextStickyPosition);
}
}否则{
var$prevstick=$stickies.eq(i-1);
$thisticky.removeClass(“固定”);

如果($prevSticky.length>0&&$window.scrollTop()我很难让Chris的答案准确地为我工作,因为所有的粘滞物都在一个相对定位的div内(上面都有一个标题,在相对div外),那么答案就是存储.offset().top,并从脚本中的.css('top',)中减去它。 在chris的版本中,最大值是将文档的顶部推离,这样可以很好地工作。 当您添加相对div时,top现在从该div的顶部推动,因此相对div上方的任何空间都包含在值中,这是您不希望看到的。 希望这对其他人有帮助。
詹姆斯首先感谢@Chris Spitles的出色回答

我已经创建了一个修改版本,不再需要包装每个粘性元素,因为它只是更改它们的相对位置,而不是使用固定的位置

var stickyHeaders = (function() {

    var $stickies;

    var load = function(stickies, target) {

        if (typeof stickies === "object" && stickies instanceof jQuery && stickies.length > 0) {

            $stickies = stickies.each(function() {

                var $thisSticky = $(this);

                $thisSticky
                    .data('originalPosition', $thisSticky.offset().top)
                    .data('originalHeight', $thisSticky.outerHeight());               
            });

            target.off("scroll.stickies").on("scroll.stickies", function(event) {
                 _whenScrolling(event);     
            });
        }
    };

    var _whenScrolling = function(event) {

        var $scrollTop = $(event.currentTarget).scrollTop();

        $stickies.each(function(i) {            

            var $thisSticky = $(this),
                $stickyPosition = $thisSticky.data('originalPosition'),
                $newPosition,
                $nextSticky;

            if ($stickyPosition <= $scrollTop) {

                $newPosition = Math.max(0, $scrollTop - $stickyPosition);
                $nextSticky = $stickies.eq(i + 1);

                if($nextSticky.length > 0) {

                    $newPosition = Math.min($newPosition, ($nextSticky.data('originalPosition') -  $stickyPosition) - $thisSticky.data('originalHeight'));
                }

            } else {

                $newPosition = 0;
            }

            $thisSticky.css('transform', 'translateY(' + $newPosition + 'px)');

            //could just as easily use top instead of transform
            //$thisSticky.css('top', $newPosition + 'px');
        });
    };

    return {
        load: load
    };
})();

$(function() {
    stickyHeaders.load($(".followMeBar"), $(window));
});

下面是另一个示例,展示了如何在使用固定标题时获得偏移量:


我尝试了上面提供的解决方案,但没有一个解决方案在没有bug的情况下能够完美工作(主要是滚动和浏览器兼容性方面的bug)。
刚刚找到这个,它对我很好。

解决方案的基本版本:

CSS

HTML

范例


玩得开心:)

如果div上面有带有粘性标题的内容,那么这并不总是很有效:

$thisticky.css('transform','translateY('+$newPosition++'px');

但这句话起了作用

//可以很容易地使用top而不是transform
$thisticky.css('top',$newPosition+'px');

chris spittles提供的解决方案帮了我很大的忙,但我也想提供一个普通的Javascript解决方案。此外,我还添加了一些功能,用于处理最后一个粘滞的问题,如果您不希望它继续通过其内容区域进行修复

constStickySubsections=(函数(){
让艾尔
返回{
元素:函数(){
返回{
胶粘物:[…document.queryselectoral('.followMeBar')]
}
},
init:函数(){
el=this.elements()
this.load()
},
加载:函数(){
this.setupStickyWrap()
window.addEventListener('scroll',()=>this.whenScrolling())
},
setupStickyWrap:函数(){
el.stickies.forEach((sticky,i)=>{
const stickyWrap=this.addWrap(sticky,“sticky wrap”)
const heightToTop=sticky.getBoundingClientRect().top+window.scrollY
const outerHeight=粘滞。偏离视线
stickyWrap.parentElement.id=
.followMeBar {
    background: #999;
    padding: 10px 20px;
    position: relative;
    z-index: 1;
    color: #fff;
}

/* For aesthetics only */

body {
    margin: 0;
    font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
}
.sectionWrapper{
    background-color: #1E1E1E;
    padding: 10px 20px;
    color: #FF7B05;
    width: 100%
    height: 45px;
    min-height: 45px;

    margin-top: 30px;   
    position: relative;
    z-index: 10;
}
.sectionHeader{
}
.sectionEmbed {
}
.sectionFixed {
    background-color: #1E1E1E;
    padding: 10px 20px;
    color: #FF7B05;
    width: 100%;
    height: 45px;

    position: fixed;
    top: 0;
    left: 0;
    margin: 0;
}
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 sectionWrapper sectionEmbed">
    <div class="sectionHeader">Headers here</div>
</div>
//check doc is ready
$(function() {
    $(window).on("scroll.sectionWrapper", function() {
        stickSections();
    });
});

//function stickSection
function stickSections()
{
    //detach the listener
    $(window).off("scroll.sectionWrapper");

    $scrollPos = $(window).scrollTop();
    $currentSticky = null;

    $('.sectionWrapper').each(function(){

        $(this).children().removeClass('sectionFixed');     

        if($scrollPos >= ($(this).offset().top - ($(this).height() - $(this).children().height() - 6)) ){
            $currentSticky = $(this);
        }
        else $(this).children().addClass('sectionEmbed');
    });

    //apply the fixed class to our scrollPos match
    if($currentSticky) $currentSticky.children().addClass('sectionFixed');

    //reattach the listener
    $(window).on("scroll.sectionWrapper", function() {
        stickSections();        
    });
}
const StickySubsections = (function(){
  let el

  return {
    elements: function () {
      return {
        stickies: [...document.querySelectorAll('.followMeBar')]
      }
    },

    init: function () {
      el = this.elements()
      this.load()
    },

    load: function () {
      this.setupStickyWrap()
      window.addEventListener('scroll', () => this.whenScrolling())
    },

    setupStickyWrap: function(){
      el.stickies.forEach((sticky, i) => {
        const stickyWrap = this.addWrap(sticky, 'sticky-wrap')
        const heightToTop = sticky.getBoundingClientRect().top + window.scrollY
        const outerHeight = sticky.offsetHeight

        stickyWrap.parentElement.id = `sticky-content-${i}`
        sticky.setAttribute('data-originalPosition', heightToTop)
        sticky.setAttribute('data-originalHeight', outerHeight)

        stickyWrap.style.height = outerHeight + 'px'
      })
    },

    addWrap: function(el, className, wrap = 'div') {
      const wrapper = document.createElement(wrap)
      wrapper.classList.add(className)
      el.parentNode.insertBefore(wrapper, el)
      wrapper.appendChild(el)
      return wrapper
    },

    elementExists: function(el){
      return typeof(el) != 'undefined' && el != null
    },

    stickyPosition: function(el){
      return el.getAttribute('data-originalPosition')
    },

    nextStickyPosition: function(current, next){
      return next.getAttribute('data-originalPosition') - current.getAttribute('data-originalHeight')
    },

    scrollingPositionTop: function(el){
      return el.getBoundingClientRect().top + window.scrollY
    },

    offsetTop: function(el){
      return el.getBoundingClientRect().top
    },

    scrollingPositionBottom: function(el){
      return el.getBoundingClientRect().bottom + window.scrollY
    },

    headerPosition: function(){
      return window.scrollY
    },

    bottomSectionHit: function(contentElement, sticky){
      const contentSection = document.getElementById(contentElement)
      const sectionBottom = contentSection.getBoundingClientRect().bottom + window.scrollY
      const stickyPositionScrolling = sticky.getBoundingClientRect().bottom + window.scrollY

      return stickyPositionScrolling >= sectionBottom
    },

    whenScrolling: function() {
      el.stickies.forEach((sticky, i) => {
        const nextSticky = el.stickies[i + 1]
        const prevSticky = el.stickies[i - 1]

        if (this.stickyPosition(sticky) <= this.headerPosition()) {
          sticky.classList.add('fixed')

          if (this.elementExists(nextSticky)) {

            while (this.scrollingPositionBottom(sticky) >= this.nextStickyPosition(sticky, nextSticky) + 50) {
              sticky.classList.add('absolute')
              sticky.style.top = this.nextStickyPosition(sticky, nextSticky)
            }

          // Handle last sticky element
          } else {
            if (this.bottomSectionHit(`sticky-content-${i}`, sticky)) {
              sticky.classList.remove('fixed')
            }
          }

        } else {

          sticky.classList.remove('fixed')

          if (this.elementExists(prevSticky) && window.scrollY <= this.stickyPosition(sticky)){
            prevSticky.classList.remove('absolute')
            prevSticky.removeAttribute('style')
          }
        }
      })
    }

  }
}())

StickySubsections.init()