{"id":23327861,"url":"https://github.com/zouloux/virtual-mouse","last_synced_at":"2026-04-26T23:31:23.798Z","repository":{"id":268927276,"uuid":"905873050","full_name":"zouloux/virtual-mouse","owner":"zouloux","description":"Move a virtual cursor on your website to show features in screencasts with a smooth cursor interaction.","archived":false,"fork":false,"pushed_at":"2025-01-09T10:06:11.000Z","size":9180,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-07T07:54:10.374Z","etag":null,"topics":["cursor","mouse","node","screencast","virtual"],"latest_commit_sha":null,"homepage":"https://zouloux.github.io/virtual-mouse/","language":"TypeScript","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/zouloux.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-19T17:35:15.000Z","updated_at":"2025-01-09T10:06:15.000Z","dependencies_parsed_at":"2024-12-19T19:19:43.906Z","dependency_job_id":"df13d448-58d2-4e11-9006-70594f366211","html_url":"https://github.com/zouloux/virtual-mouse","commit_stats":null,"previous_names":["zouloux/virtual-mouse"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zouloux/virtual-mouse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fvirtual-mouse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fvirtual-mouse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fvirtual-mouse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fvirtual-mouse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zouloux","download_url":"https://codeload.github.com/zouloux/virtual-mouse/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fvirtual-mouse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32317162,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"ssl_error","status_checked_at":"2026-04-26T23:26:25.802Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["cursor","mouse","node","screencast","virtual"],"created_at":"2024-12-20T20:42:19.254Z","updated_at":"2026-04-26T23:31:23.775Z","avatar_url":"https://github.com/zouloux.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Virtual Mouse\n\nMove a virtual cursor on your website to show features in **screencasts** with a **smooth cursor interaction**.\n\nIt can be loaded on any website, without access to the source code.\n\nVirtual Mouse also has its **own studio** to create scene from user actions.\n\n- [See video ↗](https://zouloux.github.io/virtual-mouse/example.mp4)\n- [Try Demo ↗](https://zouloux.github.io/virtual-mouse/)\n\n- [How it works ↓](#how-it-works)\n- [Code Example ↓](#code-example)\n- [Virtual Mouse Studio ↓](#virtual-mouse-studio)\n- [NPM ↓](#npm)\n- [Test it ↓](#test-it)\n\n---\n## How it works\n\nIt creates a virtual cursor on the screen, over your website.\nYou can move it, scroll and click on elements to simulate user interactions.\nIt can be useful to create screen captures of your website with a super smooth mouse move.\n\n#### Hovers\nJavascript cannot trigger CSS `:hover` pseudo state on DOM elements,\nIt can work thanks to [this lib](https://github.com/TSedlar/pseudo-styler) which permit virtual mouse to trigger CSS `:hover` like the user's cursor.\n\nIt has a known issue when the `:hover` is inside a media query, it can't be triggered.\n```css\n@media (min-width: 200px) {\n\t.test:hover {\n\t\t// Will not work\n\t}\n}\n```\n\nTo use it : `await mouse.initHoversHack()`\n\n#### React\n\nReact has its own (and now totally useless) `SyntheticEvents` integration.\nWhich prevents javascript based events to be converted to React elements.\nI found a hack to trigger handlers directly on React elements, it may not work on future react version.\nSimply give any React node and the code will find how to communicate `SyntheticEvents` on all React nodes. \n\nTo use it : `mouse.initReactEvents( document.body.firstChild ) // any react node will do`\n\n#### Scrolls\n\nIts compatible with vertical and horizontal scrolls.\nHorizontal scroll is not supported by the studio but can be used with the `scroll` and `scrollTo` commands. \n\n#### Dependencies\n\nIt has `gsap` as only dependency. Loaded from `esm.sh` if directly in a browser environment.\n\n---\n## Use it, even on websites you don't own\n\nYou can use it on websites loaded in chrome, without having to build anything.\n\nSimply open the developer console and load this lib using :\n```typescript\nconst { createVirtualMousePlayer } = await import('https://esm.sh/@zouloux/virtual-mouse')\n```\n\nWhen loaded, you can start to use it \n```typescript\nconst mouse = createVirtualMousePlayer()\nawait mouse.delay(.2)\nawait mouse.move(400, 400)\nawait mouse.delay(.2)\nawait mouse.click()\nawait mouse.delay(.2)\nawait mouse.hide()\nmouse.dispose()\n```\n\n## Code Example\n\nThis and example you can copy and paste in any website's console.\n\n```typescript\nconst { createVirtualMousePlayer } = await import('https://esm.sh/@zouloux/virtual-mouse')\nconst mouse = createVirtualMousePlayer({\n\t// Hide scroll bar, even if moving, can break rendering\n\thideScrollbar: true,\n\t// Hide user cursor\n\thideCursor: true,\n\t// Print actions and parameters in console\n\tverbose: false,\n\t// Block user mouse wheel inputs\n\tpreventMouseWheel: false,\n\t// Default animation parameters\n\tdefaultAnimate: {\n\t\tduration: 1.0,\n\t\tease: 'power4.inOut', // gsap easings\n\t},\n  \t// Apply custom style on cursor\n\tmouseStyle: {\n\t\ttransform: \"translate(-50%, -50%) scale(2)\",\n\t\tborder: \"2px solid red\",\n\t},\n})\n// Enable hovers hack\nawait mouse.initHoversHack()\n// Enable React synthetic events compatibility\nmouse.initReactEvents()\n// Move mouse to an absolute position in the screen ( not the viewport )\nawait mouse.to(250, 250)\n// Move mouse relatively to its current position\nawait mouse.move(-100, 0)\n// Scroll relatively\nawait mouse.scroll(0, 200)\n// Hide virtual mouse\nawait mouse.hide()\n// Scroll to an absolute position\nawait mouse.scrollTo(0, 0)\n// Show virtual mouse\nawait mouse.hide()\n// Wait 1 second\nawait delay(1)\n// Click on element under virtual mouse\nawait mouse.click()\n// Scroll and move mouse in the same time\nmouse.to(500, 500, { duration: 1 }) // no await\nawait mouse.scroll(0, 500, { duration: 1 })\n// Dispose and go back to normal\nmouse.dispose()\n```\n\n## Viewport size\n\nBecause all positions are absolute to the viewport :\nWhen you create a virtual mouse scene, you have to remember the actual viewport size.\n\n\u003e Virtual Mouse Studio will add a comment with the actual viewport size as a comment\n\n```javascript\n// Url /virtual-mouse-demo.html\n// Viewport: 1440x720\nimport { createVirtualMousePlayer } from \"@zouloux/virtual-mouse\"\nconst mouse = createVirtualMousePlayer({})\n// ...\n```\n\n\n---\n## Virtual Mouse Studio\n\nThe studio can be helpful to record user actions and convert them to a Virtual Mouse Scene.\n\nPaste this in the developer console on the website you want to animate :\n\n```\nconst { createVirtualMouseStudio } = await import('https://esm.sh/@zouloux/virtual-mouse')\ncreateVirtualMouseStudio()\n```\n\nThen, move your cursor on the website, and click around.\n- To register a scroll, use `[CMD]`.\n- To finish your scene, hit `[CMD]` + `[Escape]` key on your keyboard.\n\nThe scene will be copied to your clipboard and ready to be pasted to play the scene.\n\n\n---\n## NPM\n\n[Available on npm ↗️](https://www.npmjs.com/package/@zouloux/virtual-mouse)\n\n```bash\nnpm i @zouloux/virtual-mouse\n```\n\n```typescript\nimport { createVirtualMousePlayer, createVirtualMouseStudio } from \"@zouloux/virtual-mouse\"\n// ...\n```\n\n---\n## Test it\n\n##### Clone\n- `git clone git@github.com:zouloux/virtual-mouse.git`\n- `cd virtual-mouse`\n\n##### Build\n- `npm run build`\n \n##### Start demo on port 8080\n- `npm run demo`\n\n---\n## Next features\n\n##### Move cursor to an element, centered into it\n- `mouse.toElement( element:Element )`\n- `mouse.toSelector( selector:string )`\n\n##### Type on keyboard\n\n```\nawait mouse.toElement('input')\nawait mouse.click()\nawait mouse.type(\"Hello world\", 2) // speed\nawait mouse.key(\"enter\")\n```\n\n##### Sounds\n\nSounds in WebAudio\n\n- Move sound\n- Click sound\n- Scroll sound\n- Type sound\n- Key sound\n\n##### Studio\n\nCreate a tool to register clicks and moves and create code.\nIt will have to smooth everything out.\nMaybe by hitting a specific key binding to create a new record.\n\n##### Dependencies\n\nRemove `gsap` as a dependency and make it a unique file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzouloux%2Fvirtual-mouse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzouloux%2Fvirtual-mouse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzouloux%2Fvirtual-mouse/lists"}