#d3.js #scroll
#d3.js #прокрутка
Вопрос:
Я использую библиотеку javascript scrollama для написания статьи «scrollytelling», которая включает в себя переход к графикам D3 и из поля зрения при прокрутке пользователем. В основном это работает, но графики накладываются друг на друга, если я прокручиваю слишком быстро.
Вот jsfiddle, основанный на этом примере автором scrollama. В моем примере цветные точки должны исчезать по одной за раз. Если вы должны были быстро прокручивать до конца, прерывистые точки не должны отображаться. Следующие фрагменты показывают, как я настроил переходы:
Я определяю некоторые функции, которые создают мои «графики», а затем вызываю их.
var makeCircle0 = function(){
g.append("circle")
.attr("cx", 50)
.attr("cy", 100)
.attr("r", 20)
.attr("fill", "red")
.attr("class", "redcircle")
g.selectAll(".redcircle")
.attr("opacity", 0)
}
makeCircle0();
// Do this for makeCircle1, 2, and 3, also.
Затем я создаю функции для обработки переходов. В этом говорится, что красный круг исчезает, а остальные круги имеют непрозрачность 0. Я делаю это для всех кругов / этапов.
var showCircle0 = function(){
g.selectAll(".redcircle")
.transition()
.duration(1000)
.attr("opacity", 1)
g.selectAll(".yellowcircle").attr("opacity", 0)
g.selectAll(".greencircle").attr("opacity", 0)
g.selectAll(".bluecircle").attr("opacity", 0)
}
В этом разделе создается массив моих функций перехода, чтобы я мог вызывать их на определенных этапах страницы при прокрутке. Это похоже на то, как Джим Валландингем работал со своим скроллером.
var activateFunctions = [];
activateFunctions[0] = showCircle0;
activateFunctions[1] = showCircle1;
activateFunctions[2] = showCircle2;
activateFunctions[3] = showCircle3;
Наконец, это вызывает нужную функцию на нужном шаге страницы. Что он и делает… но не без остановки других переходов, которые были запущены на предыдущем шаге, что приводит к появлению нескольких точек на разных этапах.
function handleStepEnter(response) {
step.classed('is-active', function (d, i) {
return i === response.index;
})
figure.call(activateFunctions[response.index])
}
Как я могу это предотвратить?
Комментарии:
1. Я думаю, это то, что вы ищете (переход не совсем совпадает с сегментами слева, но круги соответствуют числам). Это правильно?
2. @AndrewReid это здорово! Итак, все, что вы сделали, это сначала «interrupt ()», прежде чем начинать какие-либо новые переходы?
3. В значительной степени — interrupt() отменит любые переходы при выборе.
4. Хорошо, интересно. Если у меня есть несколько классов, которые могут переходить (например, redcircle, yellowcircle и т. Д.) Мне пришлось бы прерывать их все?
5. Если есть риск, что они все еще переходят — вот почему я использовал class для выбора их всех и id для выбора одного по отдельности.
Ответ №1:
Если вам нужно прервать переход, в d3-transition есть метод для этого:
selection.interrupt();
Это отменит переход в выделенном элементе. При использовании именованных переходов вы можете указать имя, предоставив прерыванию один аргумент, указывающий имя перехода для отмены.
Если это общая версия вашей функции для отображения элемента:
function show() {
selectionToHide.attr("opacity",0);
selectionToShow.transition()
.attr("opacity",1);
}
Без использования selection.interrupt вы устанавливаете непрозрачность на ноль, а затем следующий тик любого выполняемого перехода продолжает обновлять непрозрачность и завершает выполнение перехода. Добавляя прерывание, мы избегаем этого. Вот обновленная скрипка.
Однако есть другое решение — мы можем применить другой переход к элементам, которые мы хотим не показывать. Для этого мы просто заменяем переход на новый:
function show() {
selectionToHide.transition()
.attr("opacity",0);
selectionToShow.transition()
.attr("opacity",1);
}
Это заменит существующие неназванные переходы (поскольку у вас нет имен) и элементы будут исчезать, а не просто скрывать их все сразу. Вот пример этого. Конечно, если у вас много элементов, это можно уточнить, чтобы применять переход только к любым элементам, которые переходят (а не к тем, которые уже скрыты), чтобы уменьшить количество активных переходов.
Я не касался прокрутки, показанный круг должен иметь индекс, соответствующий отображаемому числу, но, похоже, число не всегда соответствует позиции прокрутки, но это отдельная проблема
Комментарии:
1. Это здорово! Будет ли это работать, если есть задержка () как часть перехода?
2. Так и должно быть — задержка является частью перехода, при замене или прерывании перехода вы удаляете весь предыдущий переход, включая задержку.
3. Я могу продемонстрировать, что задержка ни на что не повлияет — вот скрипка, показывающая как прерывание, так и замену перехода на новый. Начальный переход изменяет радиус после задержки, но он никогда не запускается, поскольку он отменяется / заменяется.
4. @GerardoFurtado, спасибо! Подходит только для 1000-го — если я не ошибаюсь, я полагаю, что я дал вам ваш чуть более 2 лет назад, когда я был еще довольно свежим. С нетерпением жду возможности закрыть как обман — обычно с менее чем 5 постоянными пользователями в d3, как правило, ждали, когда вы выйдете в Интернет и увидите это.
5. @GerardoFurtado, я имел в виду просто обычный золотой значок для людей d3 или что-то еще, было трудно достичь порога в пять голосов за обман (или по любой другой близкой причине, если на то пошло) без поддержки gold из-за того, как мало постоянных пользователей. Но теперь, когда Alto со дня на день получит золото, надеюсь, ведение домашнего хозяйства станет немного проще.