Reputation: 271
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
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