【问题标题】:How to fill background color to svg image in percentage如何以百分比填充背景颜色到 svg 图像
【发布时间】:2018-10-23 06:28:48
【问题描述】:

如何将背景颜色以百分比填充到 SVG 图像

我想用百分比填充 svg 图像的颜色

这是月亮 svg 图像,我想根据月亮上的照明百分比填充白色

90% 80% 70% 等等

<?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>

【问题讨论】:

    标签: css svg


    【解决方案1】:

    我会带着面具来做这件事。所以我可以制作一个椭圆形的阴影。

    // Set handler on input slider
    var control = document.getElementById("control");
    control.addEventListener("input", setMoonPhase);
    
    // Initialise SVG from initial value of slider
    setMoonPhase();
    
    function setMoonPhase(evt) {
      // Convert from percentage to a 0..1 value
      var val = control.value / 100;
      // Get the ellipse element that represents the moon phase
      var  phaseEllipse = document.getElementById("phase-ellipse");
      // Set the X radius of the phase ellipse (where 100% = 0.5 -> 50% = 0 -> 0% = 0.5)
      phaseEllipse.rx.baseVal.value = Math.abs(val - 0.5);
      // If the phase > 50% then the ellipse needs to be white.
      // Otherwise it is black, to make a hole in the mask to let the black background show through.
      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>

    【讨论】:

      【解决方案2】:

      我会用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>

      【讨论】:

        【解决方案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>

        【讨论】:

          【解决方案4】:

          你的意思是这样的?

          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 110 110" width="100px" height="100px"> 
              <circle fill="#000" r="50" cy="55" cx="55"/>
              <circle fill="#fff" r="50" cy="55" cx="90"/>
              <circle fill="transparent" r="50" cy="55" stroke="#000" stroke-width="10" cx="55"/>
          </svg>

          使用自定义 CSS 属性:

          :root{
            --stroke-width: 10;
            --side: 50;
            --gutter: calc(var(--stroke-width) / 2);
            --cx: calc(var(--gutter) + var(--side));
            --percent: calc(15 * 0.02 * var(--side));
            --moon-light: calc(var(--cx) + var(--percent));
          }
            
          circle{
               cx: var(--cx);
               cy: var(--cx);
               r: var(--side);
          }
          
          .moon-percent{
              cx: var(--moon-light);
          }
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 110 110" width="100px" height="100px"> 
              <circle fill="#000" />
              <circle class="moon-percent" fill="#fff"/>
              <circle fill="transparent" stroke="#000" stroke-width="var(--stroke-width)"/>
          </svg>

          【讨论】:

            【解决方案5】:

            您可以计算两个圆的交点并构造相应的路径。

            类似这样的:

            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>

            【讨论】:

              猜你喜欢
              • 2013-06-07
              • 1970-01-01
              • 2017-04-16
              • 2012-11-02
              • 1970-01-01
              • 2016-12-27
              • 2016-02-12
              相关资源
              最近更新 更多