Невозможно выбрать элемент SVG ForeignObject в d3

Я работаю с силовым макетом d3 с метками узлов HTML, реализованными с элементами SVG foreignObject. Я хотел бы выбирать эти элементы в разное время, чтобы обновлять их позиции и другие свойства (и отслеживать их по мере их создания и уничтожения с помощью enter() и exit() ), но, похоже, я не могу выбрать их, как другие элементы SVG. .

Вот компактный пример:

HTML:

<html>
    <head>
        <title>Cannot Select SVG Foreign Object</title>
        <script src="http://d3js.org/d3.v2.js"></script>
        <script src = "fo_select.js"></script>
     </head>
     <body>
         <svg id="example_svg" width="600" height="600">
               <g>
                  <circle r="40" cx = "80" cy="80"></circle>
                  <foreignObject width = "100" height = "100" x = "200" y="200">
                         <body>Hello, world</body>
                  </foreignObject>
               </g>
         </svg>
         <script>run()</script>
     </body>
</html>

Javascript:

function run() {
    svg = d3.select("#example_svg");
    console.log(svg.selectAll("circle"));
    console.log(svg.selectAll("foreignObject"));
}

Это также доступно по адресу http://bl.ocks.org/3217448 . Вывод консоли:

[Array[1]]
[Array[0]] 

где первый массив содержит элемент circle, а второй пустой. Почему объект circle доступен для выбора, а foreignObject нет? Я предполагаю, что это связано с необычной природой foreignObject. Как бы я выбрал его, чтобы манипулировать им в моем коде? Большое спасибо.


person Ryan Gabbard    schedule 31.07.2012    source источник
comment
(Обновлено, чтобы удалить лишнюю опечатку с запятой)   -  person Ryan Gabbard    schedule 31.07.2012


Ответы (2)


Строго говоря, SVG чувствителен к регистру, поэтому вы должны использовать <foreignObject> вместо <foreignobject>.

Однако более серьезно то, что в WebKit есть открытая ошибка, которая не позволяет выбирать элементы camelCase.

Одним из возможных обходных путей является использование:

.selectAll(function() { return this.getElementsByTagName("foreignObject"); })

(Однако это может не работать в более старых версиях WebKit; см. уже закрытую ошибку WebKit 46800.)

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

person Jason Davies    schedule 31.07.2012
comment
Большое спасибо - зная, что это ошибка, я чувствую себя лучше. :-) Я просто использую выбор класса в качестве обходного пути. - person Ryan Gabbard; 31.07.2012
comment
Я получаю сообщение об ошибке Uncaught SyntaxError: не удалось выполнить запрос: «[object NodeList]» не является допустимым селектором. при использовании d3.selectAll(document.getElementsByTagName(foreignObject)). Но выбор по имени класса работает отлично. Спасибо. Это все еще кажется ошибкой в ​​​​Chrome 31. - person Alex KeySmith; 11.12.2013
comment
На самом деле, в предложенном мной обходном пути была ошибка. Я обновил его, чтобы использовать функцию, которая вызывается для каждого элемента выделения. Мое первоначальное предложение работало только для d3.selectAll, а не для selection.selectAll. - person Jason Davies; 12.12.2013
comment
Патч для этого был представлен год назад. Не задерживайте дыхание, чтобы исправить это в WebKit. - person jcollum; 14.01.2014

Вы должны иметь возможность использовать d3.selectAll("foreignObject") или svg.selectAll("foreignObject"). Это может быть дополнительная запятая в ваших атрибутах ForeignObject (между x и y). Я вставлял только элементы ForeignObject с помощью D3, так что, возможно, в их встраивании есть что-то другое.

person Elijah    schedule 31.07.2012