Функция JavaScript для управления пользовательскими свойствами CSS, не работающими с $ (window) .resize () - PullRequest
0 голосов
/ 05 октября 2019

У меня есть фиксированный заголовок с :target привязками на странице, и мне нужно динамически корректировать значения свойств с помощью JavaScript или JQuery, чтобы поддерживать соответствующую позицию :target непосредственно под заголовком при изменении размера окна, адаптируясь к изменениям как высоты .container предыдущего раздела, так и высоты .header_container, которые происходят при изменении размера.

Самым простым решением представляется псевдоэлемент ::before для псевдо :target-class, а затем использовать пользовательские свойства CSS для динамического изменения свойств стиля.

У меня нет проблем с правильным размещением :target с помощью указанной ниже функции при загрузке (или перезагрузке) страницы или правильным размещением первого :target на $(window).resize(), однако он не может сделать то же самоедля оставшихся целей на $(window).resize().

Скрипки

Упрощенный код: https://jsfiddle.net/chayanyc/g6p3549s/

Адаптивный дизайн (упрощенный): https://jsfiddle.net/chayanyc/wuk92dns/

Фрагменты кода

CSS:

.header_container {height: 98px; margin: 0; padding: 0; position: fixed; top: 0; display: block; z-index: 100;}
.main {margin-top: 98px; width: 100%;}
:target::before {height: var(--target_position1); margin-top: var(--target_position2); content: ""; display: block; visibility: hidden;}

JavaScript:

var headerHeight;

function setTarget() {
    headerHeight = document.getElementById('header').offsetHeight;
    headerHeight1 = headerHeight + "px";       
    document.documentElement.style.setProperty('--target_position1', headerHeight1);
    document.documentElement.style.setProperty('--target_position2', '-' + headerHeight1);
}

$(window).resize(function () {
    setTarget();
});

$(document).ready(function () {
    setTarget();
});

Ответы [ 2 ]

1 голос
/ 06 октября 2019

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

нет необходимости в этой части CSS (удалить ее)

:target::before {margin: 0; content: ""; dis.....

и измените свой jQuery на:

$(document).ready(function () {

  // global info for menu -> target elememt
  var InfoTarget = { ID: null, tempo:300 }

  $('a').click(function(evt){
    InfoTarget.ID = $(this).attr('href') // possible target elm

    // check if InfoTarget.ID exist on page
    let nbElements = 0
    try        { nbElements = $(InfoTarget.ID).length  }
    catch(err) { nbElements = 0 }

    if ( nbElements != 1 ) {
      InfoTarget.ID = null  // not target element found
    }
    else {
      evt.preventDefault()   // disable auto scroll to target element  

      $('html').animate({
          scrollTop: ($(InfoTarget.ID).offset().top - $('#header').outerHeight(true))
      }, InfoTarget.tempo  );
    }
  });

  $(window).resize(function (){
    if (InfoTarget.ID) {  // if InfoTarget.ID exist <=> InfoTarget.ID != null
      $('html').animate({
        scrollTop: ($(InfoTarget.ID).offset().top - $('#header').outerHeight(true))
      }, InfoTarget.tempo);
    }
  });

});

Мой код говорит сам за себя, но вот полное объяснение:

принцип прост: функция target css активируется по щелчкупо ссылке <a href="#..."> для запуска прокрутки страницы в направлении элемента, имеющего для id = значение, содержащееся в начальном href.

, поэтому этот код перехватывает любой щелчок по ссылке на странице и сначала должен определитьявляется ли это ссылкой на якорь или нет.

Чтобы определить, является ли это ссылкой на якорь на странице, он просто проверяет, имеет ли элемент страницы это значение как ID, (// check if InfoTarget.ID exists on page).
Поскольку этот вид теста также может выдавать ошибку, этот тест помещается в try / catch.

Если результат действительно является привязкой, действие щелчка отменяется (с evt.preventDefault()), что не позволяет браузеру запускать автоматический переход к ссылке;

ссылкассылка хранится в объектной переменной (глобальной)

var InfoTarget = {ID: null, tempo: 300}

при просмотре: InfoTarget.ID = $(this).attr('href') // possible target elm

остальное просто, нужно прокрутить вниз до якоря. В зависимости от ширины страницы и предыдущих элементов браузеры непрерывно пересчитывают позицию каждого тега, присутствующего на странице, и jQuery может получить эту позицию смещения на $(element).offset().Top

, так как на вашей панели меню естьДля страницы, которая маскирует верхнюю часть страницы, вы должны вычесть ее высоту из позиции в свитке (= $ ('# header'). outerHeight (true))
a scroll = 0 приведет к перемещению к вершинеpage
a scroll = $(element).offset().top помещает element вверху страницы, на которую мы должны вычесть высоту #header

, полная формула составляет

scrollTop: ($ (InfoTarget.ID) .offset (). top - $ ('# header'). outerHeight (true))

эта команда помещается в jQuery.animate длявизуально более плавное перемещение и использует значение InfoTarget.tempo в качестве продолжительности этой анимации.

Во время изменения размера страницы и в той степени, в которой ссылка, имеющая цель, была предварительно нажата (поэтому всегда активна)затем запускается тот же тип прокрутки.

Различные используемые методы jQuery описаны в документе jQuery (например: https://api.jquery.com/outerHeight/)

Новое решение - Lundi 14 октября 2019 / 01:00 (в ночь на воскресенье / понедельник)

этот скрипт должен быть помещен после всех html-элементов тела

// scroll to target upon window.location.hash 
$(window).on('hashchange', function() {
  $('.TargetMark').removeClass('TargetMark')
  $(window.location.hash).addClass('TargetMark')

  setTimeout( scrollTop2, 220 )  // scroll to target after browser auto scrolling conflit
})

function scrollTop2() {
  if ($('.TargetMark').length===1) { // if target exist
    $('html').animate({
        scrollTop: ($('.TargetMark').offset().top - $('#header').outerHeight(true))
    }, 100);
  }
}

В этой версии цельдобавлен элемент (TargetMark), позволяющий найти его при изменении размера окна

конечная часть

$(document).ready(function () {
  //...
  // --------------------------->  no call to scrollTop();
  //...
});

$(window).resize(function () {
  //...
  scrollTop2();
  //...
});

о конфликте toggleMenu:

function toggleMenu() {
  $('.navbar-toggle').on('click', function () {
    if ($("#js-menu").is(".expand")) {
      $("#js-menu").toggleClass("expand");
      $("#submenu").removeClass("active_sub").addClass("inactive_sub");
    } else {
      $("#js-menu").toggleClass("expand");
      $("#submenu").removeClass("inactive_sub").addClass("active_sub");
    }
    resetTarget();
    setTimeout( scrollTop2, 220 )  // scroll to target after browser auto scrolling conflit
  });
}


я потратилМного времени уделяя вашему вопросу, я изучал разные подходы и различные автоматы, применяемые самими навигаторами, и с которыми нужно бороться, чтобы получить результат, который вы ищете. Я пришел к выводу, что проблема в первую очередь связана с архитектурой вашей страницы.
Тот факт, что меню ("#header") покрывает страницу ("#main"), является серьезным недостатком, препятствующим эффективному использованию. JS-код для вашего вопроса.
Вызов хэша привязки запускает одну или несколько прокруток страницы, изменение размера страницы также влечет за собой вычисление прокрутки, поскольку при изменении размера на экране также изменяется размерстраница. страница (уменьшение размера экрана вдвое приводит к удвоению размера страницы), то же самое происходит при изменении размера шрифта, а также при изменении размера страницы.
Всякий раз, когда изменяется размер страницы, браузер должен пересчитать много вещей, и некоторые из этих механизмов могут вызвать одну или несколько прокруток.
Здесь вы просите пересчитать позиционирование страницы в соответствии с элементом, который мы не можемуверен, что он полностью установлен, потому что этот процесс выполняется параллельно с другими процессами браузера, которые могут изменять полезные значения.
Плюс тот факт, что некоторые процессы браузера также работают для прокрутки страницы и что он может быть последнимготово!
Таким образом, тот факт, что меню и страница перекрываются, увеличивает сложность и делает невозможным решение проблемы. Измените свой макет, и 3/4 вашей проблемы будет исправлено.
0 голосов
/ 05 октября 2019

Изменение размера стреляет, высота смещения не меняется. Установка одного и того же значения снова и снова не дает никаких изменений. Вы можете проверить это:

см. Изменение значения

Я использовал логотип для вывода:

$('.logo').text(headerHeight + ' -' + i++);

Вы хотите прокрутитьвплоть до одного деления, выбранного целью, без наложения его на вашу навигацию?

.. затем расширяйте области. см. Здесь добавьте положительный margin-top и отрицательный padding-top.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...