Jeyanth Kanagaraj
Jeyanth Kanagaraj

Reputation: 271

Creating Heart shaped progress loader | Reactjs

I want to make an Heart shaped progress loader for a react project. I tried using css. But, it didn't show the progress properly, like it only cover some part of the heart design. Below is the code, which i tried to do that. The progress should start from the bottom and need to reach, if it's 100 percentage. Please check and let me know, how can i achieve that.

Thanks in Advance

/***Progress***/
import React, { Component } from 'react';
import ProgressBar from './ProgressBar';

 class Progress extends Component {
    constructor(props) {
        super(props);
        this.state = {
            percentage: 60,
        }
    }
  render() {
    return (
      <div>
        <ProgressBar percentage={this.state.percentage}/>
      </div>
    )
  }
}

export default Progress

/***Progress bar***/

import React from 'react';
import Filler from './Filler.js';

const ProgressBar = (props) => {
    return (
        <div className="ProgressBarH">
            <Filler percentage={props.percentage}/>
        </div>
    )
}

export default ProgressBar;

/***Filler***/

import React from 'react';

const Filler = (props) => {
    return (
        <div className = "filler" style={{width: `${props.percentage}%`}} />
    )
}

export default Filler;

/***css***/
.ProgressBarH {
  position: relative;
  width: 10px;
  height: 10px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  -o-transform: rotate(45deg);
  transform: rotate(45deg);
  border: 1px solid #ff7777 ;
  background-color:#ff7777;
  margin: 0 auto;
}

.ProgressBarH:before,
.ProgressBarH:after {
  position: absolute;
  width: 12px;
  height: 12px;
  content: '';
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  -o-border-radius: 50%;
  border-radius: 50%;
   background-color:#ff7777; 
}

.ProgressBarH:before {
  bottom: -1px;
    left: -8px;
}

.ProgressBarH:after {
  top: -8px;
    right: -1px;
} 

.filler {
  /* background: red; */
  height: 100%;
  border-radius: inherit;
  transition: width .2s ease-in;

}

Upvotes: 1

Views: 1036

Answers (1)

Will Jenkins
Will Jenkins

Reputation: 9787

I don't think it's possible to fill the heart from bottom to top in the way that you want to if it's created using pseudo elements.

It is possible with a svg with a clipPath though - something like this:

const ProgressBar = props => {
  const y = 24 - (24 * props.percentage) / 100;
  return (
    <div className="ProgressBarH">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="24"
        height="24"
        viewBox="0 0 24 24"
      >
        <defs>
          <clipPath id="cut-off-bottom">
            <rect x="0" y={y} width="24" height="24" />
          </clipPath>
        </defs>
        <path
          style={{ fill: "red" }}
          d="M12 4.248c-3.148-5.402-12-3.825-12 2.944 0 4.661 5.571 9.427 12 15.808 6.43-6.381 12-11.147 12-15.808 0-6.792-8.875-8.306-12-2.944z"
          clipPath="url(#cut-off-bottom)"
        />
      </svg>
    </div>
  );
};

Quick and dirty sandbox here: https://codesandbox.io/s/optimistic-bird-8g63q

Edited to add black border:

<svg
    xmlns="http://www.w3.org/2000/svg"
    width="26"
    height="26"
    viewBox="0 0 26 26"
  >
    <defs>
      <clipPath id="cut-off-bottom">
        <rect x="0" y={y} width="26" height="24" />
      </clipPath>
    </defs>

    <path
      style={{ fill: "red" }}
      d="M12 4.248c-3.148-5.402-12-3.825-12 2.944 0 4.661 5.571 9.427 12 15.808 6.43-6.381 12-11.147 12-15.808 0-6.792-8.875-8.306-12-2.944z"
      clipPath="url(#cut-off-bottom)"
    />
    <path
      style={{ stroke: "black", strokeWidth: "2", fill: "none" }}
      d="M12 4.248c-3.148-5.402-12-3.825-12 2.944 0 4.661 5.571 9.427 12 15.808 6.43-6.381 12-11.147 12-15.808 0-6.792-8.875-8.306-12-2.944z"
    />
  </svg>

(See sandbox)

Upvotes: 1

Related Questions