skip to Main Content

I have an image of a bottle and try fill this bottle of some color

I found the fill coordinates, but my background inside of bottle doesn’t filled

.item {
  width: 150px;
  height: 150px;
}

#tubeLiquid {
  background-color: #74ccf4;
  clip-path: polygon(45% 19%, 41% 22%, 41% 29%, 41% 36%, 41% 43%, 41% 50%, 41% 57%, 41% 63%, 41% 70%, 41% 77%, 41% 83%, 41% 90%, 43% 93%, 50% 92%, 56% 93%, 60% 88%, 59% 81%, 60% 75%, 60% 68%, 60% 61%, 59% 55%, 59% 48%, 59% 42%, 59% 35%, 59% 29%, 58% 23%, 54% 19%);
}

#bottleMask{
  background-color: #FFFFFF;
  clip-path: polygon(45% 19%, 41% 22%, 41% 29%, 41% 36%, 41% 43%, 41% 50%, 41% 57%, 41% 63%, 41% 70%, 41% 77%, 41% 83%, 41% 90%, 43% 93%, 50% 92%, 56% 93%, 60% 88%, 59% 81%, 60% 75%, 60% 68%, 60% 61%, 59% 55%, 59% 48%, 59% 42%, 59% 35%, 59% 29%, 58% 23%, 54% 19%);
}
<div class="item">
  <svg viewBox="0 0 300 300">
    <image
      width="300"
      clip-path="url(#bottleMask)"
      xlink:href="https://i.ibb.co/Mhfwtxp/image-removebg-preview-1.png"
    ></image>
    <defs>
      <mask id="bottleMask"></mask>
    </defs>
    <g id="maskedLiquid" mask="url(#bottleMask)">
      <path id="tubeLiquid" fill="#74ccf4"></path>
    </g>
  </svg>
</div>

2

Answers


  1. The closest solution I found is this i didnt fill the whole bottle but you just need to change some of the coordinates in polygons i dont have that knowledge about shapes and polygons.

    <style>
    .item {
      width: 150px;
      height: 150px;
    }
    
    #tubeLiquid {
      background-color: #74ccf4;
      clip-path: polygon(45% 19%, 41% 22%, 41% 29%, 41% 36%, 41% 43%, 41% 50%, 41% 57%, 41% 63%, 41% 70%, 41% 77%, 41% 83%, 41% 90%, 43% 93%, 50% 92%, 56% 93%, 60% 88%, 59% 81%, 60% 75%, 60% 68%, 60% 61%, 59% 55%, 59% 48%, 59% 42%, 59% 35%, 59% 29%, 58% 23%, 54% 19%);
    }
    
    #bottleMask{
      background-color: #FFFFFF;
      clip-path: polygon(45% 19%, 41% 22%, 41% 29%, 41% 36%, 41% 43%, 41% 50%, 41% 57%, 41% 63%, 41% 70%, 41% 77%, 41% 83%, 41% 90%, 43% 93%, 50% 92%, 56% 93%, 60% 88%, 59% 81%, 60% 75%, 60% 68%, 60% 61%, 59% 55%, 59% 48%, 59% 42%, 59% 35%, 59% 29%, 58% 23%, 54% 19%);
    }</style>
    
    <div class="item">
      <svg viewBox="0 0 300 300">
        <defs>
          <mask id="bottleMask" fill="white">
            <path d="M0,0h300v300H0V0z M89,68h122v147H89V68z" />
          </mask>
          <clipPath id="liquidClip">
            <path d="M89,68h122v147H89V68z" />
          </clipPath>
        </defs>
        <image width="300" xlink:href="https://i.ibb.co/Mhfwtxp/image-removebg-preview-1.png" />
        <path id="tubeLiquid" fill="#74ccf4" d="M0,0h300v300H0V0z" clip-path="url(#liquidClip)" mask="url(#bottleMask)" />
      </svg>
    </div>
    
    Login or Signup to reply.
  2. You don’t need an additional <mask>.
    Due to the shape of the bottle, you could use a rounded <rect> as clip-path:

    waterLevel.addEventListener('input', e => {
      let value = +e.currentTarget.value
      tubeLiquid.setAttribute('stroke-dasharray', `${value} 100`)
    })
    svg {
      width: 20%;
    }
    <h3>Draw clip-path</h3>
    <svg viewBox="0 0 300 300">
        <image width="300" href="https://i.ibb.co/Mhfwtxp/image-removebg-preview-1.png" />
        <!-- test clip path -->
        <rect x="115" y="55" width="69" height="235" rx="20" ry="20" fill="red" />
      </svg>
    
    <h3>Draw liquid fill</h3>
    <svg viewBox="0 0 300 300">
        <image width="300" href="https://i.ibb.co/Mhfwtxp/image-removebg-preview-1.png" />
        <line x1="149.5" y1="290" x2="149.5" y2="50" stroke="green" stroke-width="70" />
      </svg>
    
    <h3>Apply clip path</h3>
    <p><input type="range" min="0" max="100" value="100" id="waterLevel" name="water-level" /></p>
    <svg viewBox="0 0 300 300">
        <clipPath id="clip">
              <rect x="115" y="55" width="69" height="235" rx="20" ry="20" fill="red" />
        </clipPath>
        <image width="300" href="https://i.ibb.co/Mhfwtxp/image-removebg-preview-1.png" />
        <line id="tubeLiquid" clip-path="url(#clip)" pathLength="100" stroke-dasharray="100 100" x1="149.5" y1="290" x2="149.5" y2="50" stroke="#74ccf4" stroke-width="80" />
      </svg>

    Draw your clip-path and fill-scale/progress bar shapes first – without clipping anything – to find the right coordinates and dimensions.

    Then you can apply, the clip-path.
    I’ve used a <line> element for the "tubeLiquid" element as it allows us to set the pathLength attribute to 100.

    We can easily change the current fill value by updating the stroke-dasharray attribute:

    // show 100 %
    stroke-dasharray="100 100"
    
    // show 50 %
    stroke-dasharray="50 100"
    

    You’ll find a lot of examples on SO using this method for all kinds of dynamic gauges/progress bars or animated pie charts like "Set svg progress bar percentage in javascript"

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search