Clipped Circle Graph

By Kevin Ball

F6
#
How do I use This?

A SCSS based clipped circle graph

HTML
<div class="clipped-circle-graph" data-clipped-circle-graph data-percent="50">
  <div class="clipped-circle-graph-progress">
    <div class="clipped-circle-graph-progress-fill"></div>
  </div>
  <div class="clipped-circle-graph-percents">
    <div class="clipped-circle-graph-percents-wrapper">
      <span class="clipped-circle-graph-percents-number"></span>
      <span class="clipped-circle-graph-percents-units">of 100</span>
    </div>
  </div>
</div>

@mixin clipped-circle-graph-circle($size) {
  content: "";
  position: absolute;
  border-radius: 50%;
  left: calc(50% - #{$size/2});
  top: calc(50% - #{$size/2});
  width: $size;
  height: $size;
}

$clipped-circle-graph-size: rem-calc(180);
$clipped-circle-graph-percent-number-size: rem-calc(24);
$clipped-circle-graph-percent-unit-size: rem-calc(16);
$clipped-circle-graph-empty-color: $dark-gray;
$clipped-circle-background-color: $light-gray;
$clipped-circle-graph-fill-color: $primary-color;
$clipped-circle-clip-size: rem-calc(80);

.clipped-circle-graph {
  width: $clipped-circle-graph-size;
  height: $clipped-circle-graph-size;
  border-radius: 50%;
  background-color: $clipped-circle-graph-empty-color;
  position: relative;

  &.gt-50 {
    background-color: $clipped-circle-graph-fill-color;
  }
  &:after {
    content: '';
    @include horizontal-center;
    bottom: 19px;
    background: $clipped-circle-background-color;
    height: $clipped-circle-clip-size;
    width: $clipped-circle-clip-size;
    z-index: 3;
    transform: rotate(45deg) translate3d(0,0,0);
    transform-origin: -30px 15px;
  }
}

.clipped-circle-graph-progress {
  @include clipped-circle-graph-circle($clipped-circle-graph-size);
  clip: rect(0, $clipped-circle-graph-size, $clipped-circle-graph-size, #{$clipped-circle-graph-size/2});
  transform: rotate(-180deg) perspective(0);

  .clipped-circle-graph-progress-fill {
    @include clipped-circle-graph-circle($clipped-circle-graph-size);
    clip: rect(0, #{$clipped-circle-graph-size/2}, $clipped-circle-graph-size, 0);
    background: $clipped-circle-graph-fill-color;
    transform: rotate(60deg);
  }

  .gt-50 & {
    clip: rect(0, #{$clipped-circle-graph-size/2}, $clipped-circle-graph-size, 0);

    .clipped-circle-graph-progress-fill {
      clip: rect(0, $clipped-circle-graph-size, $clipped-circle-graph-size, #{$clipped-circle-graph-size/2});
      background: $clipped-circle-graph-empty-color;
    }
  }
}
.clipped-circle-graph-percents {
  @include clipped-circle-graph-circle(#{$clipped-circle-graph-size/1.45});
  background: $clipped-circle-background-color;
  text-align: center;
  display: table;
  z-index: 4;

  .clipped-circle-graph-percents-number {
    display: block;
    font-size: $clipped-circle-graph-percent-number-size;
    font-weight: bold;
    color: $clipped-circle-graph-fill-color;
  }

  .clipped-circle-graph-percents-units {
    display: block;
    font-size: $clipped-circle-graph-percent-unit-size;
    font-weight: bold;
  }
}
.clipped-circle-graph-percents-wrapper {
  display: table-cell;
  vertical-align: middle;
  line-height: 0;

  span {
    line-height: 1;
  }
}


.clipped-circle-graph {
  width: 11.25rem;
  height: 11.25rem;
  border-radius: 50%;
  background-color: #8a8a8a;
  position: relative;
}

.clipped-circle-graph.gt-50 {
  background-color: #1779ba;
}

.clipped-circle-graph:after {
  content: '';
  position: absolute;
  left: 50%;
  -webkit-transform: translateX(-50%);
      -ms-transform: translateX(-50%);
          transform: translateX(-50%);
  bottom: 19px;
  background: #e6e6e6;
  height: 5rem;
  width: 5rem;
  z-index: 3;
  -webkit-transform: rotate(45deg) translate3d(0, 0, 0);
          transform: rotate(45deg) translate3d(0, 0, 0);
  -webkit-transform-origin: -30px 15px;
      -ms-transform-origin: -30px 15px;
          transform-origin: -30px 15px;
}

.clipped-circle-graph-progress {
  content: "";
  position: absolute;
  border-radius: 50%;
  left: calc(50% - 5.625rem);
  top: calc(50% - 5.625rem);
  width: 11.25rem;
  height: 11.25rem;
  clip: rect(0, 11.25rem, 11.25rem, 5.625rem);
  -webkit-transform: rotate(-180deg) perspective(0);
          transform: rotate(-180deg) perspective(0);
}

.clipped-circle-graph-progress .clipped-circle-graph-progress-fill {
  content: "";
  position: absolute;
  border-radius: 50%;
  left: calc(50% - 5.625rem);
  top: calc(50% - 5.625rem);
  width: 11.25rem;
  height: 11.25rem;
  clip: rect(0, 5.625rem, 11.25rem, 0);
  background: #1779ba;
  -webkit-transform: rotate(60deg);
      -ms-transform: rotate(60deg);
          transform: rotate(60deg);
}

.gt-50 .clipped-circle-graph-progress {
  clip: rect(0, 5.625rem, 11.25rem, 0);
}

.gt-50 .clipped-circle-graph-progress .clipped-circle-graph-progress-fill {
  clip: rect(0, 11.25rem, 11.25rem, 5.625rem);
  background: #8a8a8a;
}

.clipped-circle-graph-percents {
  content: "";
  position: absolute;
  border-radius: 50%;
  left: calc(50% - 7.75862rem/2);
  top: calc(50% - 7.75862rem/2);
  width: 7.75862rem;
  height: 7.75862rem;
  background: #e6e6e6;
  text-align: center;
  display: table;
  z-index: 4;
}

.clipped-circle-graph-percents .clipped-circle-graph-percents-number {
  display: block;
  font-size: 1.5rem;
  font-weight: bold;
  color: #1779ba;
}

.clipped-circle-graph-percents .clipped-circle-graph-percents-units {
  display: block;
  font-size: 1rem;
  font-weight: bold;
}

.clipped-circle-graph-percents-wrapper {
  display: table-cell;
  vertical-align: middle;
  line-height: 0;
}

.clipped-circle-graph-percents-wrapper span {
  line-height: 1;
}

JS
$("[data-clipped-circle-graph]").each(function() {
  var $graph = $(this),
      percent = parseInt($graph.data('percent'), 10),
      deg = 30 + (300*percent)/100;
  if(percent > 50) {
    $graph.addClass('gt-50');
  }
  $graph.find('.clipped-circle-graph-progress-fill').css('transform','rotate('+ deg +'deg)');
  $graph.find('.clipped-circle-graph-percents-number').html(percent+'%');
});