Как залить фоновый цвет в SVG изображении луны в процентах

85
18 февраля 2022, 20:20

Я хочу, чтобы цвет фонового изображения SVG заполнялся постепенно, в процентах.

Вот изображение луны SVG. Я хочу постепенно, в процентах заполнять её белым цветом.

<?xml version="1.0" encoding="iso-8859-1"?> 
<svg xmlns="http://www.w3.org/2000/svg" width="139" height="134"> 
<g> 
  <circle stroke-width="7" stroke="#000" fill="#fff" r="58" cy="69" cx="69"/>
  <path stroke-width="0" fill="#000" d="m69,9 a62,60 0 0 0 1,121 l0,-5 a70,68 0 0 1 0,-110 l0,-5 z"/>
 </g></svg>

Свободный перевод вопроса How to fill background color to svg image in percentage от участника @M.Javid.

Answer 1

Я бы сделал это с маской.

Так что, я могу сделать эллиптическую тень.

Пояснения смотрите в комментариях скрипта

// Установить handler на input слайдера
var control = document.getElementById("control");
control.addEventListener("input", setMoonPhase);
// Инициализируйте SVG из начального значения слайдера
setMoonPhase();
function setMoonPhase(evt) {
  // Преобразовать из процента в значение 0..1
  var val = control.value / 100;
  // Получить элемент эллипса, который представляет фазу луны
  var  phaseEllipse = document.getElementById("phase-ellipse");
  // Установите радиус X фазового эллипса (где 100% = 0,5 -> 50% = 0 -> 0% = 0,5)
  phaseEllipse.rx.baseVal.value = Math.abs(val - 0.5);
  // Если фаза> 50%, то эллипс должен быть белым.
  // В противном случае это черный цвет, чтобы сделать дыру в маске, чтобы пропустить черный фон.
  phaseEllipse.style.fill = (val > 0.5) ? "white" : "black";
}
<svg xmlns="http://www.w3.org/2000/svg" width="139" height="134">
  <defs>
    <mask id="phase-mask" maskContentUnits="objectBoundingBox">
      <rect x="0.5" y="0" width="0.5" height="1" fill="white"/>
      <ellipse id="phase-ellipse" cx="0.5" cy="0.5" rx="0.2" ry="0.5" fill="white"/>
    </mask>
  </defs>
  <circle fill="black" r="58" cy="69" cx="69"/><!-- moon shadow -->
  <circle fill="#fff" r="54.5" cy="69" cx="69" mask="url(#phase-mask)"/><!-- sunlight on moon -->
  <circle stroke-width="7" stroke="black" fill="none" r="58" cy="69" cx="69"/><!-- moon border -->
</svg>
<p>
<input id="control" type="range" min="0" max="100" value="90" /><span id="output"></span>
</p>

Свободный перевод ответа от участника @Paul LeBeau.

Answer 2

Как-то так можно посчитать точки пересечения окружностей, для конструирования пути

requestAnimationFrame(draw); 
 
function draw(t) { 
  requestAnimationFrame(draw); 
  let r = 51; 
  let x = Math.sin(t/2010)*90; 
  let y = Math.sin(t/1731)*40; 
  let a = Math.atan2(y, x); 
  let s = Math.acos(Math.sqrt(x*x + y*y)/2/r); 
  let p0 = [Math.cos(a+s)*r, Math.sin(a+s)*r]; 
  let p1 = [Math.cos(a-s)*r, Math.sin(a-s)*r]; 
  sun.setAttribute('d', ` 
      m${p0} 
      A${r},${r},0,1,1,${p1} 
      A${r},${r},0,0,0,${p0} 
      z 
  `); 
}
body{ 
  overflow: hidden; 
  margin: 0; 
}
<svg viewBox=-55,-55,110,110 height=100vh width=100vw> 
  <path id=sun stroke=teal fill=none stroke-width=2 stroke-linejoin=round></path> 
</svg>

Answer 3

Анимация окружностей

Я бы сделал это с применением анимации чёрной окружности, которая постепенно и открывает и снова закрывает светлую окружность.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"  viewBox="0 0 73 73" > 
<defs> 
 <radialGradient id="RadialGrad" 
           fx="50%" fy="50%" r="65%" 
           spreadMethod="pad"> 
          <stop offset="0%"   stop-color="#E7D68C" stop-opacity="1"/> 
          <stop offset="100%" stop-color="#FFFEED" stop-opacity="1" /> 
        </radialGradient> 
 
</defs> 
<rect width="100%" height="100%" /> 
<g transform="rotate(-20 35.5 35.5)"> 
<circle cx="35.5" cy="35.5" r="35" stroke="none"  fill="url(#RadialGrad)" /> 
 
 <circle cx="35.5" cy="35.5" r="35" stroke="none" fill="black" > 
  
 <animate id="youngMoon" 
   attributeName="cx" 
   values="35.5;-35.5;" 
   begin="1s;oldMoon.end+1s" 
   dur="10s" 
   fill="freeze" 
  /> 
<animate id="oldMoon" 
   attributeName="cx" 
   values="105;35.5;" 
   begin="youngMoon.end+1s" 
   dur="10s" 
   fill="freeze" />  
 
</circle>  
</g> 
</svg>

Источник: @Alexandr_TT

Answer 4

Я бы сделал это с помощью 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>

Свободный перевод ответа от участника @enxaneta.

READ ALSO
Получить значение id из ссылки

Получить значение id из ссылки

Давайте перейдем сразу к сути) У меня есть директория console/indexphp

114
Работа php скрипта в промежутке даты

Работа php скрипта в промежутке даты

Подскажите пожалуйста как сделать , чтобы скрипт отрабатывал в промежуток даты 1512

92
mysqli_fetch_row() expects parameter 1 to be mysqli_result

mysqli_fetch_row() expects parameter 1 to be mysqli_result

возникла некая ошибка:

111