<svg>
	<g>
		<path d="M 100 200 L 300 400"></path>
		<circle r="10" />
	</g>
</svg>
<pre></pre>
html,
body,
svg {
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}

path,
circle {
	stroke: black;
	stroke-width: 1px;
	fill: none;
}
g {
	transform-origin: center;
	animation: pulse 60s infinite;
	animation-timing-function: linear;
}
circle {
	stroke: orange;
	stroke-width: 3px;
}

@keyframes pulse {
	0% {
		transform: rotate(0);
	}
	100% {
		transform: rotate(360deg);
	}
}

pre {
	width: 100%;
	position: fixed;
	top: 0;
	text-align: center;
	font-size: 250%;
}
function getTransformedPoint(point, element) {
	const matrix = element.getCTM().inverse();
	return point.matrixTransform(matrix);
}


const svg = document.querySelector("svg");
const path = document.querySelector("path");
const circle = document.querySelector("circle");
const pre = document.querySelector("pre");
const { innerWidth, innerHeight } = window;
let min = Math.min(innerWidth, innerHeight);
let mul = Math.random() * 0.5 + 0.25;
path.setAttribute(
	"d",
	`M ${innerWidth / 2} ${innerHeight / 2} L ${min * mul} ${min * mul}`
);
circle.setAttribute("cx", min * mul);
circle.setAttribute("cy", min * mul);

const length = path.getTotalLength();
const point = path.getPointAtLength(length);

setInterval(() => {
	const transformedPoint = getTransformedPoint(point, path);
	pre.innerHTML = `Original position: ${parseInt(point.x)}, ${parseInt(
		point.y
	)}<br/>Transformed position: ${parseInt(transformedPoint.x)}, ${parseInt(
		transformedPoint.y
	)}`;
}, 250);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.