Я бы сделал это с clip-path
.
mooning()
control.addEventListener("input",()=>{
mooning()
})
function map(n, a, b, _a, _b) {
let d = b - a;
let _d = _b - _a;
let u = _d / d;
return _a + n * u;
}
function mooning(){
output.innerHTML = control.value + "%";
let value = map(control.value, 0, 100, -25, 175)
moon.setAttributeNS(null, "cx", value)
}
svg{border:1px solid; width:75vh}
#control{width:75vh;}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
<clipPath id="cp">
<circle id="fullMoon" r="50" cy="75" cx="75"/>
</clipPath>
<g clip-path="url(#cp)">
<rect width="100%" height="100%" />
<circle id="moon" r="50" cy="75" cx="175" fill="white" />
</g>
<use xlink:href="#fullMoon" fill="none" stroke="black" />
</svg>
<p><input id="control" type="range" min="0" max="100" value="60" /><span id="output"></span></p>