placing an image within a circular loading icon

I stumbled upon this amazing progress ring by Matěj Husák and I have a vision to incorporate an image inside the ring as shown:

https://i.sstatic.net/MeSeK.png

Here is the original code:

const circle = document.querySelector('.ring-circle');
const radius = circle.r.baseVal.value;
const circumference = radius * 2 * Math.PI;

circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = circumference;

function setProgress(percent) {
  const offset = circumference - percent / 100 * circumference;
  circle.style.strokeDashoffset = offset;
}

function setProgressFromButton() {
    setProgress(document.getElementById("input-percent").value);
}

setProgress(10);
body, html {
    margin: 0;
    background-color: #2D132C;
    height: 100%;
    font-family: Sanchez, sans-serif;
    color: white;
}

h1 {
    margin: 0px;
    margin-bottom: 24px;
    font-size: 24px;
    text-align: center;
    font-weight: 100;
}

button:active {
    outline: none;
}

button:focus {
    outline: none;
}

.container {
    width: 350px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}


.button-start {
    font-family: Sanchez;
    font-style: normal;
    font-weight: normal;
    font-size: 16px;
    line-height: 20px;
    text-align: center;
    color: #FFFFFF;
    padding: 6px 26px;
    border: none;
    display: block;
    margin-left: auto;
    margin-right: auto;
    display: inline-block;
    border-bottom: 4px solid #C72C41;;
    background: #EE4540;
    cursor: pointer;
    vertical-align: top;
    transition: 250ms ease;
}

.button-start:hover {
    background: #EE342F;

}

.button-start:active {
    border-bottom: none;
}


h1 {
    margin-bottom: 0px;
}

.ring {
    display: block;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 40px;
    margin-top: 40px;
    transform: rotate(90deg);
}

.ring-circle {
    stroke-dasharray: 10 20;
    transition: stroke-dashoffset 0.60s ease;
}

#input-percent {
    width: 121px;
    height: 30px;
    background: #881238;
    border:none;
    border-bottom: 4px solid #660B28;
    vertical-align: top;
    margin-top: 2px;
    padding-right: 8px;
    color: white;
    font-family: Sanchez;
    font-style: normal;
    font-weight: normal;
    font-size: 16px;
    line-height: 20px;
    text-align: center;
    text-align: right;
}

.input-wrapper {
    width: max-content;
    margin-left: auto;
    margin-right: auto;
    display: block;
}

input:active {
    outline: none;
}
input:focus {
    outline: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>The progress ring</title>
    <link href="https://fonts.googleapis.com/css?family=Sanchez&display=swap" rel="stylesheet">
</head>
<body>
    <div class="container">
    <h1 id="main-header">The progress ring.</h1>


      <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/18320/profile/profile-512.jpg?3"/>

    <svg class="ring" height="200" width="200">
        <circle stroke-width="18" stroke="#801336" fill="transparent" r="84" cx="100" cy="100"/>
        <circle class="ring-circle" stroke-width="18" stroke="#EE4540" fill="transparent" r="84" cx="100" cy="100"/> 
    </svg>

    <div class="input-wrapper">
        <input id="input-percent" value="10" type="text" name="" id="">
        <button onclick="setProgressFromButton()" id="confirm-button" class="button-start">Ok</button>
    </div>
    
</div>
</body>
</html>

The challenge lies in using SVG for the ring and facing difficulties incorporating the image within the circle without affecting other elements.

Answer №1

If you want to embed HTML inside an SVG, you can utilize the <foreignObject ...> element. Then, it's just a matter of styling the image to fit your requirements.

For example:

<foreignObject height="150" width="150" x="25" y="25">
  <img
    src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/18320/profile/profile-512.jpg?3"
    style="border-radius: 50%; width: 100%; height: 100%;"
  />
</foreignObject>

Below is an edited version based on what you provided:

const circle = document.querySelector('.ring-circle');
const radius = circle.r.baseVal.value;
const circumference = radius * 2 * Math.PI;

circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = circumference;

function setProgress(percent) {
  const offset = circumference - percent / 100 * circumference;
  circle.style.strokeDashoffset = offset;
}

function setProgressFromButton() {
    setProgress(document.getElementById("input-percent").value);
}

setProgress(10);
body, html {
    margin: 0;
    background-color: #2D132C;
    height: 100%;
    font-family: Sanchez, sans-serif;
    color: white;
}

h1 {
    margin: 0px;
    margin-bottom: 24px;
    font-size: 24px;
    text-align: center;
    font-weight: 100;
}

button:active {
    outline: none;
}

button:focus {
    outline: none;
}

.container {
    width: 350px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
...
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>The progress ring</title>
    <link href="https://fonts.googleapis.com/css?family=Sanchez&display=swap" rel="stylesheet">
</head>
<body>
    <div class="container">
    <h1 id="main-header">The progress ring.</h1>
      
      ...
        
        <svg class="ring" height="200" width="200">
          <circle stroke-width="18" stroke="#801336" fill="transparent" r="84" cx="100" cy="100"/>
          <circle class="ring-circle" stroke-width="18" stroke="#EE4540" fill="transparent" r="84" cx="100" cy="100"/> 
          
          <foreignObject height="150" width="150" x="25" y="25">
            <img
              src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/18320/profile/profile-512.jpg?3"
              style="border-radius: 50%; width: 100%; height: 100%;"
            />
          </foreignObject>

        </svg>

    <div class="input-wrapper">
        <input id="input-percent" value="10" type="text" name="" id="">
        <button onclick="setProgressFromButton()" id="confirm-button" class="button-start">Ok</button>
    </div>
    
</div>
</body>
</html>

The rotation of the image in this demo is due to the CSS rule:

.ring {
  ...
  transform: rotate(90deg);
}

To correct that, simply make adjustments to the CSS as needed.

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

Switch on/off the active class for menu items in a list using VueJS

When I click on a menu item, I want the active class to be triggered only for that specific item and removed for the others. So far, I have written this code: <template> <nav class="navbar"> <div class="navbar__brand"> <ro ...

Tips for customizing the selected and hover color of ListItem in Material UI

Having trouble getting the 'selected' or 'hover' colors to work for the ListItem component. I've tried setting its classes like this: <ListItem selected button key="home" classes={{ selected: classes.listItemSelected } ...

How to Vertically Center an Image in a Row using Bootstrap

I've been struggling for a while to properly center this image within the row that contains the div with the image. Here is the HTML code I am using: <div class="row"> <div class="col-md-9"> <div ...

The alert box for model validation summary errors is deactivated when hidden using .hide() method

In my MVC web application form, there is an optional postcode finder. If there is no match for the entered postcode, I add a custom error message to the .validation-summary-errors section. After the error is fixed, I remove all instances of the postcode cl ...

What strategies can be implemented to decrease the value of the writing box by 2.5%?

I would like to decrease the value in the input box by 2.5%. Here is the HTML code snippet: <div class="ZakatCalc"> <div class="calcimg"> <img src="" alt="" srcset="" class=" ...

Choose a select few checkboxes and then disable the remaining checkboxes using Vue and Laravel

I'm currently working on a project using Laravel 10 and Vue3. In the form, users are allowed to select only 3 checkboxes. Once they have selected 3 checkboxes, all remaining checkboxes should be disabled. I attempted to implement this functionality a ...

Should I consider implementing Flexbox even if I need to cater to users still using IE9?

Currently, I am embarking on a fresh project centered around constructing a chat window. Typically, I would readily employ Flexbox for this endeavor; nevertheless, one of the stipulations for this project is to ensure compatibility with IE9. While I under ...

Customizing handleSubmit in redux-form for dynamic form handling

Being relatively new to the React ecosystem, my approach and understanding may be somewhat off, but I trust you can comprehend my issue. I have a parent Component that receives a form from the router and connects state and action creators to its propertie ...

Eliminate any uneven values within the array

I'm in search of a different approach to eliminate all odd numbers from an array. A friend proposed this solution which I understand, but I have yet to think of another method. Do you have any thoughts on how to tackle this differently? Javascript l ...

Error code 10062 occurred on the Discord Bot while verifying the channel name during the processing of a user-sent slash command

I've been developing a Discord bot using JavaScript for a study server with my friends. Currently, I'm working on a feature that allows users to add phone numbers but only in specific channels. Everything was functioning properly until I implemen ...

Unable to extract all advertisements from Facebook Marketplace

https://i.stack.imgur.com/xEhsS.jpg I'm currently attempting to scrape listings from Facebook marketplace, however, only the first listing is being scraped. Does anyone have any suggestions on how I can scrape the entire list of listings? CODE (async ...

Change the height of a div after submitting a form using Django (Python)

I have a registration form with one submit button. Upon clicking submit, if there is an error, the height of the div increases by setting it to height:auto. However, when I click submit, it changes the height of the div (.continer). Strangely, after one ...

Enhance Bootstrap 4 Navigation with Active State Styling

I'm having trouble with my jQuery code in Bootstrap 4. No matter what I try, I can't seem to add an "active" class to the nav-link that I click on. <script> $(document).ready(function () { $('.nav-link').click(function() { ...

Responsive design issues with Bootstrap Popover

Whenever I open the popover for the first time, the image is not displayed correctly. How can I ensure that it always shows correctly? Here is a link to the issue: https://jsfiddle.net/n2Lfro30/1/ Below is the button code causing the problem: <button ...

Searching for an array of objects within a MongoDB collection using queries

I have a collection where I store information in an array of objects named Degrees. Each object in this array has keys like {Uni:'',Level:'',Degree:''}. I am trying to create a query that will help me find documents with a de ...

NodeJs Classes TypeError: Unable to access 'name' property as it is undefined

I am currently developing a useful API using Node.js. In order to organize my code effectively, I have created a UserController class where I plan to include all the necessary methods. One thing I am struggling with is how to utilize a variable that I set ...

Communicating TCP/IP with hexadecimal codes in JavaScript

As I work on my client application using a node module called 'net' to send data through a TCP socket, I need to make sure the message I'm sending starts and ends with specific hex codes. In this case, the data packet should begin with "0F" ...

Issue with back button functionality when loading page with history.pushState in JavaScript

My current issue involves loading a page via ajax using history.pushState. The page loads successfully, but the back button does not work as expected. I have included my code below for reference: function processAjaxData(response, urlPath){ document.wr ...

The directive is becoming unbound

Currently, I am facing an issue with my code. I have set up a fiddle that demonstrates a directive displaying an alert and also a controller with an alert function. Everything is functioning correctly except for the fact that the binding for the text on th ...

How can I ensure a header is displayed on each page by utilizing CSS or JavaScript/jQuery?

On a lengthy page with approximately 15 pages of text, I would like to insert a header at the beginning of each page when the document is printed by the user. Can this functionality be achieved using CSS or JavaScript/jQuery? ...