Search code examples
csscss-animationspie-chart

CSS pie chart with background pattern


I'm trying to make a pie chart with PNG image as background-image there:

.piebg {
  width: 95px;
  height: 95px;
  border-radius: 50%;
  background-image: url('https://pngimg.com/uploads/pizza/pizza_PNG44095.png');
  background-size: cover;
}

.pie {
  width: 102px;
  height: 102px;
  border-radius: 50%;
  background: inherit;
}

.pie::before {
  content: '';
  display: block;
  margin-left: 50%;
  height: 100%;
  border-radius: 0 100% 100% 0 / 50%;
  background-color: #fff;
  transform-origin: left;
  animation: spin 5s linear infinite, bg 5s step-end 1;
}

.pie::after {
  content: '';
  display: block;
  height: 100%;
  right: 50px;
  border-radius: 100% 0 0 100% / 50%;
  background-color: #fff;
  position: relative;
  top: -102px;
}

@keyframes spin {
  to {
    transform: rotate(.5turn);
  }
}

@keyframes bg {
  50% {
    background: transparent;
  }
}
<div class="piebg">
  <div class="pie"></div>
</div>

There is an issue with the wrong fill of a pie chart area. CSS animation is not a strong side of my experience yet to complete this example.

Could you help me to find an article or example how to complete my pie chart?


Solution

  • If you consider discontinuous animation, we can do this with only single div and mask.

    .pie {
      width: 95px;
      height: 95px;
      border-radius: 50%;
      background-image: url('https://i.sstatic.net/tJMg9.png');
      background-size: cover;
      --s: 0%;
      --mask: conic-gradient(#000 var(--s), transparent var(--s) 360%);
      -webkit-mask: var(--mask);
      mask: var(--mask);
      animation: pie 2s forwards;
      /*                   ↑ you can use "infinite" instead */
    }
    
    @keyframes pie {
      10% {
        --s: 10%;
      }
      20% {
        --s: 20%;
      }
      30% {
        --s: 30%;
      }
      40% {
        --s: 40%;
      }
      50% {
        --s: 50%;
      }
      60% {
        --s: 60%;
      }
      70% {
        --s: 70%;
      }
      80% {
        --s: 80%;
      }
      90% {
        --s: 90%;
      }
      100% {
        --s: none;
      }
    }
    <div class="pie"></div>

    Also now we can make a continuous animation with @property

    @property --s {
      initial-value: 0%;
      inherits: false;
      syntax: '<percentage>';
    }
    
    .pie {
      width: 95px;
      height: 95px;
      border-radius: 50%;
      background-image: url('https://i.sstatic.net/tJMg9.png');
      background-size: cover;
      --s: 0%;
      --mask: conic-gradient(#000 var(--s), transparent var(--s) 360%);
      -webkit-mask: var(--mask);
      mask: var(--mask);
      animation: pie 2s 1s infinite;
    }
    
    @keyframes pie {
      100% {
        --s: 100%;
      }
    }
    <div class="pie"></div>