Tips for finishing Vuetify's circular progress bar using a center percentage value

I've been exploring the features of Vuetify's progress circular component lately. This component allows you to specify a value prop, which represents the current progress percentage. The circle completes when the value reaches 100.
In my scenario, I'm working on a countdown where the maximum percentage value is limited to 10. I want the circle to indicate completion at this value. However, I'm facing challenges in achieving this for mid-range percentage values.

Is there a way to accomplish this?

Below is an example code snippet illustrating my attempt to replicate the completion effect of a 100-value circle for values like 10 and 20.

Note- Values can be multiples of 10, such as 10, 20, 30, 50, and so on.

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      second_10: 10,
      second_20: 20,
      second_100: 100,
      interval_10: null,
      interval_20: null,
      interval_100: null,
    }
  },
  methods: {
    countDown(val) {
      this[`interval_${val}`] = setInterval(() => {
         if(this[`second_${val}`] == 0) {
           this[`second_${val}`] = val
         } else {
           this[`second_${val}`]--;
         }
      }, 1000)
    },
    stopCountDown() {
      clearInterval(this.interval_10);
      clearInterval(this.interval_20);
      clearInterval(this.interval_100)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2c5a59496c1e0254">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="16606373627f706f562438253827">[email protected]</a>/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f6808393829f908fb6c4d8c5d8c7">[email protected]</a>/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons"/>
<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-row>
        <v-col cols="12" align="center">
          <v-btn small color="error" @click="stopCountDown()">Stop Timer</v-btn>
        </v-col>
        <v-col>
          <v-btn small @click="countDown(100)">start timer</v-btn>
          <v-progress-circular
            :rotate="360"
            :size="50"
            :width="5"
            :value="second_100"
            color="success"
            class="mt-3"
            >
            {{ second_100 }}
          </v-progress-circular>
        </v-col>
        <v-col>
          <v-btn small @click="countDown(10)">start timer</v-btn>
          <v-progress-circular
            :rotate="360"
            :size="50"
            :width="5"
            :value="second_10"
            color="success"
            class="mt-3"
            >
            {{ second_10 }}
          </v-progress-circular>
        </v-col>
        <v-col>
          <v-btn small @click="countDown(20)">start timer</v-btn>
          <v-progress-circular
            :rotate="360"
            :size="50"
            :width="5"
            :value="second_20"
            color="success"
            class="mt-3"
            >
            {{ second_20 }}
          </v-progress-circular>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</div>

Answer №1

To achieve a target of 100 from your initial countdown value, you must determine the multiplier. Simply use the formula

counter * (100 / initialCounterValue)
to calculate it.

It is important to note that the initial counter value must be a multiple of 100 for this formula to work effectively. It may not yield accurate results with values like 18.

I recommend creating a component to centralize this logic in one place:

<template>
  <v-col>
     <v-btn small @click="startCountdown">start timer</v-btn>
     <v-progress-circular
        :rotate="360"
        :size="50"
        :width="5"
        :value="counter * (100 / from)"
        color="success"
        class="ms-4"
     >
       {{ counter }}
     </v-progress-circular>
   </v-col>
</template>
<script>
export default {
  props: {
    from: { type: Number, default: 10 }
  },
  data() {
    return {
       counter: this.from,
       interval: null,
    }
  },
  methods: {
    startCountdown() {
       this.interval = setInterval(() => {
          if (this.counter <= 0 && this.interval) {
             clearInterval(this.interval)
          } else {
             this.counter--;
          }
       }, 1000)
    }
  }
}
</script>

Here's an example using the formula:

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      second_100: 100,
      second_20: 20,
    }
  },
  methods: {
    countDown(val) {
      setInterval(() => {
         if(this[`second_${val}`] == 0) {
           this[`second_${val}`] = val
         } else {
           this[`second_${val}`]--;
         }
      }, 1000)
    },
  }
})
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1365667653213d6b">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5a2c2f3f2e333c231a687469746b">[email protected]</a>/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="84f2f1e1f0ede2fdc4b6aab7aab5">[email protected]</a>/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons"/>
<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-row>
        <v-col>
          <v-btn small @click="countDown(100)">start timer</v-btn>
          <v-progress-circular
            :rotate="360"
            :size="50"
            :width="5"
            :value="second_100"
            color="success"
            class="ms-4"
            >
            {{ second_100 }}
          </v-progress-circular>
        </v-col>
        <v-col>
          <v-btn small @click="countDown(20)">start timer</v-btn>
          <v-progress-circular
            :rotate="360"
            :size="50"
            :width="5"
            :value="second_20 * (100/20)"
            color="success"
            class="ms-4"
            >
            {{ second_20 }}
          </v-progress-circular>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</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

The function `jQuery .html('<img>')` is not functional in Firefox and Opera browsers

This particular code snippet jq("#description" + tourId).html('<b>Opis: </b> '+ data); has been tested and functions correctly in Internet Explorer, Firefox, and Opera. However, when it comes to this specific piece of code jq("#i ...

Updating a JSON file with new object using node.js

Currently, I am attempting to insert a single object into an extensive JSON file. My approach involves parsing the entire file using FS and JSON.Parse, adding the new JSON object in memory, and then rewriting the file. While I am aware of FS's append ...

Exploring the transparency of material lab autocomplete drop-down text for enabling multiple selections

Check out this demo for checkboxes and tags in Material UI The code below demonstrates an autocomplete component that functions correctly. However, the drop-down text appears transparent. Is there a way to fix this issue without modifying any libraries? ...

Why Jquery's nth-child selection and conditional formatting are failing to work

I am working with a table and need to format specific data fields based on their content. For instance, any field less than 95% should be highlighted in red. Below is the jQuery code I am using: $(function(){ $('#ConditionalTable td:nth-child(2n ...

Ways to bring GIFs into NextJS

I am currently working on my portfolio website using Nextjs and I would like to incorporate gifs into the site. However, I have been struggling to figure out how to do so. Below is the code that I have been working with: https://i.stack.imgur.com/zjoiD.pn ...

Exploring the world of JSON files using JavaScript

Basically, my bot responds to a command (!accounts) by providing users with information based on their ID. For example, if an ID of 662 sends the command !account, the bot will search for steamID 662 in the json files and display the currency and correspon ...

Retrieve an array from a JSON object by accessing the corresponding key/value pair using the utility library underscore

I have a dataset in JSON format (as shown below) and I am attempting to use the _.where method to extract specific values from within the dataset. JSON File "data": [{ "singles_ranking": [116], "matches_lost": ["90"], "singles_high_rank": [79 ...

Tips for updating VUE's main.js file to incorporate the routers/index.js configuration

What is the reason for the difference in syntax between the VUE UI main.js code generated by CLI/3 and the older version, and how does it function? What are the various components of the new syntax and how do they work? sync(store, router) // for vuex-rou ...

Mongoose fails to persist data

Exploring the world of Express and following a tutorial to create a project. Currently stuck in the seeding phase where I am trying to populate my database with data. However, when I execute the command node product-seeder.js in the terminal, no data is be ...

What is the best method for connecting a ref to a component that I am duplicating with React.cloneElement?

Hi everyone! I'm trying to pass a ref into my component so that I can access the variables on the component like state. The only problem is, I'm having trouble getting it to work. It needs to be functional for both classes and functions. Every t ...

Tips for simulating a window event in Vue Test Utils while conducting unit tests

I have included 'attachToDocument' in my code, but I am still unable to trigger a keyup event on the window. The versions of my dependencies are: "@vue/test-utils": "^1.0.0-beta.29" "vue": "2.5.18" <template lang="pug"> div h1 123 < ...

When the browser back button is clicked, conceal the current div and reveal the previously hidden div

I'm faced with a situation where my website consists of multiple pages which I've achieved by displaying and hiding divs within a single html file. The issue I'm encountering is that the browser's back and forward buttons aren't fu ...

Steps for adding a delete icon to a text input field and enabling the functionality to delete text

In the code snippet below, I am creating a text input field: <input type="text" class="signup-input text-value" name="" placeholder="e.g. <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2d48554c405d41486d">[email pro ...

"Troubleshooting an issue with post requests in VueJS and Laravel resulting in

Trying to execute a basic POST request using VueJS 2 (with axios) and Laravel 5.3, but encountering an issue where my method consistently returns an empty array when attempting to print $request->all(). The blade template includes the following meta ta ...

How can I make an image the background on a webpage when clicking the mouse?

I find myself in a predicament without any code to guide me. The idea seems simple - I desire the ability to select an image from a collection and set it as the background image for the webpage. While I understand that JavaScript is essential for this tas ...

A Vue filtering feature that consistently adds 5 additional elements upon each use

I was wondering, how can I create a computed property filter function that always adds 5 more elements to the current array? Here are more details: Template: <span class="box-content" v-for="item in activeItems" :key="item.id"> <img class=" ...

Guide on utilizing Vue to trigger an API call when the input box loses focus

I am currently facing challenges while trying to learn vue, and I am not sure how to proceed. I would greatly appreciate any assistance! To begin with, I want to acknowledge that my English may not be perfect, but I will do my best to explain my issue tho ...

What is the best way to perform a single asynchronous or promise-based fetch request and utilize the retrieved data across multiple functions?

Is there a way to optimize fetching data from an API and use the fetched data in multiple methods within the same service without making redundant requests in the Network? export class MediaService { constructor(private mediaAppApiService: MediaAppApiS ...

What could be causing getStaticProps to receive an incorrect slug value?

Currently, I am encountering an issue with obtaining the correct slug in getStaticProps(). My goal is to retrieve the translated slug for a specific page (for example: the about page). The getStaticPaths() function is able to generate the correct object. ...

Vue.js combined with Video.js (MPEG-DASH) is throwing an error: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED)

I am facing an issue with Video.js when using it as a component in vue.js. I receive a .mpd link from a server and I want to display the video from that link. Following the example in the documentation of Video.js and Vue integration. Every time I call th ...