2015-05-11 3 views
1

У меня есть немного неприятная проблема.Позиционирование элементов SVG через .getBoundingClientRect() в переменной ширине div

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

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

Я пытаюсь использовать .getBoundingClientRect(), чтобы получить позиции, поскольку текстовые элементы преобразуются в позицию (так что .getBBox() не является опцией), а не позиционируется по атрибутам x и y.

С .getBoundingClientRect(), я могу получить правильный размер/расположение новых элементов, но так как ширина SVG-содержащего div является переменной, всегда есть немного странное смещение, которое я не могу учитывать.

Я создал упрощенный пример моей проблемы here. Измените размер и обновите страницу, чтобы увидеть проблему в действии.

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

var circs = theSvg.selectAll("circle") 
    .data(theCircles) 
    .enter() 
    .append("circle") 
    .attr("r", 15) 
    .attr("fill", "#f00") 
    .style("opacity", 0.3) 
    .attr("transform", function(d){ 

     var sizeDif = 800/(d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["width"]); 

     var theNum = parseInt(d.split("&")[1]); 
     var thePosition = theSvg.selectAll("text").filter(function(e){ 
     return e == theNum;})[0]; 
     var theCoords = thePosition[0].getBoundingClientRect(); 

     var leftOffset = d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["left"]; 
     var leftOffset2 = d3.select(".svgTest")[0][0].getBoundingClientRect()["left"]; 
     var bottomOffset = d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["top"]; 
     var bottomOffset2 = d3.select(".svgTest")[0][0].getBoundingClientRect()["top"]; 

     return 
     "translate(" + ((theCoords["left"] - leftOffset - leftOffset2) 
     * sizeDif) + "," + ((theCoords["top"] - bottomOffset - bottomOffset2) 
     * sizeDif) + ")"; 
}) 

EDIT:

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

В моем случае мне пришлось использовать ряд последовательных преобразований, а не комбинацию преобразования и изменения положения x/y (из-за некоторых реалий проекта, не представленных в связанном примере). Но я рад, что нашел ответ!

ответ

2

Ваш пример отлично подходит для меня в Chrome. Но на самом деле это только потому, что SVG - единственное, что есть на странице. Если я добавлю текст над SVG, все пойдет не так.

https://jsfiddle.net/rrpfmm6d/1/

Является ли это проблемой вы говорите?

Если это так, причина в том, что вы делаете неправильный выбор при использовании getBoundingClientRect(). Он обеспечивает координаты в пространстве экрана. Это начало - верхний левый угол окна (или iframe в случае jsfiddle).

Вы должны использовать getBBox(). Возвращаемые значения находятся в том же координатном пространстве, что и элементы SVG. Это начало (обычно) в левом верхнем углу SVG.

Таким образом, используя координаты, возвращаемые по телефону getBBox(), на ваш <text> элемент для расчета местоположения для вашего круга. Если круги вставляются в тот же SVG, что и текст, не нужно будет корректировать смещения div или svg.

+2

Я понимаю, что теоретически getBBox() решит мою проблему, но поскольку я использовал преобразование на элементах, которые мне нужны, getBBox() не является решением. Вот почему я пытался позиционировать путем смещения в соответствии с getBoundingClientRect() и добавлением/вычитанием смещения родительских элементов по мере необходимости (см. [Обновленный скрипт] (https://jsfiddle.net/rrpfmm6d/3/)).Я искал альтернативы getBBox() для преобразованных элементов, включая применение матрицы преобразования SVG к текстовым элементам x и y (согласно [этому парню] (http://stackoverflow.com/a/18561829/3899852) решение). – Jess

+2

Вы говорите, что не можете использовать одни и те же преобразования, но почему вы не можете просто скопировать их из текстовых элементов? Например: https://jsfiddle.net/rrpfmm6d/5/ –

+1

Я немного поиграл с извлечением трансформирования, но не сделал этого так, как вы сказали, потому что я стараюсь избегать установки позиций cx и cy на круги (в фактической части), я уже трансформирую круги в соответствии с другим набором параметров, и поэтому стараюсь, чтобы cx и cy были равны 0. Я дам вашему предложению вращение, а также рассмотрю применение нескольких преобразований и отчетов. Благодаря! – Jess

Смежные вопросы