Как создать изогнутый путь SVG между двумя точками?

Мне нужно нарисовать симметрично изогнутая линия между центрами двух окружностей.

<svg>
    <circle class = "spot" id = "au" cx = "1680" cy = "700" r = "0"></circle>
    <circle class = "spot" id = "sl" cx = "1425" cy = "525" r = "0"></circle>

    <line id = "line1" stroke-width = "2" stroke = "red"/>
</svg>

Это код, который я написал до сих пор. Элемент <line> следует заменить изогнутым контуром.

function drawNow() {
    let point1X = document.getElementById("au").getAttribute("cx");
    let point1Y = document.getElementById("au").getAttribute("cy");
    let point2X = document.getElementById("sl").getAttribute("cx");
    let point2Y = document.getElementById("sl").getAttribute("cy");

    let line1 = document.getElementById("line1");
    line1.setAttribute("x1", point1X);
    line1.setAttribute("y1", point1Y);
    line1.setAttribute("x2", point2X);
    line1.setAttribute("y2", point2Y);
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
11
0
12 742
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Квадратичной кривой SVG, вероятно, будет достаточно. Чтобы нарисовать его, вам нужны конечные точки (которые у вас есть) и контрольная точка, которая будет определять кривую.

Чтобы получилась симметричная кривая, контрольная точка должна находиться на серединном перпендикуляре линии между конечными точками. Немного математики найдет это.

Итак, с двух точек ...

Two points to join

вы можете добраться до

Points joined with curve

с кодом в

<!DOCTYPE html>
    <html>
    <head>
    	<meta charset = "UTF-8">
    	<title></title>
    	<style>
    		svg { background-color: bisque; }
    		.spot { fill: blue; }
    		.spot2 { fill: red; }
    	</style>
    	<script>
    		function x() {
    			var p1x = parseFloat(document.getElementById("au").getAttribute("cx"));
    			var p1y = parseFloat(document.getElementById("au").getAttribute("cy"));
    			var p2x = parseFloat(document.getElementById("sl").getAttribute("cx"));
    			var p2y = parseFloat(document.getElementById("sl").getAttribute("cy"));
    
    			// mid-point of line:
    			var mpx = (p2x + p1x) * 0.5;
    			var mpy = (p2y + p1y) * 0.5;
    
    			// angle of perpendicular to line:
    			var theta = Math.atan2(p2y - p1y, p2x - p1x) - Math.PI / 2;
    
    			// distance of control point from mid-point of line:
    			var offset = 30;
    
    			// location of control point:
    			var c1x = mpx + offset * Math.cos(theta);
    			var c1y = mpy + offset * Math.sin(theta);
    
    			// show where the control point is:
    			var c1 = document.getElementById("cp");
    			c1.setAttribute("cx", c1x);
    			c1.setAttribute("cy", c1y);
    
    			// construct the command to draw a quadratic curve
    			var curve = "M" + p1x + " " + p1y + " Q " + c1x + " " + c1y + " " + p2x + " " + p2y;
    			var curveElement = document.getElementById("curve");
    			curveElement.setAttribute("d", curve);
    		}
    	</script>
    </head>
    <body>
    	<svg width = "240" height = "160">
    		<circle id = "au" class = "spot" cx = "200" cy = "50" r = "4"></circle>
    		<circle id = "sl" class = "spot" cx = "100" cy = "100" r = "4"></circle>
    		<circle id = "cp" class = "spot2" cx = "0" cy = "0" r = "4"></circle>
    		<path id = "curve" d = "M0 0" stroke = "green" stroke-width = "4" stroke-linecap = "round" fill = "transparent"></path>
    	</svg>
    	<button type = "button" onclick = "x();">Click</button>
    </body>
    </html>

Если вы хотите, чтобы кривая пошла в другую сторону, измените знак offset.

Если вы используете браузеры, совместимые с ES6, вы можете использовать строковая интерполяция для более аккуратного кода:

var curve = `M${p1x} ${p1y} Q${c1x} ${c1y} ${p2x} ${p2y}`;

Нет необходимости отображать контрольную точку - просто чтобы вы могли видеть, где она находится, и проиллюстрировать, что кривая не проходит через нее.

Note: an alternative to using atan2 is to calculate the negative reciprocal of the gradient of the line between the points, but that is fiddly for the case where the gradient is zero and may produce wildly inaccurate results when the gradient is close to zero.

Другие вопросы по теме