Tips for including a line within a circular canvas

My progress bar crafted with css, javascript and html looks great (left image).

However, I'm facing a challenge in adding white color dividers to enhance the appearance of the progress bar as shown in the image on the right. Despite my various attempts, I have not been able to achieve this desired effect. I would greatly appreciate any assistance or guidance on how to resolve this issue.

Check out the DEMO

Answer №1

A solution to this problem involves using the globalCompositeOperation property in HTML canvas, which allows us to draw lines over the canvas and use them as a mask to clip the chart. Some adjustments may be necessary to customize the lines to your specific requirements. Here is a starting point for implementing this functionality:

var applyMask = function(numLines, lineWidth) {
  ctx.save();
  ctx.beginPath();
  // Reset any previous rotations:
  ctx.rotate(-1 * options.rotate * Math.PI / 180);
  // Set up the mask:
  ctx.globalCompositeOperation = 'destination-out';
  ctx.lineWidth = lineWidth;
  for (var i = 0; i < numLines; i++) {
    ctx.rotate(Math.PI / (numLines / 2));
    ctx.moveTo(0, 0);
    ctx.lineTo(0, 120);
    ctx.stroke();
  }
  ctx.restore();
}
applyMask(8, 4);

To observe how this code integrates with your existing implementation, you can view either the JSFiddle example or refer to the following functional demo:

// Retrieve canvas element
var el = document.getElementById('graph');

// Define custom options
var options = {
    percent: el.getAttribute('data-percent') || 45,
    size: el.getAttribute('data-size') || 220,
    lineWidth: el.getAttribute('data-line') || 25,
    rotate: el.getAttribute('data-rotate') || 200
}

// Create new canvas element
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = el.getAttribute('data-text') + ' $';

if (typeof(G_vmlCanvasManager) !== 'undefined') {
    G_vmlCanvasManager.initElement(canvas);
}

var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);

ctx.translate(options.size / 2, options.size / 2); 
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); 

var radius = (options.size - options.lineWidth) / 2;

var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'square'; 
ctx.lineWidth = lineWidth;
ctx.stroke();
};

drawCircle('#bbbec3', options.lineWidth, 100 / 100);
drawCircle('#c21b17', options.lineWidth, options.percent / 100);

// Apply mask over the chart
var applyMask = function(numLines, lineWidth) {
  ctx.save();
  ctx.beginPath();
  ctx.rotate(-1 * options.rotate * Math.PI / 180);
  ctx.globalCompositeOperation = 'destination-out';
  ctx.lineWidth = lineWidth;
  for (var i = 0; i < numLines; i++) {
    ctx.rotate(Math.PI / (numLines / 2));
    ctx.moveTo(0, 0);
    ctx.lineTo(0, 120);
    ctx.stroke();
  }
  ctx.restore();
}
applyMask(8, 4);
.chart {
    position: relative;
    width: 220px;
    text-align: center;
}
canvas {
    display: block;
    position:absolute;
    top:0;
    left:0;
}
span {
    color:#555;
    display:block;
    line-height:220px;
    text-align:center;
    width:220px;
    font-family:sans-serif;
    font-size:30px;
    font-weight:100;
    margin-left:5px;
} 
.centerbox{
        display: inline-block;
    bottom: 0;
    width: 45px;
    position: absolute;
    z-index: 1;
    margin-left: -50px;
    border-bottom: 35px solid #fff;
    border-left: 30px solid transparent;
    border-right: 30px solid transparent;
}
<div class="chart" id="graph" data-text="123123" data-percent="55"><label class="centerbox"><i class="fa fa-usd" aria-hidden="true" style="padding-top: 10px;position: absolute;"></i></label></div>

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

Executing asynchronous function in Angular using Typescript

My team and I are new to Angular and we are facing a challenge with invoking methods in sequence and returning a value. The issue is that the return statement is being executed before the completion of the execution process. We have tried various approac ...

Can you share the method for concatenating an object at a specific index within an Array using JavaScript?

Currently, I have an array arr = [object1, object2, object3]. After removing the second index, the array now looks like arr = [object1, object3], and I am looking to add back the removed object2 at its original position in the array so that it becomes a ...

Attempting to extract the data from SweetAlert

I've been attempting to retrieve the return value from sweetalert, but I encountered this: Promise {<pending>} >__proto_:Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]:true resulting from this piece of code: var ret = swal({ ...

The first three AJAX requests are successful, but the fourth one fails to reach the PHP script

I am currently working on cascaded selects (a total of 4) that retrieve data from a database. To populate them, I use SQL queries based on the selection made in the previous select element. To establish communication between the select element and the subs ...

Linking all styles with Angular 2

Is it possible to apply a style when the exact nature of that style is unknown? Consider a scenario where I have a model containing string variables defining styles, as shown below: myStyle1:string="margin-left:10px"; myStyle2:string="margin ...

Blur-triggered form validation

Within my webpage, I'm facing an issue with 5 input fields that need to be validated on blur. Instead of relying on alert boxes, I aim to display either an error or success message through DOM scripting. Despite trying various codes, nothing seems to ...

What is the best way to define a custom route in react-router-dom?

My goal is to have the URL display "/login" in the address bar when I am on the login page. // App.js <Routes> {isLoggedIn ? ( <Route path="/" element={<Root onLogout={handleLogout} />}> <Route index e ...

Updating state in React is not possible

I am having trouble updating my state (specifically with setCoords). The API request is returning a 200 status code and the elements I need are present: https://i.stack.imgur.com/a8QzN.png Below is the code I am working with: const App = () => { co ...

The loading spinner fails to function when triggered by the ng-click or ng-change events in an AngularJS application

I have implemented a loading spinner to display while the page is loading. App.controller('MailFolderController', ['$scope', '$http',function ($scope, $http){ $scope.loading = true; $scope.allotmentStatus = [ {"value ...

How Can I Utilize a URL Parameter Twice to Execute SQL Queries in Two asp.DataLists on a Single Page?

I've been trying everything, but I just can't seem to get one query to function properly. My goal is to retrieve information from the SQL Server database in two separate queries - one for album names (based on URL parameter) and another for song ...

Is my implementation of Model and Views in backbone.js accurate?

I'm new to backbone.js and I've just created my first page. I'm curious to know if I'm headed in the right direction with my approach (if there even is a "correct" way in software development). Is there a way to automatically bind mode ...

Exploring the possibilities of using React for looping?

I have integrated Dexie.js with React for this specific example. However, the implementation details are not of great importance to me. My main focus is on finding out how to iterate through all objects in my IndexDB database using React. In the code snip ...

Looking for reliable resources on establishing a connection between a Google account and my application

I am currently working on creating a react native app that aims to simplify the user login process by allowing them to link their Google account with just one click. This way, users won't have to constantly log in every time they use the app. While I ...

Changing the identification of elements

I noticed that when I open object X and Y, they have the same fields, tabs, and checkboxes. However, I am confused as to why the IDs of the checkboxes and other elements are different. Can you explain what gwt-uid(number) means? Please take a look at the a ...

Ensure that the headers of the table are in perfect alignment with the

Is there a way to create a table with fixed row headers so that column headings stay in place while scrolling? I've managed to achieve this, but now the table headers are not aligned properly with the rows below. I've also created a helpful jsfid ...

Not adhering to directive scope when transclusion is used, despite explicit instructions to do so

Trying to use a transcluding directive within another controller, but the inner scope isn't being redefined as expected. Despite trying different methods, I can't seem to figure out what's going wrong. The simplified code looks like this: ...

Adjust the hue of a circle based on whether the user's position falls within its designated range

I am working with a map that displays several circles, each with its own radius. When the page loads, I capture the user's position and show it on the map. Initially, all circles are red. My goal is to determine if the user's current position fal ...

Transforming a Bootstrap Background Image to a Captivating Video Display

Here is the CSS code snippet that I'm having trouble with: .masthead { position: relative; width: 100%; height: auto; min-height: 35rem; padding: 15rem 0; background: linear-gradient(to bottom, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 75% ...

I'm noticing multiple repeated entries appearing when I try to set the cookie - what could be causing

Currently, I am utilizing the library js-cookie instead of my previous use of jquery.cookie. I have encountered an issue related to duplicating cookie entries. There are occasions when I invoke the following method: Cookies.set('my-cookie-name', ...

What is the method for entering text into a span element and submitting it by hitting the "ENTER" key using Selenium in Python 3.7?

Environment: Using Python 3.7 and Selenium 3.141 Issue : I need to automate commenting on posts using Selenium in a web page. The challenge is that the comment form does not have a traditional "Submit" button; instead, it's a SPAN element where yo ...