Скрипт получения координат для svg-линий
Вложений: 1
Уважаемы знатоки Jquery, прошу помощи в реализации скрипта.
Задача такая: есть 5 окружностей - одна в центре и 4 по-краям. Все они заданы через position: absolute в процентном отношении отступов. Необходимо рассчитать координаты линий, соединяющих эти окружности для svg line. Сложность в том, чтобы посчитать точки пересечения этих окружностей и линий. Сам алгоритм и его реализацию написал - все работает, скрин прилагаю. Но т.к. я в JS близок к нулю, реализовано все через одно место - для каждой координаты написаны свои правила, хотя уверен, что весь скрипт можно сократить ни в два и даже ни в три раза, при этом унифицировать его. Может кто-нить помочь? $(function(){ var slideSize = $('#slide-business'); var imgS1 = parseInt($('.circles img.img1').width()); var imgS2 = parseInt($('.circles img.img2').width()); var line1CoorX1 = parseInt($('.circles img.img1').css('left')); var line1CoorY1 = parseInt($('.circles img.img1').css('top')); var line2CoorX2 = slideSize.width()-parseInt($('.circles div.img2').css('right'))-imgS2/2; var line2CoorY2 = parseInt($('.circles div.img2').css('top'))+imgS2/2; var line3CoorX2 = slideSize.width()-parseInt($('.circles div.img3').css('right'))-imgS2/2; var line3CoorY2 = parseInt($('.circles div.img3').css('top'))+imgS2/2); var line4CoorX2 = parseInt($('.circles div.img4').css('left'))+imgS2/2; var line4CoorY2 = slideSize.height()-parseInt($('.circles div.img4').css('bottom'))-imgS2/2; var line5CoorX2 = parseInt($('.circles div.img5').css('left'))+imgS2/2; var line5CoorY2 = slideSize.height()-parseInt($('.circles div.img5').css('bottom'))-imgS2/2; // Для правых кругов (X2 > X1). Математический расчет координат var line2Angle = Math.atan2(line2CoorX2-line1CoorX1,line1CoorY1-line2CoorY2); // Находим угол для линии 2 var line2SideX1 = Math.abs(Math.sin(line2Angle)*(imgS1/2)); // Находим сдвиг X1 var line2SideY1 = Math.abs(Math.cos(line2Angle)*(imgS1/2)); // Находим сдвиг Y1 var line2SideX2 = Math.abs(Math.sin(line2Angle)*(imgS2/2)); // Находим сдвиг X2 var line2SideY2 = Math.abs(Math.cos(line2Angle)*(imgS2/2)); // Находим сдвиг Y2 var line3Angle = Math.atan2(line3CoorX2-line1CoorX1,line1CoorY1-line3CoorY2); var line3SideX1 = Math.abs(Math.sin(line3Angle)*(imgS1/2)); var line3SideY1 = Math.abs(Math.cos(line3Angle)*(imgS1/2)); var line3SideX2 = Math.abs(Math.sin(line3Angle)*(imgS2/2)); var line3SideY2 = Math.abs(Math.cos(line3Angle)*(imgS2/2)); // Для левых кругов (X2 < X1). Математический расчет координат var line4Angle = Math.atan2(line1CoorX1-line4CoorX2,line4CoorY2-line1CoorY1); var line4SideX1 = Math.abs(Math.sin(line4Angle)*(imgS1/2)); var line4SideY1 = Math.abs(Math.cos(line4Angle)*(imgS1/2)); var line4SideX2 = Math.abs(Math.sin(line4Angle)*(imgS2/2)); var line4SideY2 = Math.abs(Math.cos(line4Angle)*(imgS2/2)); var line5Angle = Math.atan2(line1CoorX1-line5CoorX2,line5CoorY2-line1CoorY1); var line5SideX1 = Math.abs(Math.sin(line5Angle)*(imgS1/2)); var line5SideY1 = Math.abs(Math.cos(line5Angle)*(imgS1/2)); var line5SideX2 = Math.abs(Math.sin(line5Angle)*(imgS2/2)); var line5SideY2 = Math.abs(Math.cos(line5Angle)*(imgS2/2)); // Находим координаты линий по центру координат окружностей и сдвигам до краев + увеличиваем сдвиг на x0.3 $('#slide-business svg .line2') .attr('x1',line1CoorX1+line2SideX1+line2SideX2*0.3) .attr('x2',line2CoorX2-line2SideX2-line2SideX2*0.3) .attr('y1',line1CoorY1-line2SideY1-line2SideY2*0.3) .attr('y2',line2CoorY2+line2SideY2+line2SideY2*0.3); if(line3CoorY2<line1CoorY1){ // Проверяем в какую сторону сдвигать линию от центра $('#slide-business svg .line3') .attr('x1',line1CoorX1+line3SideX1+line3SideX2*0.3) .attr('x2',line3CoorX2-line3SideX2-line3SideX2*0.3) .attr('y1',line1CoorY1-line3SideY1-line3SideY2*0.3) .attr('y2',line3CoorY2+line3SideY2+line3SideY2*0.3); } else { $('#slide-business svg .line3') .attr('x1',line1CoorX1+line3SideX1+line3SideX2*0.3) .attr('x2',line3CoorX2-line3SideX2-line3SideX2*0.3) .attr('y1',line1CoorY1+line3SideY1+line3SideY2*0.3) .attr('y2',line3CoorY2-line3SideY2-line3SideY2*0.3); } if(line4CoorY2>line1CoorY1){ $('#slide-business svg .line4') .attr('x1',line1CoorX1-line4SideX1-line4SideX2*0.3) .attr('x2',line4CoorX2+line4SideX2+line4SideX2*0.3) .attr('y1',line1CoorY1+line4SideY1+line4SideY2*0.3) .attr('y2',line4CoorY2-line4SideY2-line4SideY2*0.3); } else { $('#slide-business svg .line4') .attr('x1',line1CoorX1-line4SideX1-line4SideX2*0.3) .attr('x2',line4CoorX2+line4SideX2+line4SideX2*0.3) .attr('y1',line1CoorY1-line4SideY1-line4SideY2*0.3) .attr('y2',line4CoorY2+line4SideY2+line4SideY2*0.3); } $('#slide-business svg .line5') .attr('x1',line1CoorX1-line5SideX1-line5SideX2*0.3) .attr('x2',line5CoorX2+line5SideX2+line5SideX2*0.3) .attr('y1',line1CoorY1+line5SideY1+line5SideY2*0.3) .attr('y2',line5CoorY2-line5SideY2-line5SideY2*0.3); }); |
EuRo1985, нафига тебе margin-ы, ты что без них не можешь отпозиционировать через top, left, right, bottom у тебя же absolute, тогда тебе не придется в коде margin-ы еще учитывать пфф... сделай обертку просто relative и в контексте ее и позиционируй...
|
да, про маргины согласен, перемудрил тут... подправил код
|
EuRo1985, lineCoorX1 и lineCoorY1 почему то названы не так line1CoorX1 и line1CoorY1, для чтения кода это существенная деталь исправь и сразу увидишь повторы кода...
|
Повторы я вижу, lineCoor подправил. Я думаю каким-то образом цикл нужно организовать и ввести переменную, которая будет увеличиваться на +1 и подставляться в необходимые места... или, скажем, пробежаться по img и оставить от класса цифру при помощи substring, которую подставлять далее в скрипт...
|
Максимально постарался сократить скрипт. Добавил все условия на примере одной линии - line2. Осталось научить его подставлять нужный порядковый номер в соответствующие места.
$(function(){ var slideSize = $('#slide-business'); var imgS1 = parseInt($('.circles img.img1').width()); var imgS2 = parseInt($('.circles img.img2').width()); var line1CoorX1 = parseInt($('.circles img.img1').css('left')); var line1CoorY1 = parseInt($('.circles img.img1').css('top')); var line2CoorX2 = slideSize.width()-parseInt($('.circles div.img2').css('right'))-imgS2/2; var line2CoorY2 = parseInt($('.circles div.img2').css('top'))+imgS2/2; var line3CoorX2 = slideSize.width()-parseInt($('.circles div.img3').css('right'))-imgS2/2; var line3CoorY2 = parseInt($('.circles div.img3').css('top'))+imgS2/2; var line4CoorX2 = parseInt($('.circles div.img4').css('left'))+imgS2/2; var line4CoorY2 = slideSize.height()-parseInt($('.circles div.img4').css('bottom'))-imgS2/2; var line5CoorX2 = parseInt($('.circles div.img5').css('left'))+imgS2/2; var line5CoorY2 = slideSize.height()-parseInt($('.circles div.img5').css('bottom'))-imgS2/2; if(line2CoorX2>line1CoorX1){ var line2Angle = Math.atan2(line2CoorX2-line1CoorX1,line1CoorY1-line2CoorY2); } else { var line2Angle = Math.atan2(line1CoorX1-line2CoorX2,line2CoorY2-line1CoorY1); } var line2SideX1 = Math.abs(Math.sin(line2Angle)*(imgS1/2)); var line2SideY1 = Math.abs(Math.cos(line2Angle)*(imgS1/2)); var line2SideX2 = Math.abs(Math.sin(line2Angle)*(imgS2/2)); var line2SideY2 = Math.abs(Math.cos(line2Angle)*(imgS2/2)); if(line2CoorX2>line1CoorX1){ $('#slide-business svg .line2') .attr('x1',line1CoorX1+line2SideX1+line2SideX2*0.3) .attr('x2',line2CoorX2-line2SideX2-line2SideX2*0.3) } else { $('#slide-business svg .line2') .attr('x1',line1CoorX1-line2SideX1-line2SideX2*0.3) .attr('x2',line2CoorX2+line2SideX2+line2SideX2*0.3) } if(line2CoorY2>line1CoorY1){ $('#slide-business svg .line2') .attr('y1',line1CoorY1+line2SideY1+line2SideY2*0.3) .attr('y2',line2CoorY2-line2SideY2-line2SideY2*0.3); } else { $('#slide-business svg .line2') .attr('y1',line1CoorY1-line2SideY1-line2SideY2*0.3) .attr('y2',line2CoorY2+line2SideY2+line2SideY2*0.3); } }); |
EuRo1985, получается если поменять размеры окна браузера то линии останутся на своих старых местах...
|
Ну событие resize как раз не проблема добавить)
|
EuRo1985, нарисуй просто свою картинку в svg (окружности, линии, фон и текст) и не мучайся...
|
Решил задачу следующим образом
$('.circles div img').each(function(i){ var relParent = $('#slide-business'); var ctrImg = $('.circles > img'); var curImg = $(this); var curDiv = $(this).parent(); var line = $('#slide-business svg line'); var lineMargin = 0.3; var ctrImgCoorX = parseInt(ctrImg.css('left')); var ctrImgCoorY = parseInt(ctrImg.css('top')); if(curDiv.css('top') !== 'auto' || curDiv.css('top') < ctrImgCoorY) { var curImgCoorY = parseInt(curDiv.css('top'))+curImg.height()/2; } else { var curImgCoorY = relParent.height()-parseInt(curDiv.css('bottom'))-curImg.height()/2; } if(curDiv.css('left') !== 'auto' || curDiv.css('left') < ctrImgCoorX) { var curImgCoorX = parseInt(curDiv.css('left'))+curImg.width()/2; } else { var curImgCoorX = relParent.width()-parseInt(curDiv.css('right'))-curImg.width()/2; } if(curImgCoorX>ctrImgCoorX){ var lineAngle = Math.atan2(curImgCoorX-ctrImgCoorX,ctrImgCoorY-curImgCoorY); } else { var lineAngle = Math.atan2(ctrImgCoorX-curImgCoorX,curImgCoorY-ctrImgCoorY); } var ctrSideX = Math.abs(Math.sin(lineAngle)*(ctrImg.width()/2)); var ctrSideY = Math.abs(Math.cos(lineAngle)*(ctrImg.height()/2)); var curSideX = Math.abs(Math.sin(lineAngle)*(curImg.width()/2)); var curSideY = Math.abs(Math.cos(lineAngle)*(curImg.height()/2)); if(curImgCoorX>ctrImgCoorX){ line.eq(i) .attr('x1',ctrImgCoorX+ctrSideX+(curSideX*lineMargin)) .attr('x2',curImgCoorX-curSideX-(curSideX*lineMargin)) } else { line.eq(i) .attr('x1',ctrImgCoorX-ctrSideX-(curSideX*lineMargin)) .attr('x2',curImgCoorX+curSideX+(curSideX*lineMargin)) } if(curImgCoorY>ctrImgCoorY){ line.eq(i) .attr('y1',ctrImgCoorY+ctrSideY+(curSideY*lineMargin)) .attr('y2',curImgCoorY-curSideY-(curSideY*lineMargin)); } else { line.eq(i) .attr('y1',ctrImgCoorY-ctrSideY-(curSideY*lineMargin)) .attr('y2',curImgCoorY+curSideY+(curSideY*lineMargin)); } }); По сути вообще убрал классы и через ф-цию each перебираю элементы img и подставляю в координаты line с соответствующим индексом. |
Часовой пояс GMT +3, время: 05:16. |