{"id":15388237,"url":"https://github.com/georapbox/canvas-circular-countdown","last_synced_at":"2025-09-11T23:21:27.491Z","repository":{"id":32941407,"uuid":"143865972","full_name":"georapbox/canvas-circular-countdown","owner":"georapbox","description":"Draw a configurable circular canvas countdown timer.","archived":false,"fork":false,"pushed_at":"2023-01-08T16:04:43.000Z","size":822,"stargazers_count":17,"open_issues_count":3,"forks_count":8,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-05T11:11:26.974Z","etag":null,"topics":["circularprogressbar","countdown-timer","html5-canvas","progress-bar"],"latest_commit_sha":null,"homepage":"https://georapbox.github.io/canvas-circular-countdown/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/georapbox.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-07T11:50:28.000Z","updated_at":"2025-03-24T07:22:54.000Z","dependencies_parsed_at":"2023-01-14T22:46:08.510Z","dependency_job_id":null,"html_url":"https://github.com/georapbox/canvas-circular-countdown","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/georapbox/canvas-circular-countdown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georapbox%2Fcanvas-circular-countdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georapbox%2Fcanvas-circular-countdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georapbox%2Fcanvas-circular-countdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georapbox%2Fcanvas-circular-countdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/georapbox","download_url":"https://codeload.github.com/georapbox/canvas-circular-countdown/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georapbox%2Fcanvas-circular-countdown/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266242072,"owners_count":23898102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["circularprogressbar","countdown-timer","html5-canvas","progress-bar"],"created_at":"2024-10-01T14:56:05.884Z","updated_at":"2025-07-21T05:06:26.675Z","avatar_url":"https://github.com/georapbox.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm version](https://img.shields.io/npm/v/canvas-circular-countdown.svg)](https://www.npmjs.com/package/canvas-circular-countdown)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://georapbox.mit-license.org/@2018)\n\n# canvas-circular-countdown\n\nDraw a configurable circular canvas countdown timer.\n\nCheck [here](https://georapbox.github.io/canvas-circular-countdown/) for a live demo.\n\n**NOTE:** Depends on `window.requestAnimationFrame`. If your environment does not support it, you can [polyfill](https://github.com/darius/requestAnimationFrame).\n\n## Install\n\n```sh\n$ npm install canvas-circular-countdown --save\n```\n\n## Usage\n\nThe library is exported in UMD, CommonJS, and ESM formats. You can import it the following ways:\n\n### Using ESM import statement\n\n```js\nimport CanvasCircularCountdown from 'canvas-circular-countdown';\n```\n\n### Using CommonJS require statement\n\n```js\nconst CanvasCircularCountdown = require('canvas-circular-countdown').default;\n```\n\n### Old school browser global\n```html\n\u003cscript src=\"https://unpkg.com/canvas-circular-countdown\"\u003e\u003c/script\u003e\n```\n\n## API\n\n### Instantiation\n\n```js\nnew CanvasCircularCountdown(element, [options], [onTimerRunning])\n```\n\n| Param | Type | Description |\n| --- | --- | --- |\n| `element` | HTMLElement | (Required) The element that the countdown is drawn to. If is a `canvas` element, the countdown will be drawn on it; otherwise a `canvas`  element will be created and appended to `element`. |\n| `options` | Object | (Optional) Options that can be overriden by user. See below for more details about each option. |\n| `onTimerRunning` | Function | (Optional) Function to be executed while timer is running. Parameters passed by include the percentage remaining, an object containing the remaining and elapsed time and the `CanvasCircularCountdown` instance. |\n\n### Options\n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| `duration` | Number | `60 * 1000` | The timer's duration in milliseconds. Throws `TypeError` if the provided value is not a `Number` or is `NaN`. |\n| `elapsedTime` | Number | `0` | The time that has elapsed in milliseconds. Throws `TypeError` if the provided value is not a `Number` or is `NaN`. |\n| `throttle` | Number | `undefined` | Throttle duration in milliseconds. Must be a number lower or equal to the `duration` option. If provided, it limits the number of times the canvas is drawn in the given period, therefore the number of times the callback function `onTimerRunning` can be called. You can use it if you perform heavy tasks inside the `onTimerRunning` callback function to improve performance. Always prefer small numbers, eg. 250, etc |\n| `clockwise` | Boolean | `false` | Determines the direction of the progress ring. By default the direction is counterclockwise. |\n| `radius` | Number | `150` | The radius of the circular countdown in pixels. |\n| `progressBarWidth` | Number | `15` | The circular progress bar in pixels. |\n| `progressBarOffset` | Number | `5` | The number of pixels that will be left between the edges of the progress bar and the rest of the circle. |\n| `circleBackgroundColor` | String | `\"#ffffff\"` | The background color of the main circle. |\n| `emptyProgressBarBackgroundColor` | String | `\"#dddddd\"` | The background color of the progress bar when is empty. |\n| `filledProgressBarBackgroundColor` \u003csup\u003e1\u003c/sup\u003e | String\\|Function | `\"#00bfeb\"` | The background color of the progress bar when is filled. |\n| `captionText` \u003csup\u003e1\u003c/sup\u003e | String\\|Function | `undefined` | The text to be displayed as caption inside the countdown circle. By default if it is left as `undefined` and `showCaption` is set to true, the remaining percentage will be displayed. |\n| `captionColor` \u003csup\u003e1\u003c/sup\u003e | String\\|Function | `\"#343a40\"` | The foreground color of the caption string. |\n| `captionFont` \u003csup\u003e1\u003c/sup\u003e | String\\|Function | `\"20px sans-serif\"` | The text style of the caption string. Check [here](https://developer.mozilla.org/en-US/docs/Web/CSS/font) for available values. |\n| `showCaption` \u003csup\u003e1\u003c/sup\u003e | Boolean\\|Function | `true` | Whether the caption text inside the countdown circle will be displayed or not. |\n| `draw` | Function | `undefined` | A function that exposes `CanvasRenderingContext2D` to allow free drawing on the canvas element. The function is called with 2 arguments. The first argument is the `CanvasRenderingContext2D` and the second is an object with information like the canvas width/height, the remaining percentage and an object containing the remaining and elapsed time. |\n\n\u003csup\u003e1\u003c/sup\u003e *If it is a function, the remaining percentage and an object containing the remaining and elapsed time are passed as parameters and it should return the appropriate type for each option. For example, for `showCaption` should return a boolean (true or false), but for `captionColor` should return a string. Useful when you need to change some options' values depending on the remaining percentage or the remaining/elapsed time.*\n\n### Instance methods\n\n### start()\n\nStart the timer. If the timer has been already started, the timer will just resume.\n\n```js\nstart() =\u003e CanvasCircularCountdown\n```\n\n### stop()\n\nStop/Pause the timer.\n\n```js\nstop() =\u003e CanvasCircularCountdown\n```\n\n#### reset()\n\nResets the timer to initial specified `duration` extracting the `elapsedTime` if provided.\n\n```js\nreset() =\u003e CanvasCircularCountdown\n```\n\n#### style(options = {})\n\nChange the styles of the circular countdown at any time while te timer running.\n\n| Param | Type | Default | Description |\n| ----- | ---- | ------- | ----------- |\n| options | \u003ccode\u003eObject\u003c/code\u003e | `{}` | Any of the options provided above can be changed apart from the `duration`, `elapsedTime` and `throttle` options. |\n\n```js\nstyle(options = {}) =\u003e CanvasCircularCountdown\n```\n\n#### setDuration(time)\n\nSet the timer's duration (in milliseconds), at any time, even when the timer is running.\n\n| Param | Type | Default | Description |\n| ----- | ---- | ------- | ----------- |\n| time | `Number` | - | The timer's duration in milliseconds. Throws `TypeError` if the provided value is not a `Number` or is `NaN`. |\n\n```js\nsetDuration(time) =\u003e CanvasCircularCountdown\n```\n\n#### setElapsedTime(time)\n\nSet the timer's elapsed time (in milliseconds), at any time, even when the timer is running.\n\n| Param | Type | Default | Description |\n| ----- | ---- | ------- | ----------- |\n| time | `Number` | - | The timer's elapsed time in milliseconds. Throws `TypeError` if the provided value is not a `Number` or is `NaN`. |\n\n```js\nsetElapsedTime(time) =\u003e CanvasCircularCountdown\n```\n\n## Examples\n\n### Example 1 - Default configuration\n\nCreate a new instance of `CanvasCircularCountdown` with the default configuration and immediately start the countdown timer. Pause the countdown after 5 seconds have passed.\n\n#### HTML\n\n```html\n\u003ccanvas id=\"countdown-canvas\"\u003e\u003c/canvas\u003e\n```\n\n#### JavaScript\n\n```js\nnew CanvasCircularCountdown(document.getElementById('countdown-canvas'), (percentage, time, instance) =\u003e {\n  if (time.elapsed \u003e= 5000) {\n    instance.stop();\n  }\n}).start();\n```\n\n### Example 2 - Custom configuration\n\nSame as the above example, but with custom configuration.\n\n#### HTML\n\n```html\n\u003ccanvas id=\"countdown-canvas\"\u003e\u003c/canvas\u003e\n```\n\n#### JavaScript\n\n```js\nnew CanvasCircularCountdown(document.getElementById('countdown-canvas'), {\n  duration: 30 * 1000,\n  radius: 200,\n  progressBarWidth: 20,\n  progressBarOffset: 0,\n  circleBackgroundColor: '#f5f5f5',\n  emptyProgressBarBackgroundColor: '#b9c1c7',\n  filledProgressBarBackgroundColor: '#17a2b8',\n  captionColor: '#6c757d',\n  captionFont: '22px serif',\n  showCaption: true\n}, (percentage, time, instance) =\u003e {\n  if (time.elapsed \u003e= 5000 ) {\n    instance.stop();\n  }\n}).start();\n```\n\n### Example 3 - Change progress bar and caption string color depending on percentage remaining\n\n#### HTML\n\n```html\n\u003ccanvas id=\"countdown-canvas\"\u003e\u003c/canvas\u003e\n```\n\n#### JavaScript\n\n```js\nconst pickColorByPercentage = (percentage, time) =\u003e {\n  switch (true) {\n    case percentage \u003e= 75:\n      return '#28a745'; // green\n    case percentage \u003e= 50 \u0026\u0026 percentage \u003c 75:\n      return '#17a2b8'; // blue\n    case percentage \u003e= 25 \u0026\u0026 percentage \u003c 50:\n      return '#ffc107'; // orange\n    default:\n      return '#dc3545'; // red\n  }\n}\n\nnew CanvasCircularCountdown(document.getElementById('countdown-canvas'), {\n  filledProgressBarBackgroundColor: pickColorByPercentage,\n  captionColor: pickColorByPercentage\n}).start();\n```\n\n### Example 4 - Responsive canvas\n\n#### HTML\n\n```html\n\u003cdiv id=\"countdown-container\"\u003e\n  \u003ccanvas id=\"countdown-canvas\"\u003e\u003c/canvas\u003e\n\u003c/div\u003e\n```\n\n#### CSS\n\n```css\n#countdown-container {\n  width: 100%;\n  max-width: 500px;\n}\n```\n\n#### JavaScript\n\n```js\nconst containerEl = document.getElementById('countdown-container');\nconst countdownEl = document.getElementById('countdown-canvas');\n\nconst countdown = new CanvasCircularCountdown(countdownEl, {\n  radius: containerEl.getBoundingClientRect().width / 2\n}).start();\n\nlet resizeTimeout;\n\nwindow.addEventListener('resize', () =\u003e {\n  clearTimeout(resizeTimeout);\n\n  resizeTimeout = setTimeout(() =\u003e {\n    countdownEl.style({\n      radius: containerEl.getBoundingClientRect().width / 2\n    });\n  }, 250);\n```\n\n### Example 5 - Change caption text depending on percentage\n\n#### HTML\n\n```html\n\u003ccanvas id=\"countdown-canvas\"\u003e\u003c/canvas\u003e\n```\n\n#### JavaScript\n\n```js\nnew CanvasCircularCountdown(document.getElementById('countdown-canvas'), {\n  captionText: percentage =\u003e {\n    if (percentage \u003c= 25) {\n      return 'Time is running out!';\n    }\n\n    return 'There is time. Don\\'t worry!';\n  }\n}).start();\n```\n\n### Example 6 - Free draw on canvas element\n\n#### HTML\n\n```html\n\u003ccanvas id=\"countdown-canvas\"\u003e\u003c/canvas\u003e\n```\n\n#### JavaScript\n\n```js\nnew CanvasCircularCountdown(document.getElementById('countdown-canvas'), {\n  draw: (ctx, opts) =\u003e {\n    // Draw a in the centre of the canvas element,\n    // with radius being 1/4 of the canvas width.\n    ctx.save();\n    ctx.beginPath();\n    ctx.arc(opts.width / 2, opts.height / 2, opts.width / 4, 0, 4 * Math.PI, false);\n    ctx.lineWidth = 5;\n    ctx.strokeStyle = opts.percentage \u003e= 50 ? '#008000' : '#ff0000'; // change color according to percentage\n    ctx.stroke();\n    ctx.restore();\n  }\n}).start();\n```\n\n## License\n\n[The MIT License (MIT)](https://georapbox.mit-license.org/@2018)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorapbox%2Fcanvas-circular-countdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeorapbox%2Fcanvas-circular-countdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorapbox%2Fcanvas-circular-countdown/lists"}