Marcel
Marcel

Reputation: 228

Image manipulation with css or javascript

I have a minor question about image manipulation on websites.

I got the question to implement some form of rating system where users can rate something for 1-2 or 3 stars. Only one star is shown per item. The request is that the star updates like the stars below:

Rating of 100%, full star = 100%

Rating of 70%, part of star = 70%

Now comes the question: is there some form of css or javascript magic which allows me to do this without using multiple images.

Thank you in advance

Upvotes: 0

Views: 107

Answers (4)

Max Patiiuk
Max Patiiuk

Reputation: 101

You can use html5 canvas (read this and this). Just create square with background image of full star and change canvas dimensions using jquery. Or create div with 6 images (one corner of the star turned to a certain angle). And make only certain parts visible (example: for 50% hide 3 images)

Upvotes: 0

K.Akbar
K.Akbar

Reputation: 46

There is a way to do this.

  1. First, the star image needs to be displayed.
  2. Then over that star, a radial progress bar will be displayed with reverse progress. The color of one side of it will be white and another side transparent.

    Visit https://codepen.io/jo-asakura/pen/stFHi to know how you can do the radial progress bar.

CSS

@import url(https://fonts.googleapis.com/css?family=Lato:700);

.size(@w, @h) {
  height: @h;
  width: @w;
}

// --
*,
*:before,
*:after {
  box-sizing: border-box;
}

html,
body {
  background: #ecf0f1;
  color: #444;
  font-family: 'Lato', Tahoma, Geneva, sans-serif;
  font-size: 16px;
  padding: 10px;
}

.set-size {
  font-size: 10em;
}

.charts-container:after {
  clear: both;
  content: "";
  display: table;
}

@bg: #34495e;
@size: 1em;

.pie-wrapper {
  .size(@size, @size);
  float: left;
  margin: 15px;
  position: relative;

  &:nth-child(3n+1) {
    clear: both;
  }

  .pie {
    .size(100%, 100%);
    clip: rect(0, @size, @size, @size / 2);
    left: 0;
    position: absolute;
    top: 0;

    .half-circle {
      .size(100%, 100%);
      border: @size / 10 solid #3498db;
      border-radius: 50%;
      clip: rect(0, @size / 2, @size, 0);
      left: 0;
      position: absolute;
      top: 0;
    }
  }

  .label {
    @font-size: @size / 4;
    @font-size-redo: @size * 4;

    background: @bg;
    border-radius: 50%;
    bottom: @font-size-redo / 10;
    color: #ecf0f1;
    cursor: default;
    display: block;
    font-size: @font-size;
    left: @font-size-redo / 10;
    line-height: @font-size-redo * .65;
    position: absolute;
    right: @font-size-redo / 10;
    text-align: center;
    top: @font-size-redo / 10;

    .smaller {
      color: #bdc3c7;
      font-size: .45em;
      padding-bottom: 20px;
      vertical-align: super;
    }
  }

  .shadow {
    .size(100%, 100%);
    border: @size / 10 solid #bdc3c7;
    border-radius: 50%;
  }

  &.style-2 {
    .label {
      background: none;
      color: #7f8c8d;

      .smaller {
        color: #bdc3c7;
      }
    }
  }

  &.progress-30 {
    .draw-progress(30, #3498db);
  }

  &.progress-60 {
    .draw-progress(60, #9b59b6);
  }

  &.progress-90 {
    .draw-progress(90, #e67e22);
  }

  &.progress-45 {
    .draw-progress(45, #1abc9c);
  }

  &.progress-75 {
    .draw-progress(75, #8e44ad);
  }

  &.progress-95 {
    .draw-progress(95, #e74c3c);
  }
}

.pie-wrapper--solid {
  border-radius: 50%;
  overflow: hidden;

  &:before {
    border-radius: 0 100% 100% 0 / 50%;
    content: '';
    display: block;
    height: 100%;
    margin-left: 50%;
    transform-origin: left;
  }

  .label {
    background: transparent;
  }

  &.progress-65 {
    .draw-progress--solid(65, #e67e22, @bg);
  }

  &.progress-25 {
    .draw-progress--solid(25, #9b59b6, @bg);
  }

  &.progress-88 {
    .draw-progress--solid(88, #3498db, @bg);
  }
}

// --
.draw-progress(@progress, @color) when (@progress <= 50) {
  .pie {
    .right-side {
      display: none;
    }
  }
}

.draw-progress(@progress, @color) when (@progress > 50) {
  .pie {
    clip: rect(auto, auto, auto, auto);

    .right-side {
      transform: rotate(180deg);
    }
  }
}

.draw-progress(@progress, @color) {
  .pie {
    .half-circle {
      border-color: @color;
    }

    .left-side {
      @rotate: @progress * 3.6;
      transform: rotate(~'@{rotate}deg');
    }
  }
}

.draw-progress--solid(@progress, @color, @bg) when (@progress <= 50) {
  &:before {
    background: @bg;
    transform: rotate((100 - (50 - @progress)) / 100 * 360deg * -1);
  }
}

.draw-progress--solid(@progress, @color, @bg) when (@progress > 50) {
  &:before {
    background: @color;
    transform: rotate((100 - @progress) / 100 * 360deg);
  }
}

.draw-progress--solid(@progress, @color, @bg) {
  background: linear-gradient(to right, @color 50%, @bg 50%);
}

HTML

<div class="set-size charts-container">
  <div class="pie-wrapper progress-30">
    <span class="label">30<span class="smaller">%</span></span>
    <div class="pie">
      <div class="left-side half-circle"></div>
      <div class="right-side half-circle"></div>
    </div>
  </div>

  <div class="pie-wrapper progress-60">
    <span class="label">60<span class="smaller">%</span></span>
    <div class="pie">
      <div class="left-side half-circle"></div>
      <div class="right-side half-circle"></div>
    </div>
  </div>

  <div class="pie-wrapper progress-90">
    <span class="label">90<span class="smaller">%</span></span>
    <div class="pie">
      <div class="left-side half-circle"></div>
      <div class="right-side half-circle"></div>
    </div>
  </div>

  <div class="pie-wrapper progress-45 style-2">
    <span class="label">45<span class="smaller">%</span></span>
    <div class="pie">
      <div class="left-side half-circle"></div>
      <div class="right-side half-circle"></div>
    </div>
    <div class="shadow"></div>
  </div>

  <div class="pie-wrapper progress-75 style-2">
    <span class="label">75<span class="smaller">%</span></span>
    <div class="pie">
      <div class="left-side half-circle"></div>
      <div class="right-side half-circle"></div>
    </div>
    <div class="shadow"></div>
  </div>

  <div class="pie-wrapper progress-95 style-2">
    <span class="label">95<span class="smaller">%</span></span>
    <div class="pie">
      <div class="left-side half-circle"></div>
      <div class="right-side half-circle"></div>
    </div>
    <div class="shadow"></div>
  </div>

  <div class="pie-wrapper pie-wrapper--solid progress-65">
    <span class="label">65<span class="smaller">%</span></span>
  </div>

  <div class="pie-wrapper pie-wrapper--solid progress-25">
    <span class="label">25<span class="smaller">%</span></span>
  </div>

  <div class="pie-wrapper pie-wrapper--solid progress-88">
    <span class="label">88<span class="smaller">%</span></span>
  </div>
</div>

Upvotes: 1

Sandeep Shah
Sandeep Shah

Reputation: 41

I'd overlay a pie-segment on the image, and just control it's size. Just make sure it's colour is the same as the background of the page, if possible.

See: https://codepen.io/sandeepshah/pen/eEqLpv

<div class="pie"></div>

.pie {
  position: absolute;
  width: 100px;
  height: 200px;
  overflow: hidden;
  left: 0;
  top: 0;
  transform-origin: left center;
}

.pie:BEFORE {
  content: "";
  position: absolute;
  height: 200px;
  width: 100px;
  left: -100px;
  border-radius: 100px 0 0 100px;
  transform-origin: right center;
  background-color: red;
  transform: rotate(60deg);
}

Use the final attribute "transform" to control it's size.

Upvotes: 0

kapitan
kapitan

Reputation: 2222

use image sprite, so technically, you only load one image.

Upvotes: 0

Related Questions