{"id":18353649,"url":"https://github.com/taystack/js-counter","last_synced_at":"2025-07-05T10:36:03.315Z","repository":{"id":57164689,"uuid":"167872866","full_name":"taystack/js-counter","owner":"taystack","description":"JavaScript step-counter. Helpful for finding animation values for pure javascript animations.","archived":false,"fork":false,"pushed_at":"2019-01-29T17:54:21.000Z","size":115,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-03T23:11:40.616Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taystack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-27T23:58:18.000Z","updated_at":"2023-03-04T03:23:59.000Z","dependencies_parsed_at":"2022-08-29T19:11:45.395Z","dependency_job_id":null,"html_url":"https://github.com/taystack/js-counter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/taystack/js-counter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taystack%2Fjs-counter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taystack%2Fjs-counter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taystack%2Fjs-counter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taystack%2Fjs-counter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taystack","download_url":"https://codeload.github.com/taystack/js-counter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taystack%2Fjs-counter/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263693662,"owners_count":23497075,"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":[],"created_at":"2024-11-05T21:42:44.358Z","updated_at":"2025-07-05T10:36:03.279Z","avatar_url":"https://github.com/taystack.png","language":"JavaScript","readme":"![JsCounter](https://github.com/taystack/js-counter/blob/master/JsCounter.png?raw=true)\n\n[![codecov](https://codecov.io/gh/taystack/js-counter/branch/master/graph/badge.svg)](https://codecov.io/gh/taystack/js-counter)\n[![Build Status](https://travis-ci.org/taystack/js-counter.svg?branch=master)](https://travis-ci.org/taystack/js-counter)\n\n---\n\n - [Installation](#installation)\n - [What is it?](#what-is-it)\n - [Use](#use)\n - [Documentation](#documentation)\n   - [Constructor](#constructor)\n   - [Attributes](#attributes)\n   - [Methods](#methods)\n\n# Installation\n\n```bash\nyarn add @taystack/js-counter\n```\n\nor\n\n```bash\nnpm i @taystack/js-counter\n```\n\n# What is it?\n\nJsCounter is a step-counter written in JavaScript.\n\n# What is it for?\n\nJsCounter is helpful for finding animation values for pure JavaScript animations. Pure-css transitions can be used to accomplish most any animation task. Sometimes you cannot rely on pure-css to animate things you need.\n\n# Why it was written\n\nDuring an animation loop, I was given two coordinantes `{x1}`, `{x2}`. I needed `{x1}` to get closer to `{x2}` at a constant rate. Simple css transition, but there was one catch; `{x2}` is constantly moving.\n\n\"So, what?\" you say? Well, css transitions are picky. Once they invoke, you can change the target value, but the rate of change to get there is a function of how much time is left. Css transformations get weird with dynamic end-values.\n\n# Use\n\nIf I wanted to change the `style.position.x` property of a DOM item, then I would use this module to track the position of, say, an animal inside an animation loop:\n\n```javascript\nimport Counter from \"@taystack/js-counter\";\n\nclass Animal {\n  constructor(speed, position = 0) {\n    this.speed = speed;\n    this.currentPosition = position;\n    this.position = new Counter(position, position, {increment: this.speed});\n  }\n\n  set target(distance) {\n    this.position.setTarget(distance);\n  }\n\n  animate() {\n    this.currentPosition = this.position.turn();\n    this.style.position.x = this.currentPosition;\n  }\n}\n```\n\nI could then create an animation loop tracking the animal's position chasing, say, another `Animal`. How about a dog chasing a cat?\n\n```javascript\nconst dog = new Animal(5);\nconst cat = new Animal(6, 10); // more speed, further starting position\ncat.target = Infinity; // cat is now targeting Infinity (running away)\n\n(function animateDog() {\n  cat.animate();\n  dog.target = cat.currentPosition; // dog is targeting the cat's position\n  dog.animate():\n  setTimeout(() =\u003e {\n    requestAnimationFrame(animateDog);\n  }, FRAMERATE);\n})();\n```\n\nNow, the `dog` will constantly be \"chasing\" the `cat` by adjusting it's `target` towards the cat's `currentPosition`.\n\nIf you wanted the dog to do something after it caught the cat, you could modify the `set target(distance)` setter method into an instance method that accepts `onDone`. Let's say, `hunt(distance, onDone)`:\n\n```javascript\nclass Hunter extends Animal {\n  ...\n  eat(animal) {/* ... */}\n\n  hunt(distance, onDone) {\n    this.onDone = onDone;\n    this.position.setTarget(distance, { onDone });\n  }\n  ...\n}\n```\n\nNow we can actually do something if our `dog` ever catches the `cat`. Let's try a wolf with our new `Hunter` class:\n\n```javascript\nconst wolf = new Hunter(7);\nconst cat = new Animal(6);\ncat.target = Infinity;\n\n(function animate() {\n  cat.animate();\n  wolf.hunt(cat.currentPosition, () =\u003e { wolf.eat(cat) });\n  setTimeout(() =\u003e {\n    requestAnimationFrame(animate);\n  }, FRAMERATE);\n})();\n```\n\n# Documentation\n\n## Constructor\n\n### `const counter = new Couter(Number from, Number to[, Object options])`\n\n#### Params\n\n   - #### `from (Number)`\n\n     The value that *`counter`* starts at.\n\n   - #### `to (Number)`\n\n     The value that *`counter`* works towards after each call to *`counter.turn()`*.\n\n   - #### `options (Object)` _\\\u003coptional\u003e_\n\n      - ##### `increment (Number \u003e 0)`\n        The value used to calculate the step size of *`counter.current`* towards *`counter.to`* each time *`counter.turn()`* is called.\n\n        ***Default***: `1`\n\n        ***Note***: This value should always be positive\n\n        ***TODO***: Make this use `Math.abs`\n\n      - ##### `onDone(value) (Function)`\n        `Function` to invoke when *`counter`* reaches it's target.\n\n        ***`onDone` params***\n        - `value (Number)` - *`counter.value`*\n\n## Attributes\n\n   - #### `counter.value`\n\n     The current value of the counter\n\n## Methods\n\n   - #### `counter.turn()`\n\n\t This will advance *`counter.current`* towards *`counter.to`*\n\n     ***Returns:***  `counter.value`\n\n   - #### `counter.setTarget(Number to[, Number increment=1])`\n\n\t Updates the target value of *`counter`*\n\n     ***Note:*** *Params are the same as constructor [to, increment] params*\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaystack%2Fjs-counter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaystack%2Fjs-counter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaystack%2Fjs-counter/lists"}