Код jQuery работает в Safari, но не в Firefox

Я пытаюсь использовать смесь jQuery и CSS, чтобы песок в песочных часах казался текущим, когда вы прокручиваете страницу вниз. В основном у меня есть два «песочных» изображения, и я использую jQuery для изменения высоты их контейнеров по мере прокрутки пользователя.

<!-- Load jQuery -->
  <script src="jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>

  <!-- Handle Hourglass Scrolling -->
  <script type="text/javascript" charset="utf-8">
   $(document).ready(function(){

    // Set value of topStart and bottomStart to equal to y-position of the equivilent divs
    var topStart = parseInt($('#top-sand').css('top'));
    var bottomStart = parseInt($('#bottom-sand').css('top'));

    // Calculate the maximum height of the sand relative to the window size
    var sandHeight = $(window).height()*0.22;

    // setValues sets positions based on window size
    function setValues() {
     topStart = parseInt($('#top-sand').css('top'));
     bottomStart = parseInt($('#bottom-sand').css('top'));
     sandHeight = $(window).height()*0.22;
     var hourglassWidth = $('#hourglass #outline img').css('width');
     var leftMargin = $(window).width()*0.5+ 320;

     $('#top-sand').height(22+"%");
     $('#top-sand img').height(sandHeight)
     $('#bottom-sand img').height(sandHeight)
     $('#hourglass').css({left:leftMargin+"px"})
     $('#trace').text(hourglassWidth)


     // contentMarginLeft = $('#hourglass #outline').width();
     //  $('#content').text(contentMarginLeft);
     // css({"margin-left": contentMarginLeft + "px"});
    };

    setValues();

    // This listens for a window scroll event and then handles the height and position of the sand in the Hourglass
       $(window).scroll(function () {

     // Calculating the position of the scrollbar
     var doc = $("body"), 
         scrollPosition = $("body").scrollTop(),
         pageSize = $("body").height(),
      windowSize = $(window).height(),
      fullScroll = pageSize - windowSize;
         percentageScrolled = (scrollPosition / fullScroll);

     // Calculating the Y-positions of the two sand piles
     var topPosition = topStart+(22*percentageScrolled);
     var bottomPosition = bottomStart-(22*percentageScrolled);

     // Updating the sand piles
          $('#top-sand').height(22-(22*percentageScrolled)+"%")
           .css({top: topPosition+"%"});
      $('#bottom-sand').height(22*percentageScrolled+"%")
          .css({top:bottomPosition+"%"});

       });

    // This listens for a window resize event and then reconfigures the layout
    $(window).bind('resize', function() {
     // Reconfigure layout
    });

     });
  </script>

Он отлично работает в Safari (хотя время от времени возникает сбой, когда высота верхнего изображения меняется, а его положение y — нет), но в Firefox он вообще не работает. Вы можете увидеть сайт здесь http://www.chris-armstrong.com/ticktalk

Я новичок в jQuery, поэтому извиняюсь, если это полная ошибка нуба.

Заранее спасибо.


person Chris Armstrong    schedule 11.01.2010    source источник
comment
отредактируйте и переформатируйте блок кода.   -  person sberry    schedule 12.01.2010
comment
ОК, кажется, отформатирован прямо сейчас (спасибо cmcculloh)   -  person Chris Armstrong    schedule 12.01.2010
comment
в качестве примечания (не решения вашей проблемы), ВСЕГДА указывайте систему счисления при использовании parseInt(), иначе позже вы столкнетесь с отвратительными, очень трудными для отладки ошибками: parseInt('123' , 10) вместо parseInt('123') - javascript имеет неприятную функцию, которая автоматически определяет основание для вас, если вы его не укажете.   -  person Tamas Czinege    schedule 12.01.2010
comment
Основа... никогда раньше не слышала об этом... быстрый поиск в Википедии подсказал мне, что это основа, так что я предполагаю, что создание системы счисления 10 сохраняет ее десятичной или что-то в этом роде?   -  person Chris Armstrong    schedule 12.01.2010
comment
Крис Армстронг: Точно. Вы не хотите, чтобы javascript случайно анализировал «0123» как восьмеричный.   -  person Tamas Czinege    schedule 12.01.2010
comment
@Chris Во-первых, УБИЙСТВЕННЫЙ ДИЗАЙН, обожаю его! Во-вторых, я играю с этим и надеюсь получить ответ для вас, когда я закончу.   -  person Doug Neiner    schedule 12.01.2010


Ответы (2)


Хорошо, я заработал! Вам придется взглянуть на мой источник, чтобы увидеть, что я сделал, потому что я так сильно изменился, но в основе вашей проблемы лежит тот факт, что элемент «прокручиваемый» отличается на разных платформах/браузерах.

Иногда это элемент html, иногда это элемент body. Я использовал несколько строк кода из scrollTo Plugin, чтобы позаботиться об этом. . Я использовал CSS для позиционирования песочных часов. И я использовал цветные блоки div, чтобы создать впечатление, что песок движется. Вам больше не нужно обрабатывать события изменения размера браузера (которые свели бы вас с ума в IE, поверьте мне :)

Вот рабочая демонстрация.

Я тестировал в Safari и FF на Mac, но в IE7+ все должно работать корректно.

Вот код jQuery (не включая фрагмент из scrollTo):

<script type="text/javascript">
  $(function(){
    var low      = 28,
        high     = 50,
        max      = 86.5,
        range    = high - low, 
        $mtop    = $("#mask-top"),
        $mbottom = $("#sandy-bottom")
        scroller = $()._scrollable(); // Uses part of the scrollTo plugin

    $(window).scroll(function(e){
      var scrollTop  = $(scroller).scrollTop(),
          bodyHeight = document.body.scrollHeight,
          itemHeight = $('#outline').outerHeight();

      var percentScrolled = scrollTop / (bodyHeight - itemHeight);
      percentScrolled = Math.floor(percentScrolled * 100) / 100;

      var newHeight = (range * percentScrolled);
      newHeight =  Math.floor(newHeight * 10) / 10;

      $mtop.height( (newHeight + low) + "%" );
      $mbottom.css( 'top', (max - newHeight) + "%" );
    })
  })
</script>

Вот обновленный HTML, который я переместил в дочерний элемент body:

<div id="hourglass">
    <img id="outline" src="img/hourglass-outline.png" width="634" height"1080" alt="Hourglass Outline" />
    <!-- A new image I created based on your two-->
    <img id="sandy" src="hourglass-insides.png" width="634" height="1080" />
    <div class="mask" id="mask-top" ></div>
    <img id="sandy-bottom" src="hourglass-insides.png" width="634" height="1080" />
</div>

И для тех, кто хочет посмотреть, вот CSS, который я использовал для позиционирования песочных часов:

<style type="text/css" media="screen">
  #hourglass {
    left: 0; top: 0; bottom: 0; right: 0;
  }
  #outline, #sandy, #sandy-bottom {
    position: fixed;
    top: 0;
    height: 100%;
    left: 50% !important;
    margin: 0;
    margin-left: 215px;
    max-height: 100%;
    min-height: 100%;
    width: auto;
  }

  #sandy {
    top: -32%;
  }

  #sandy-bottom {
    top: 86.5%;
  }

  .mask {
    background: #262B28;
    position: fixed;
    width: 100%;
    left: 0;
    right: 0;
  }
  #mask-top {
    top: 0;
    height: 28%;
  }
</style>
person Doug Neiner    schedule 12.01.2010
comment
Упс! Только что понял, что изменил ваш дизайн... исправлю сейчас. - person Doug Neiner; 12.01.2010
comment
ОК, исправлено. Теперь это действительно похоже на вашу оригинальную анимацию :) Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы. - person Doug Neiner; 12.01.2010
comment
Вау, спасибо... теперь попробуем разобраться, что все изменить. но одно но, когда я открываю его в полноэкранном режиме (у меня разрешение 1920 x 1200), песок неуместен. Любая идея, почему это было бы? Спасибо еще раз - person Chris Armstrong; 13.01.2010
comment
@Chris, у меня было фиксированное смещение в пикселях вместо процентов. Я обновил свою демонстрацию, чтобы отразить это изменение, и я также обновляю свой ответ здесь. - person Doug Neiner; 13.01.2010
comment
@Doug, спасибо, сейчас я просто пытаюсь реализовать ваши изменения, но где-то ошибаюсь... chris-armstrong.com/ticktalk2 Я добавил еще несколько функций для обработки карт и т. д. Могут ли они мешать вашему коду? - person Chris Armstrong; 18.01.2010
comment
@Chris, вам просто нужно загрузить это изображение: pixelgraphics.s3.amazonaws .com/stackoverflow/2045742/ и загрузите и обновите элемент img, чтобы он отражал правильный путь. Он должен работать иначе. - person Doug Neiner; 18.01.2010

Некоторые мысли для размышления:

  1. Предпочитайте методы позиционирования jQuery для прямого доступа к значениям CSS. Например, используйте .offset(), .position() и т. д. вместо .css("top"). Методы jQuery более переносимы между браузерами и будут возвращать числа, а не строки. См. http://docs.jquery.com/CSS.

    Показательный пример: topStart = parseInt($('#top-sand').css('top')) выше и многие другие.

  2. Если вам необходимо получить метрику позиционирования с помощью атрибута CSS, обязательно

    (1) всегда преобразовывать его в число, например. с parseInt(). Строки JavaScript незаметно преобразуются — или нет — в числа неясными способами. Всегда четко указывайте, что вы хотите рассматривать как число.

    (2) учитывать случай, когда в значении CSS есть единицы, например. как в «100px».

    Пример: var hourglassWidth = $('#hourglass #outline img').css('width') выше.

  3. Следите за дробными значениями. В $('#hourglass').css({left:leftMargin+"px"}) выше, что произойдет, если leftMargin не является целым числом (имеет десятичную точку?)

  4. Лучше всего использовать firebug в один шаг и наблюдать за переменными позиционирования, когда они меняются от строки к строке, и сравнивать их с вашими ожиданиями.

person Oren Trutner    schedule 12.01.2010