`Heart-shaped loading bar in Reactjs`

Looking for help in creating a heart-shaped progress loader for a React project. I attempted using CSS but encountered issues with the progress not filling the entire heart design. Below is the code snippet I used. The progress should start from the bottom and fill up to 100%. Any suggestions on how to achieve this would be appreciated.

Thank you 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;
}

Answer №1

In order to achieve the desired effect of filling the heart from bottom to top, using pseudo elements may not be the most effective method.

Alternatively, you can use an SVG with a clipPath 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>
  );
};

For a quick demo, check out this sandbox link: https://codesandbox.io/s/optimistic-bird-8g63q

To enhance the visual appearance, you can add a black border as shown below:

<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>

(View updated version in the sandbox)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Node.js threw an error when trying to download a tarball, displaying a status code of

While attempting to install various modules in Nodejs using NPM, I encountered a situation where the installation process failed and returned an error: Error: 403 status code downloading tarball This same issue happened again when I tried to install node ...

Search for documents using jQuery on the page

Here is the layout of a page: HTML <div class="alert alert-dismissable"> <div class="form-group text-center"> <div id="Section"> <div class="row"> <div class="col-md-12"> ...

The iconClassNameRight for "muidocs-icon-navigation-expand-more" is not functioning correctly

Newbie Here: Just getting started with Material-UI and I'm having a small issue. When I try to implement the first example in the components section, the expand more icon on the right side of the AppBar is not showing up (that little down arrow): ht ...

Issue with Google Tag Manager click event not propagating to parent element

I am currently configuring Google Tag Manager for a client's website and encountering difficulties in getting click event tags to activate. Although I have set the trigger to activate based on the button's CSS selector, the actual button contain ...

Tips for optimizing the "framerate" (setInterval delay) in a JavaScript animation loop

When creating a JavaScript animation, it's common practice to use setInterval (or multiple setTimeouts) to create a loop. But what is the optimal delay to set in these setInterval/setTimeout calls? In the jQuery API page for the .animate() function, ...

Is it possible to programmatically bind a click event to each individual word in a div element?

I'm attempting to link each word within an element without altering the markup inside the element using Javascript. ...

Guide to verifying the update of user information with sweet Alert on ASP MVC

I'm currently working on an ASP MVC web application that involves using stored procedures with SQL Server. My goal is to implement a confirmation alert (Sweet Alert) to confirm the data update for a logged-in user. The code for editing works fine wi ...

What is the most effective strategy for managing dependencies for npm packages?

I am currently working on extracting a few Vue.js components from the main application and converting them into an npm package stored in a repository. This package will be imported and utilized across two different websites. To bundle everything, I am util ...

Can a tooltip be displayed on a disabled Material UI Button within a ButtonGroup without causing any layout disruptions?

I am attempting to create a Material UI ButtonGroup with disabled buttons and tooltips. The code snippet below displays the buttons correctly, but according to this source (https://material-ui.com/components/tooltips/#disabled-elements), disabled elements ...

What is the process for converting a UTC datetime string into the local timezone of users?

I am utilizing Laravel 5.7 for the API and Vue for the frontend development. The API response includes a user's last seen timestamp in UTC format by default, like this: last_seen: "2019-04-17 05:20:37". Laravel API code: $user_details = array( ...

What is the best way to create a hover effect for this text?

When I hover over the image div, the text section will smoothly appear from the bottom. You can see an example of what I want here. Below, you'll find the HTML and CSS code I've implemented for this effect. ============================== ...

Building relational meteor databases for hierarchical structures

Hey there, I'm diving into the world of Meteor and Mongo and I've got some basic questions on designing databases. Imagine I'm creating a turn-based strategy game similar to Advance Wars. I'm stuck on how to structure my data efficient ...

Declare the variable as a number, yet unexpectedly receive a NaN in the output

I'm facing an issue with a NaN error in my TypeScript code. I've defined a variable type as number and loop through an element to retrieve various balance amounts. These values are in the form of "$..." such as $10.00 and $20.00, so I use a repla ...

The jQuery fadeToggle function toggles the visibility of an element starting from hidden instead

I'm having an issue where text in my div only appears on the second click, instead of the first. What could be causing this problem? $('#fPaperCirclePic').on('click', function () { $('#fPaperCircleText, #isargebla, #moq10 ...

"Customize the font style of columns in a WordPress table created with TablePress by setting them to it

Recently, I designed a table in a WordPress blog using the TablePress plugin. My intention now is to style the left column's font in italics, excluding the table header. ...

The Power of Symfony Combined with jQuery's Data Handling Function

My app features an ajax navigation system. Each ajax link is given the class ajax, and the page it should load is stored in an aurl attribute, as shown below: <a class="ajax" aurl="/user/posts/3/edit">Edit Post</a> The element's aurl is ...

Struggling to grasp the concept within this particular Array.map callback

Within my React component, I am exploring the concept of the this keyword and its context with the following code snippet. While this example may seem simple, it is part of my efforts to enhance my comprehension. const NAVBAR_ITEM_TITLES = ["Home" ...

Error encountered: CORS restriction preventing access when attempting to connect from local network

I am currently developing a web application where the backend retrieves data from a MongoDB and then the frontend displays it. Here is a simplified outline of the setup: Backend (ExpressJs) const app = express(); const port = process.env.PORT || 3001; a ...

.displaying a grid of div elements is not functioning as expected

On a single page, there is a grid of Divs (2 by 3) with a menu (<li> in <lu>) positioned to the left of the grid. Each menu section contains its own grid of divs, all enclosed within one main div to facilitate manipulation. Menu Sections: < ...

After applying array.map, Material UI ToggleButton does not display correctly with either Jest or React Testing Library. It was functioning properly before the array.map was implemented. What could

Code Testing: import { render, screen } from "@testing-library/react"; import App from "../App"; test("The 2nd button is rendered", () => { render(<App />); expect(screen.getByRole("button", { name: &qu ...