22.11.2016, 16:39
|
Новичок на форуме
|
|
Регистрация: 22.11.2016
Сообщений: 8
|
|
Скрипт получения координат для svg-линий
Уважаемы знатоки 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, 22.11.2016 в 18:20.
|
|
22.11.2016, 17:05
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
EuRo1985, нафига тебе margin-ы, ты что без них не можешь отпозиционировать через top, left, right, bottom у тебя же absolute, тогда тебе не придется в коде margin-ы еще учитывать пфф... сделай обертку просто relative и в контексте ее и позиционируй...
|
|
22.11.2016, 17:13
|
Новичок на форуме
|
|
Регистрация: 22.11.2016
Сообщений: 8
|
|
да, про маргины согласен, перемудрил тут... подправил код
Последний раз редактировалось EuRo1985, 22.11.2016 в 17:15.
|
|
22.11.2016, 17:27
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
EuRo1985, lineCoorX1 и lineCoorY1 почему то названы не так line1CoorX1 и line1CoorY1, для чтения кода это существенная деталь исправь и сразу увидишь повторы кода...
|
|
22.11.2016, 17:59
|
Новичок на форуме
|
|
Регистрация: 22.11.2016
Сообщений: 8
|
|
Повторы я вижу, lineCoor подправил. Я думаю каким-то образом цикл нужно организовать и ввести переменную, которая будет увеличиваться на +1 и подставляться в необходимые места... или, скажем, пробежаться по img и оставить от класса цифру при помощи substring, которую подставлять далее в скрипт...
Последний раз редактировалось EuRo1985, 22.11.2016 в 18:02.
|
|
22.11.2016, 18:40
|
Новичок на форуме
|
|
Регистрация: 22.11.2016
Сообщений: 8
|
|
Максимально постарался сократить скрипт. Добавил все условия на примере одной линии - 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, 22.11.2016 в 18:47.
|
|
22.11.2016, 19:17
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
EuRo1985, получается если поменять размеры окна браузера то линии останутся на своих старых местах...
|
|
22.11.2016, 21:20
|
Новичок на форуме
|
|
Регистрация: 22.11.2016
Сообщений: 8
|
|
Ну событие resize как раз не проблема добавить)
|
|
22.11.2016, 22:36
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
EuRo1985, нарисуй просто свою картинку в svg (окружности, линии, фон и текст) и не мучайся...
|
|
23.11.2016, 14:48
|
Новичок на форуме
|
|
Регистрация: 22.11.2016
Сообщений: 8
|
|
Решил задачу следующим образом
$('.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 с соответствующим индексом.
|
|
|
|