Хобрук: Ваш путь к мастерству в программировании

Элементы HTML следуют друг за другом по пути SVG с помощью javascript

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

Я создал codepen, демонстрирующий, что у меня есть на данный момент: http://codepen.io/mikes000/pen/GIJab

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

Есть ли способ заставить их оставаться на одном и том же расстоянии при движении вдоль линии?

Спасибо!

Обновлять**

После некоторого дальнейшего возни я обнаружил, что изменение расстояния, по-видимому, вызвано тем, что соотношение сторон окна просмотра SVG увеличивается для X больше, чем для Y. Когда он растягивается по оси X, 1 пиксель вниз по линии может стать 3 пиксель на экран.

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

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

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

Любые идеи, как это сделать, или какие-либо идеи о лучшем способе решения этой проблемы?

13.06.2014

  • Почему бы просто не использовать элементы SVG? А что не так с тем, что у вас есть (т.е. с предполагаемым поведением)? 17.06.2014
  • Предполагаемое поведение состоит в том, чтобы красные точки находились точно впереди и позади квадрата, но они удаляются дальше друг от друга при движении вдоль оси x. В будущем я планирую заменить квадраты изображениями или другим типом контента. 17.06.2014
  • Чтобы добиться того, что вы предложили, вы должны поддерживать постоянную скорость и рассчитывать x и y при движении по пути. Однако текущий алгоритм поддерживает согласованность только delta_x. Это заставляет объекты отделяться друг от друга, когда наклон небольшой. 20.06.2014

Ответы:


1

Взгляните на http://jsfiddle.net/4LzK4/.

var svg = d3.select("#line").append("svg:svg").attr("width", "100%").attr("height", "100%");
var data = d3.range(50).map(function(){return Math.random()*10})
var x = d3.scale.linear().domain([0, 10]).range([0, 700]);
var y = d3.scale.linear().domain([0, 10]).range([10, 290]);
var line = d3.svg.line()
  .interpolate("cardinal")
  .x(function(d,i) {return x(i);})
  .y(function(d) {return y(d);})

var path = svg.append("svg:path").attr("d", line(data));
var circle = 
    svg.append("circle")
      .attr("cx", 100)
      .attr("cy", 350)
      .attr("r", 3)
      .attr("fill", "red");

var circleBehind = 
    svg.append("circle")
      .attr("cx", 50)
      .attr("cy", 300)
      .attr("r", 3)
      .attr("fill", "blue");

var circleAhead = 
    svg.append("circle")
      .attr("cx", 125)
      .attr("cy", 375)
      .attr("r", 3)
      .attr("fill", "green");

var pathEl = path.node();
var pathLength = pathEl.getTotalLength();
var BBox = pathEl.getBBox();
var scale = pathLength/BBox.width;
var offsetLeft = document.getElementById("line").offsetLeft;
var randomizeButton = d3.select("button");

svg.on("mousemove", function() {
  var x = d3.event.pageX - offsetLeft; 
  var beginning = x, end = pathLength, target;
  while (true) {
    target = Math.floor((beginning + end) / 2);
    pos = pathEl.getPointAtLength(target);
    if ((target === end || target === beginning) && pos.x !== x) {
        break;
    }
    if (pos.x > x)      end = target;
    else if (pos.x < x) beginning = target;
    else                break; //position found
  }
  circle
    .attr("opacity", 1)
    .attr("cx", x)
    .attr("cy", pos.y);

  posBehind = pathEl.getPointAtLength(target-10); 
  circleBehind
    .attr("opacity", 1)
    .attr("cx", posBehind.x)
    .attr("cy", posBehind.y);

  posAhead = pathEl.getPointAtLength(target+10); 
  circleAhead
    .attr("opacity", 1)
    .attr("cx", posAhead.x)
    .attr("cy", posAhead.y);

});

randomizeButton.on("click", function(){
  data = d3.range(50).map(function(){return Math.random()*10});
  circle.attr("opacity", 0)                                     
  path
    .transition()
    .duration(300)
    .attr("d", line(data));
});

Вместо того, чтобы самостоятельно вычислять положения кругов сзади и впереди, используйте getPointAtLength относительно центра объекта, который должен оставаться посередине.

Источник вдохновения: http://bl.ocks.org/duopixel/3824661

23.06.2014
  • Я использую метод getPointAtLength, который вы описали в примере. Проблема заключается в том, что при перемещении точки на 10 пикселей позади строки из-за растягивания соотношения сторон окна просмотра SVG 10 пикселей становятся больше, чем 10 пикселей на реальном экране. 23.06.2014
  • Новые материалы

    Освоение информационного поиска: создание интеллектуальных поисковых систем (глава 1)
    Глава 1. Поиск по ключевым словам: основы информационного поиска Справочная глава: «Оценка моделей поиска информации: подробное руководство по показателям производительности » Глава 1: «Поиск..

    Фишинг — Упаковано и зашифровано
    Будучи старшим ИТ-специалистом в небольшой фирме, я могу делать много разных вещей. Одна из этих вещей: специалист по кибербезопасности. Мне нравится это делать, потому что в настоящее время я..

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..