[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"url-settings":80,"blog-\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api":589,"blog-author-\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api":1300},{"id":4,"extension":5,"footer":6,"header":66,"meta":77,"stem":78,"__hash__":79},"navigation\u002Fdata\u002Fshared\u002Fnavigation.yml","yml",{"brand":7,"columns":10,"legal":56},{"name":8,"tagline":9},"Pieces","The memory layer for modern work.",[11,26,41],{"title":12,"links":13},"Product",[14,17,21,24],{"label":15,"href":16},"Pieces Desktop","\u002Fdownloads",{"label":18,"href":19,"external":20},"Pieces MCP","url:docs.mcp.overview",true,{"label":22,"href":23,"external":20},"Pieces APIs","url:docs.api",{"label":25,"href":16},"Downloads",{"title":27,"links":28},"Resources",[29,32,35,38],{"label":30,"href":31,"external":20},"Documentation","url:docs.home",{"label":33,"href":34},"Blog","\u002Fblog",{"label":36,"href":37},"Changelog","\u002Fchangelog",{"label":39,"href":40,"external":20},"GitHub","url:github.org",{"title":42,"links":43},"Company",[44,47,50,53],{"label":45,"href":46},"About","\u002Fabout",{"label":48,"href":49},"Enterprise","\u002Fenterprise",{"label":51,"href":52,"external":20},"Discord","url:social.discord",{"label":54,"href":55,"external":20},"X \u002F Twitter","url:social.x",[57,60,63],{"label":58,"href":59,"external":20},"Privacy Policy","url:legal.privacyPolicy",{"label":61,"href":62,"external":20},"Refund Policy","url:legal.refundPolicy",{"label":64,"href":65,"external":20},"Terms of Service","url:legal.terms",{"links":67,"signIn":68,"contact":71,"cta":74},[],{"label":69,"href":70},"Sign in","url:portal.home",{"label":72,"href":73},"Contact sales","url:site.contact",{"label":75,"href":76},"Download","url:routes.downloads",{},"data\u002Fshared\u002Fnavigation","Ia8tCWWqcGvuaIro8jwZ3HH-MwI66yqJpWshASJdYQ0",{"id":81,"extension":5,"links":82,"meta":586,"stem":587,"__hash__":588},"urlSettings\u002Fdata\u002Fshared\u002Furls.yml",[83,87,91,95,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203,207,211,215,219,223,227,231,235,238,242,246,249,253,257,261,265,269,273,277,281,285,289,293,297,301,305,309,313,317,321,325,329,333,337,341,345,349,353,357,361,365,369,373,377,381,385,389,393,396,400,404,408,412,416,420,423,426,429,432,436,440,444,448,452,456,460,464,468,472,476,480,484,488,492,495,499,503,507,511,515,519,523,527,531,534,538,542,546,550,553,557,561,565,568,571,575,579,582],{"key":84,"label":85,"href":86},"downloads.desktop","Desktop download page","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdownload",{"key":88,"label":89,"href":90},"downloads.macOS.dmgArm64","macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg-arm64\u002Fdownload",{"key":92,"label":93,"href":94},"downloads.macOS.dmgIntel","macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg\u002Fdownload",{"key":96,"label":97,"href":98},"downloads.macOS.pkg","macOS PKG","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg\u002Fdownload",{"key":100,"label":101,"href":102},"downloads.windows.appinstaller","Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fpieces_for_x.appinstaller",{"key":104,"label":105,"href":106},"downloads.windows.exe","Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-exe\u002Fdownload",{"key":108,"label":109,"href":110},"downloads.windows.suiteManager","Windows Suite Manager","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_suite_windows\u002Fappinstaller\u002Fdownload",{"key":112,"label":113,"href":114},"downloads.linux.flatpakRepo","Linux Flatpak repository","https:\u002F\u002Fbuilds.pieces.app\u002Fpieces-flatpak-repo\u002Fpieces-flatpak.flatpakrepo",{"key":116,"label":117,"href":118},"downloads.linux.snapDesktop","Linux Snap Desktop","https:\u002F\u002Fsnapcraft.io\u002Fpieces-for-developers",{"key":120,"label":121,"href":122},"downloads.linux.snapPiecesOS","Linux Snap PiecesOS","https:\u002F\u002Fsnapcraft.io\u002Fpieces-os",{"key":124,"label":125,"href":126},"downloads.piecesOS.macOS.dmgArm64","PiecesOS macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg-arm64\u002Fdownload",{"key":128,"label":129,"href":130},"downloads.piecesOS.macOS.dmgIntel","PiecesOS macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg\u002Fdownload",{"key":132,"label":133,"href":134},"downloads.piecesOS.windows.appinstaller","PiecesOS Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fos_server.appinstaller",{"key":136,"label":137,"href":138},"downloads.piecesOS.windows.exe","PiecesOS Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-exe\u002Fdownload",{"key":140,"label":141,"href":142},"downloads.guides.macOS","macOS installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fmacos-installation-guide",{"key":144,"label":145,"href":146},"downloads.guides.windows","Windows installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fwindows-installation-guide",{"key":148,"label":149,"href":150},"downloads.guides.linux","Linux installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide",{"key":152,"label":153,"href":154},"downloads.guides.piecesOS","PiecesOS manual installation","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fmanual-installation",{"key":156,"label":157,"href":158},"extensions.chrome","Chrome extension","https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fpieces-save-code-snippets\u002Figbgibhbfonhmjlechmeefimncpekepm",{"key":160,"label":161,"href":162},"extensions.firefox","Firefox add-on","https:\u002F\u002Faddons.mozilla.org\u002Fen-US\u002Ffirefox\u002Faddon\u002Fpieces-save-code-from-the-web\u002F",{"key":164,"label":165,"href":166},"extensions.edge","Edge add-on","https:\u002F\u002Fmicrosoftedge.microsoft.com\u002Faddons\u002Fdetail\u002Fpieces-save-code-snippet\u002Fhglfimcdgonaeeobjckfdabcldfidmim",{"key":168,"label":169,"href":170},"extensions.vscode","VS Code extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.pieces-vscode",{"key":172,"label":173,"href":174},"extensions.visualStudio","Visual Studio extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.PiecesVisualStudio",{"key":176,"label":177,"href":178},"extensions.jetbrains","JetBrains plugin","https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F17328-pieces--save-search-share--reuse-code-snippets",{"key":180,"label":181,"href":182},"extensions.obsidian","Obsidian plugin","https:\u002F\u002Fobsidian.md\u002Fplugins?id=pieces-for-developers",{"key":184,"label":185,"href":186},"extensions.sublime","Sublime package","https:\u002F\u002Fpackagecontrol.io\u002Fpackages\u002FPieces",{"key":188,"label":189,"href":190},"extensions.neovim","Neovim plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neo_vim",{"key":192,"label":193,"href":194},"extensions.jupyterlab","JupyterLab plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fjupyterlab-pieces",{"key":196,"label":197,"href":198},"extensions.cli","Pieces CLI","https:\u002F\u002Fpypi.org\u002Fproject\u002Fpieces-cli\u002F",{"key":200,"label":201,"href":202},"docs.home","Documentation home","https:\u002F\u002Fdocs.pieces.app",{"key":204,"label":205,"href":206},"docs.getStarted","Get started docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces",{"key":208,"label":209,"href":210},"docs.api","API docs","https:\u002F\u002Fdocs.pieces.app\u002Fapi",{"key":212,"label":213,"href":214},"docs.desktop.overview","Desktop overview","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop",{"key":216,"label":217,"href":218},"docs.desktop.onboarding","Desktop onboarding","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fonboarding",{"key":220,"label":221,"href":222},"docs.desktop.timeline","Desktop timeline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Ftimeline",{"key":224,"label":225,"href":226},"docs.desktop.summaries","Desktop summaries docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fsingle-click-summaries",{"key":228,"label":229,"href":230},"docs.desktop.search","Desktop conversational search docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconversational-search",{"key":232,"label":233,"href":234},"docs.desktop.drive","Desktop drive docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdrive",{"key":236,"label":237,"href":86},"docs.desktop.download","Desktop download docs",{"key":239,"label":240,"href":241},"docs.piecesOS.overview","PiecesOS overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies",{"key":243,"label":244,"href":245},"docs.piecesOS.details","PiecesOS details docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os",{"key":247,"label":248,"href":154},"docs.piecesOS.install","PiecesOS install docs",{"key":250,"label":251,"href":252},"docs.piecesOS.quickMenu","PiecesOS quick menu docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fquick-menu",{"key":254,"label":255,"href":256},"docs.piecesOS.storage","On-device storage docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fon-device-storage",{"key":258,"label":259,"href":260},"docs.piecesOS.troubleshooting","PiecesOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Ftroubleshooting",{"key":262,"label":263,"href":264},"docs.mcp.overview","MCP overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp",{"key":266,"label":267,"href":268},"docs.mcp.cursor","MCP Cursor docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcursor",{"key":270,"label":271,"href":272},"docs.mcp.vscode","MCP VS Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fvs-code",{"key":274,"label":275,"href":276},"docs.mcp.claudeDesktop","MCP Claude Desktop docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-desktop",{"key":278,"label":279,"href":280},"docs.mcp.claudeCode","MCP Claude Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-code",{"key":282,"label":283,"href":284},"docs.mcp.claudeCowork","MCP Claude Cowork docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-cowork",{"key":286,"label":287,"href":288},"docs.mcp.githubCopilot","MCP GitHub Copilot docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgithub-copilot",{"key":290,"label":291,"href":292},"docs.mcp.goose","MCP Goose docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoose",{"key":294,"label":295,"href":296},"docs.mcp.windsurf","MCP Windsurf docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fwindsurf",{"key":298,"label":299,"href":300},"docs.mcp.zed","MCP Zed docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fzed",{"key":302,"label":303,"href":304},"docs.mcp.jetbrains","MCP JetBrains docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fjetbrains-ides",{"key":306,"label":307,"href":308},"docs.mcp.continueDev","MCP Continue docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcontinue-dev",{"key":310,"label":311,"href":312},"docs.mcp.cline","MCP Cline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcline",{"key":314,"label":315,"href":316},"docs.mcp.raycast","MCP Raycast docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fraycast",{"key":318,"label":319,"href":320},"docs.mcp.rovoDevCli","MCP Rovo Dev CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Frovo-dev-cli",{"key":322,"label":323,"href":324},"docs.mcp.openaiCodexCli","MCP OpenAI Codex CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenai-codex-cli",{"key":326,"label":327,"href":328},"docs.mcp.googleGeminiCli","MCP Google Gemini CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoogle-gemini-cli",{"key":330,"label":331,"href":332},"docs.mcp.amazonQ","MCP Amazon Q docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Famazon-q-developer",{"key":334,"label":335,"href":336},"docs.mcp.chatgptDev","MCP ChatGPT Developer Mode docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fchatgpt-developer-mode",{"key":338,"label":339,"href":340},"docs.mcp.openclaw","MCP OpenClaw docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenclaw",{"key":342,"label":343,"href":344},"docs.mcp.mcpRemote","MCP Remote docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fmcp-remote",{"key":346,"label":347,"href":348},"docs.mcp.ngrok","MCP ngrok docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fngrok-setup",{"key":350,"label":351,"href":352},"docs.troubleshooting.macOS","macOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fmacos",{"key":354,"label":355,"href":356},"docs.troubleshooting.windows","Windows troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fwindows",{"key":358,"label":359,"href":360},"docs.troubleshooting.linux","Linux troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Flinux",{"key":362,"label":363,"href":364},"docs.privacy","Privacy and security docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fprivacy-security-your-data",{"key":366,"label":367,"href":368},"docs.support","Support docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fsupport",{"key":370,"label":371,"href":372},"portal.home","Pieces portal","https:\u002F\u002Fportal.pieces.app",{"key":374,"label":375,"href":376},"site.home","Website home","https:\u002F\u002Fpieces.app",{"key":378,"label":379,"href":380},"site.about","About page","https:\u002F\u002Fpieces.app\u002Fabout",{"key":382,"label":383,"href":384},"site.features","Features page","https:\u002F\u002Fpieces.app\u002Ffeatures",{"key":386,"label":387,"href":388},"site.plugins","Plugins page","https:\u002F\u002Fpieces.app\u002Fplugins",{"key":390,"label":391,"href":392},"site.contact","Contact page","https:\u002F\u002Fpieces.app\u002Fcontact",{"key":394,"label":36,"href":395},"site.changelog","https:\u002F\u002Fpieces.app\u002Fchangelog",{"key":397,"label":398,"href":399},"site.news","News","https:\u002F\u002Fpieces.app\u002Fnews",{"key":401,"label":402,"href":403},"site.events","Community events","https:\u002F\u002Fpieces.app\u002Fcommunity\u002Fevents",{"key":405,"label":406,"href":407},"site.userStories","User stories","https:\u002F\u002Fpieces.app\u002Fuser-stories",{"key":409,"label":410,"href":411},"site.academy","Academy","https:\u002F\u002Fpieces.app\u002Flearn\u002Facademy",{"key":413,"label":414,"href":415},"site.support","Website support","https:\u002F\u002Fpieces.app\u002Fsupport",{"key":417,"label":418,"href":419},"site.standup","Standup","https:\u002F\u002Fpieces.app\u002Fstandup",{"key":421,"label":33,"href":422},"site.blog","https:\u002F\u002Fcode.pieces.app\u002Fblog",{"key":424,"label":51,"href":425},"social.discord","https:\u002F\u002Fdiscord.gg\u002Fgetpieces",{"key":427,"label":54,"href":428},"social.x","https:\u002F\u002Fx.com\u002Fgetpieces",{"key":430,"label":431,"href":428},"social.twitter","Twitter",{"key":433,"label":434,"href":435},"social.instagram","Instagram","https:\u002F\u002Fwww.instagram.com\u002Fgetpieces\u002F",{"key":437,"label":438,"href":439},"social.tiktok","TikTok","https:\u002F\u002Fwww.tiktok.com\u002F@getpieces",{"key":441,"label":442,"href":443},"social.linkedin","LinkedIn","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgetpieces\u002F",{"key":445,"label":446,"href":447},"social.youtube","YouTube","https:\u002F\u002Fyoutube.com\u002F@getpieces",{"key":449,"label":450,"href":451},"github.org","GitHub organization","https:\u002F\u002Fgithub.com\u002Fpieces-app",{"key":453,"label":454,"href":455},"github.support","GitHub support","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport",{"key":457,"label":458,"href":459},"github.issues","GitHub issues","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fissues",{"key":461,"label":462,"href":463},"github.discussions","GitHub discussions","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fdiscussions",{"key":465,"label":466,"href":467},"github.documentation","GitHub documentation","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fdocumentation",{"key":469,"label":470,"href":471},"github.opensource","GitHub open source","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fopensource",{"key":473,"label":474,"href":475},"github.sdks.python","Python SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-python",{"key":477,"label":478,"href":479},"github.sdks.typescript","TypeScript SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-typescript",{"key":481,"label":482,"href":483},"github.sdks.dart","Dart SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-dart",{"key":485,"label":486,"href":487},"github.sdks.kotlin","Kotlin SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-kotlin",{"key":489,"label":490,"href":491},"github.plugins.obsidian","Obsidian plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fobsidian-pieces",{"key":493,"label":494,"href":194},"github.plugins.jupyterlab","JupyterLab plugin repository",{"key":496,"label":497,"href":498},"github.plugins.sublime","Sublime plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_sublime",{"key":500,"label":501,"href":502},"github.plugins.neovim","Neovim plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neovim",{"key":504,"label":505,"href":506},"github.cliAgent","CLI agent repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fcli-agent",{"key":508,"label":509,"href":510},"github.mcpDart","MCP Dart repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fmcp_dart",{"key":512,"label":513,"href":514},"github.awesomePieces","Awesome Pieces repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fawesome-pieces",{"key":516,"label":517,"href":518},"legal.privacyPolicy","Privacy policy","https:\u002F\u002Fpieces.app\u002Flegal\u002Fprivacy-policy",{"key":520,"label":521,"href":522},"legal.refundPolicy","Refund policy","https:\u002F\u002Fpieces.app\u002Flegal\u002Frefund-policy",{"key":524,"label":525,"href":526},"legal.terms","Terms","https:\u002F\u002Fpieces.app\u002Flegal\u002Fterms",{"key":528,"label":529,"href":530},"legal.security","Legal security","https:\u002F\u002Fpieces.app\u002Flegal\u002Fsecurity",{"key":532,"label":533,"href":447},"videos.youtubeChannel","YouTube channel",{"key":535,"label":536,"href":537},"videos.gettingStartedDesktop","Getting started desktop video","https:\u002F\u002Fyoutu.be\u002FdUr1lRM_TYk",{"key":539,"label":540,"href":541},"videos.snippetDiscovery","Snippet discovery video","https:\u002F\u002Fyoutu.be\u002FG6vb1USw-30",{"key":543,"label":544,"href":545},"sales.bookACall","Book a sales call","https:\u002F\u002Fcalendar.app.google\u002FWVUDtUfNy5Vst3sH7",{"key":547,"label":548,"href":549},"sales.enterprise","Enterprise form","https:\u002F\u002Fgetpieces.typeform.com\u002Fto\u002FaVQFTvpE",{"key":551,"label":552,"href":463},"sales.feedback","Feedback discussions",{"key":554,"label":555,"href":556},"sales.earlyAccess","Early access form","https:\u002F\u002Fgetpieces.typeform.com\u002Fearlyaccess",{"key":558,"label":559,"href":560},"sales.supportEmail","Support email","mailto:support@pieces.app",{"key":562,"label":563,"href":564},"routes.home","Home route","\u002F",{"key":566,"label":567,"href":46},"routes.about","About route",{"key":569,"label":570,"href":16},"routes.downloads","Downloads route",{"key":572,"label":573,"href":574},"routes.pricing","Pricing route","\u002Fpricing",{"key":576,"label":577,"href":578},"routes.security","Security route","\u002Fsecurity",{"key":580,"label":581,"href":49},"routes.enterprise","Enterprise route",{"key":583,"label":584,"href":585},"routes.thankYou","Thank you \u002F download route","\u002Fthank-you",{},"data\u002Fshared\u002Furls","P27xKEauu8D-8sfyr0wR4giF0teFSaCuAQ8kgcICQdI",{"id":590,"title":591,"author":592,"authorPhoto":593,"authorPhotoAlt":594,"authorSlug":595,"body":596,"buttonText":1287,"buttonUrl":1287,"category":1288,"date":1289,"description":1290,"draft":1291,"editorsPick":1291,"extension":1292,"featured":1291,"image":1293,"imageAlt":1294,"meta":1295,"navigation":20,"ogImage":1287,"ogImageAlt":1287,"path":1296,"seo":1297,"stem":1298,"tags":1287,"__hash__":1299},"blog\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api.md","Drawing interactive shapes with the Canvas API in a React application","The Pieces Team","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fannouncing-the-pieces-visual-studio-extension\u002Fauthor.png","The Pieces logo.","the-pieces-team",{"type":597,"value":598,"toc":1275},"minimark",[599,603,606,609,615,618,659,664,690,696,706,713,720,726,773,776,780,783,789,792,795,800,812,818,833,853,856,862,868,890,894,914,921,927,930,936,939,945,951,954,972,977,981,984,987,995,998,1004,1007,1013,1020,1026,1079,1082,1089,1095,1098,1161,1165,1168,1185,1191,1197,1224,1227,1233,1237,1240,1269],[600,601,602],"p",{},"In this blog post, we will build a React application through which we can draw interactive shapes with the help of the Canvas API.",[600,604,605],{},"We’ll also learn about Canvas HTML elements, the Canvas API, and drawing different shapes with mouse interactions.",[600,607,608],{},"Without further ado, let’s get started!",[600,610,611],{},[612,613,614],"strong",{},"Prerequisites",[600,616,617],{},"To follow along with this blog post, I would highly recommend that you review the following topics:",[619,620,621,638,645,652],"ul",{},[622,623,624,631,632,637],"li",{},[625,626,630],"a",{"href":627,"rel":628},"https:\u002F\u002Freactjs.org\u002Ftutorial\u002Ftutorial.html",[629],"nofollow","Basics of React"," and ",[625,633,636],{"href":634,"rel":635},"https:\u002F\u002Freactjs.org\u002Fdocs\u002Fhooks-reference.html#useeffect",[629],"useEffect",".",[622,639,640],{},[625,641,644],{"href":642,"rel":643},"https:\u002F\u002Freactjs.org\u002Fdocs\u002Fglossary.html#refs",[629],"React refs",[622,646,647],{},[625,648,651],{"href":649,"rel":650},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FLearn\u002FGetting_started_with_the_web\u002FJavaScript_basics",[629],"Basic JavaScript",[622,653,654],{},[625,655,658],{"href":656,"rel":657},"https:\u002F\u002Fwww.typescriptlang.org\u002Fdocs\u002Fhandbook\u002F2\u002Fbasic-types.html",[629],"Basics of TypeScript",[660,661,663],"h2",{"id":662},"the-canvas-html-element-and-the-canvas-api","The Canvas HTML Element and the Canvas API",[600,665,666,670,671,676,677,679,680,683,684,689],{},[667,668,669],"code",{},"canvas"," is an ",[625,672,675],{"href":673,"rel":674},"https:\u002F\u002Fpieces.app\u002Fblog\u002Fintroduction-to-html",[629],"HTML element"," that helps you to draw shapes. You can draw shapes inside a canvas element using the Canvas API provided by your browser. This element acts as a container in which you can draw different shapes. To draw inside a ",[667,678,669],{}," element, a context for the element is required. A context is an entity that we can draw shapes on. We can use ",[667,681,682],{},"getContext"," to get the ",[625,685,688],{"href":686,"rel":687},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FCanvasRenderingContext2D",[629],"CanvasRenderingContext2D"," that returns the 2-D context.",[600,691,692,693,695],{},"Let’s look at a simple React ",[667,694,669],{}," component that draws a rectangle inside an element.",[697,698,703],"pre",{"className":699,"code":701,"language":702},[700],"language-text","import { useEffect, useRef } from \"react\";\nexport const Rectangle = () => {\n const canvasRef = useRef(null);\n  useEffect(() => {\n if (canvasRef.current) {\n const ctx = canvasRef.current.getContext(\"2d\");\n      ctx?.strokeRect(200, 200, 40, 50);\n    }\n  }, []);\n return (\n \n      ref={canvasRef}\n      width=\"400\"\n      height=\"350\"\n      style={{ border: \"2px solid black\" }}\n    \u002F>\n  );\n};\n","text",[667,704,701],{"__ignoreMap":705},"",[600,707,708,709,712],{},"Here is what the ",[667,710,711],{},"Rectangle"," component will render:",[600,714,715],{},[716,717],"img",{"alt":718,"src":719},"A rendered rectangle drawn with the Canvas API.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api\u002Fimg-001.png",[600,721,722,723,725],{},"Let’s take a peek into the above ",[667,724,711],{}," component:",[619,727,728,744,757],{},[622,729,730,731,733,734,736,737,631,740,743],{},"The ",[667,732,711],{}," component returns a ",[667,735,669],{}," element whose width and height are set to ",[667,738,739],{},"400px",[667,741,742],{},"300px",", respectively.",[622,745,746,747,750,751,753,754,756],{},"We need to make sure that we pass a ",[667,748,749],{},"ref"," to the ",[667,752,669],{}," element. This will help us to access the different properties of the ",[667,755,669],{}," element.",[622,758,759,760,762,763,765,766,769,770,637],{},"Lastly, we want to draw inside the ",[667,761,669],{}," element once the component is rendered. To do so, we’ll write a piece of code that gets the ",[667,764,669],{}," element’s 2-D context using ",[667,767,768],{},"getContext(\"2d\")"," and uses the above context to draw a rectangle with a function",[667,771,772],{},"strokeRect",[600,774,775],{},"Now, with this understanding, let’s dive into drawing some shapes.",[660,777,779],{"id":778},"drawing-a-rectangle-on-the-canvas","Drawing a Rectangle on the Canvas",[600,781,782],{},"In this section, we’re going to talk about drawing a rectangle upon clicking the canvas, as in the gif below:",[600,784,785],{},[716,786],{"alt":787,"src":788},"Gif showing a new rectangle being created with every click.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api\u002Fimg-002.gif",[600,790,791],{},"If we think about building an app like this in React or in JS, then we need to consider two important points: First, how we get the cursor’s x and y coordinates for drawing onto the canvas, and second, how we’re going to draw on the mouse click.",[600,793,794],{},"Let’s investigate these points further:",[796,797,799],"h3",{"id":798},"how-would-we-get-the-cursors-x-and-y-coordinates-so-that-we-can-draw-it-onto-the-canvas","How would we get the cursor’s x and y coordinates so that we can draw it onto the canvas?",[619,801,802,809],{},[622,803,804,805,808],{},"In this scenario, we can simply add an event listener on the ",[667,806,807],{},"mousemove"," event.",[622,810,811],{},"The handler we will attach will simply set the x and y coordinates to the values that are relative to the edges of the given element, like this:",[697,813,816],{"className":814,"code":815,"language":702},[700],"const handleCursorMovement = (event) => {\n let rect = event.target.getBoundingClientRect();\n return {\n      x: event.clientX - rect.left,\n      y: event.clientY - rect.top\n    };\n  };\n",[667,817,815],{"__ignoreMap":705},[619,819,820,826],{},[622,821,730,822,825],{},[667,823,824],{},"x-coordinate"," is the difference between the viewport's x-coordinate and the distance of the current object from the left edge of the viewport. This will give us the x-coordinate inside the rectangle. In this case, the current object is what we’re hovering over.",[622,827,828,829,832],{},"Similarly, we have ",[667,830,831],{},"y"," where it is the difference between the viewport’s y-coordinate and the distance of the current object from the top edge of the viewport. In this case, the current object is what we’re hovering over.",[600,834,835,836,631,839,842,843,631,848,852],{},"You can read more about ",[667,837,838],{},"clientX",[667,840,841],{},"getBoundingClientRect"," ",[625,844,847],{"href":845,"rel":846},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FMouseEvent\u002FclientX",[629],"here",[625,849,847],{"href":850,"rel":851},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FElement\u002FgetBoundingClientRect",[629],". This is a really useful scenario, and it will be used in most of our examples.",[600,854,855],{},"So, let’s wrap this logic into a hook so that we can use it in any component we want.",[600,857,858,859],{},"Copy-paste the below code into a file named ",[667,860,861],{},"useMousePosition.tsx",[697,863,866],{"className":864,"code":865,"language":702},[700],"import { useEffect, useState } from \"react\";\nconst useMousePosition = (\n  global: boolean = false\n): [{ x: number; y: number }, (event: MouseEvent) => void] => {\n const [mouseCoords, setMouseCoords] = useState\u003C{\n    x: number;\n    y: number;\n  }>({\n    x: 0,\n    y: 0\n  });\n const handleCursorMovement = (event: MouseEvent): void => {\n \u002F\u002F@ts-ignore\n let rect = event.target.getBoundingClientRect();\n    setMouseCoords({\n      x: event.clientX - rect.left,\n      y: event.clientY - rect.top\n    });\n  };\n  useEffect(() => {\n if (global) {\n window.addEventListener(\"mousemove\", handleCursorMovement);\n return () => {\n window.removeEventListener(\"mousemove\", handleCursorMovement);\n      };\n    }\n  }, [global]);\n return [mouseCoords, handleCursorMovement];\n};\nexport default useMousePosition;\n",[667,867,865],{"__ignoreMap":705},[619,869,870,873,883],{},[622,871,872],{},"This hook returns an array that consists of two things: the current cursor coordinates, and a function that handles the setting of these coordinates.",[622,874,875,876,879,880,882],{},"This function also accepts a parameter called “global.” If set to ",[667,877,878],{},"true",", this parameter makes sure that a listener is attached to the ",[667,881,807],{}," event over the entire window.",[622,884,885,886,889],{},"The default value of the ",[667,887,888],{},"global"," parameter is set to false.",[796,891,893],{"id":892},"how-are-we-going-to-draw-on-the-mouse-click","How are we going to draw on the mouse click?",[619,895,896,904],{},[622,897,898,899,901,902,637],{},"In this scenario, we’re going to draw inside the ",[667,900,669],{}," whenever the user clicks on the ",[667,903,669],{},[622,905,906,907,909,910,913],{},"To do this, we are going to bind the ",[667,908,669],{}," element with a function that executes itself on a click. It’s as simple as adding an ",[667,911,912],{},"onClick"," attribute to it.",[600,915,916,917,920],{},"To wrap up this scenario, place the following code inside a file named ",[667,918,919],{},"Square.tsx",":",[697,922,925],{"className":923,"code":924,"language":702},[700],"import { useRef } from \"react\";\nimport useMousePosition from \".\u002Fhooks\u002FuseMousePosition\";\nexport default function Sqaure() {\n const canvasRef = useRef(null);\n const [coords, handleCoords] = useMousePosition(true);\n return (\n \u003C>\nSqaure on click\n \n        ref={canvasRef}\n        width=\"400\"\n        height=\"350\"\n        style={{ border: \"2px solid black\" }}\n        onClick={(e) => {\n          handleCoords((e as unknown) as MouseEvent);\n          if (canvasRef.current) {\n            const ctx = canvasRef.current.getContext(\"2d\");\n            ctx?.strokeRect(coords.x, coords.y, 40, 50);\n          }\n        }}\n      >\n \n        onClick={() => {\n          if (canvasRef.current) {\n            const ctx = canvasRef.current.getContext(\"2d\");\n            ctx?.clearRect(0, 0, 400, 350);\n          }\n        }}\n      >\n        CLEAR\n \n  );\n}\n",[667,926,924],{"__ignoreMap":705},[600,928,929],{},"The output will look something like below:",[600,931,932],{},[716,933],{"alt":934,"src":935},"Several rectangles on a canvas.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api\u002Fimg-003.jpeg",[600,937,938],{},"In this, we also make sure to provide a “clear” button so that the Canvas can be cleared.",[600,940,941,942,944],{},"As you can see from the above code, we have attached a function on the ",[667,943,912],{}," attribute of the canvas:",[697,946,949],{"className":947,"code":948,"language":702},[700],"        ref={canvasRef}\n        width=\"400\"\n        height=\"350\"\n        style={{ border: \"2px solid black\" }}\n        onClick={(e) => {\n          handleCoords((e as unknown) as MouseEvent);\n if (canvasRef.current) {\n const ctx = canvasRef.current.getContext(\"2d\");\n            ctx?.strokeRect(coords.x, coords.y, 40, 50);\n          }\n        }}\n      >\n",[667,950,948],{"__ignoreMap":705},[600,952,953],{},"This function will do the following things:",[619,955,956,963,966],{},[622,957,958,959,962],{},"It will execute the ",[667,960,961],{},"handleCoords"," function that sets the current mouse position coordinates.",[622,964,965],{},"Then it gets the current canvas’s 2-D context.",[622,967,968,969,971],{},"Finally, it draws a rectangle using the ",[667,970,772],{}," function via passing the x and y coordinates of the mouse pointer.",[600,973,974,975,637],{},"Let’s go ahead and look at what else we can draw with React ",[667,976,669],{},[660,978,980],{"id":979},"animate-canvas-objects","Animate Canvas Objects",[600,982,983],{},"In this section of the article, we’re going to talk about the interesting stuff: the animation of the objects present inside the canvas.",[600,985,986],{},"Things that we are going to do in this section are:",[619,988,989,992],{},[622,990,991],{},"Draw the shape on the canvas",[622,993,994],{},"Move the shape on the canvas at a regular interval to get the animation effect",[600,996,997],{},"The animation that we are building here is a ball moving continuously in a horizontal direction. Here is a glimpse of it:",[600,999,1000],{},[716,1001],{"alt":1002,"src":1003},"A ball moving across a rectangle.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api\u002Fimg-004.gif",[600,1005,1006],{},"To draw a circle, we can use the below code:",[697,1008,1011],{"className":1009,"code":1010,"language":702},[700],"export const drawCircle = (\n  ctx: CanvasRenderingContext2D,\n  circleDims: {\n    radius: number;\n    lineWidth: number;\n    strokeStyle: string;\n    colorFill?: string;\n    startX: number;\n    startY: number;\n  },\n  rectDims: { w: number; h: number } = { w: 400, h: 3500 }\n) => {\n const {\n    radius,\n    strokeStyle,\n    startX,\n    startY,\n    lineWidth,\n    colorFill\n  } = circleDims;\n  ctx?.clearRect(0, 0, rectDims.w, rectDims.h);\n  ctx.lineWidth = lineWidth;\n  ctx.strokeStyle = strokeStyle;\n  ctx?.beginPath();\n  ctx?.arc(startX, startY, radius, 0, Math.PI * 2, true);\n  ctx?.stroke();\n if (colorFill) {\n    ctx.fillStyle = colorFill;\n    ctx.fill();\n  }\n};\n",[667,1012,1010],{"__ignoreMap":705},[600,1014,1015,1016,1019],{},"I have wrapped the logic of creating a circle in the function ",[667,1017,1018],{},"drawCircle",". The logic of it is below:",[697,1021,1024],{"className":1022,"code":1023,"language":702},[700],"ctx?.clearRect(0, 0, rectDims.w, rectDims.h);\n  ctx.lineWidth = lineWidth;\n  ctx.strokeStyle = strokeStyle;\n  ctx?.beginPath();\n  ctx?.arc(startX, startY, radius, 0, Math.PI * 2, true);\n  ctx?.stroke();\n if (colorFill) {\n    ctx.fillStyle = colorFill;\n    ctx.fill();\n  }\n",[667,1025,1023],{"__ignoreMap":705},[619,1027,1028,1035,1042,1049,1060,1069],{},[622,1029,1030,1031,1034],{},"First, we clear the canvas using the",[667,1032,1033],{},"clearRect"," function.",[622,1036,1037,1038,1041],{},"Next, we set the ",[667,1039,1040],{},"lineWidth"," of the circumference of the circle\u002Fball.",[622,1043,1044,1045,1048],{},"We also set the ",[667,1046,1047],{},"strokeStyle"," that sets the color of the border.",[622,1050,1051,1052,1055,1056,1059],{},"Then, we start to create a new path using the",[667,1053,1054],{},"beginPath"," function. We make use of the",[667,1057,1058],{},"arc"," method that helps draw circular arcs with the given x-coordinate, y-coordinate, radius, start and end angle.",[622,1061,1062,1063,1065,1066,1034],{},"Once the ",[667,1064,1058],{}," is added as a sub-path, we can draw the arc onto the canvas with the given stroke style using the",[667,1067,1068],{},"stroke",[622,1070,1071,1072,1075,1076,637],{},"Finally, if the ",[667,1073,1074],{},"colorFill"," is available, then it will fill the path with the available ",[667,1077,1078],{},"fillStyle",[600,1080,1081],{},"Next, we will make use of this function to create a component that animates the shape.",[600,1083,1084,1085,1088],{},"Create a file named ",[667,1086,1087],{},"Circle.tsx"," file and place the below code within:",[697,1090,1093],{"className":1091,"code":1092,"language":702},[700],"import { useEffect, useRef, useState } from \"react\";\nimport { drawCircle } from \".\u002Futilities\";\nconst Circle = () => {\n const canvasRef = useRef(null); const [startX, setStartX] = useState(0);\n  useEffect(() => {\n if (canvasRef?.current) {\n const ctx = canvasRef.current.getContext(\"2d\");\n      requestAnimationFrame(function ball() {\n \u002F\u002F@ts-ignore\n        drawCircle(ctx, {\n          radius: 50,\n          lineWidth: 3,\n          strokeStyle: \"#4F7CAC\",\n          colorFill: \"#4F7CAC\",\n          startY: 150,\n          startX\n        });\n        setStartX((prevStartX) => prevStartX + 5);\n        ctx?.stroke();\n if (startX > 400) {\n          setStartX(0);\n        }\n      });\n    }\n  }, [startX]);\n return (\n    \u003C>\nMoving Circle\n      \n        ref={canvasRef}\n        width=\"400\"\n        height=\"350\"\n        style={{ border: \"2px solid black\" }}\n      \u002F>\n    \n  );\n};\nexport default Circle;\n",[667,1094,1092],{"__ignoreMap":705},[600,1096,1097],{},"Let’s analyze this code a bit:",[619,1099,1100,1112,1122,1134,1145,1155],{},[622,1101,730,1102,733,1105,1107,1108,1111],{},[667,1103,1104],{},"Circle",[667,1106,669],{}," element. This is similar to the ",[667,1109,1110],{},"Square"," component that we saw in the earlier section.",[622,1113,1114,1115,1118,1119,1121],{},"The aim of this animation is to move the circle continuously in the horizontal direction. So, in this case, we need to make sure we change the x-coordinate. For this, we created a new state variable called ",[667,1116,1117],{},"startX",". We’ll look later at how we update ",[667,1120,1117],{}," continuously.",[622,1123,1124,1125,1127,1128,1130,1131,637],{},"Next, we have a ",[667,1126,636],{},". This ",[667,1129,636],{}," gets the 2-D context of the canvas and then executes the function ",[667,1132,1133],{},"requestAnimationFrame",[622,1135,1136,1138,1139,1142,1143,637],{},[667,1137,1133],{}," is a function that tells the browser it needs to perform an animation. The provided function will be executed before the next repaint. In this case, we are going to pass a function, ",[667,1140,1141],{},"ball",", that draws a new circle on every new x-coordinate with the help of ",[667,1144,1117],{},[622,1146,1147,1148,1151,1152,1154],{},"We make use of the ",[667,1149,1150],{},"setStartX"," update handler that updates the current ",[667,1153,1117],{}," by 5.",[622,1156,1157,1158,1160],{},"Lastly, we check if the ",[667,1159,1117],{}," state is crossing the right edge of the canvas. If yes, then we set the value to 0. This ensures that whenever the ball hits the right edge, it can start the animation again from the left edge.",[660,1162,1164],{"id":1163},"moving-shapes-with-mouse-events","Moving Shapes with Mouse Events",[600,1166,1167],{},"In this section, we’re going to talk about how we can make the shapes inside the canvas interact with mouse events.",[600,1169,1170,1171,1173,1174,1176,1177,1179,1180,1176,1183,756],{},"The process that we are going to follow is very similar to what we had in the ",[667,1172,1110],{}," component. In the square component, we made use of the ",[667,1175,912],{}," attribute of the ",[667,1178,669],{}," element to draw a rectangle on the mouse click event. Similarly, we are going to make use of the ",[667,1181,1182],{},"onMouseMove",[667,1184,669],{},[600,1186,1084,1187,1190],{},[667,1188,1189],{},"TrackingBall.tsx"," and paste the below code:",[697,1192,1195],{"className":1193,"code":1194,"language":702},[700],"import { useEffect, useRef } from \"react\";\nimport useMousePosition from \".\u002Fhooks\u002FuseMousePosition\";\nimport { drawCircle } from \".\u002Futilities\";\nconst MouseBall = () => {\n const canvasRef = useRef(null);\n const [coords, handleCoords] = useMousePosition();\n  useEffect(() => {\n if (canvasRef?.current) {\n const ctx = canvasRef.current.getContext(\"2d\");\n      requestAnimationFrame(function ball() {\n \u002F\u002F@ts-ignore\n        drawCircle(ctx, {\n          radius: 50,\n          lineWidth: 3,\n          strokeStyle: \"#4F7CAC\",\n          colorFill: \"#4F7CAC\",\n          startY: coords.y,\n          startX: coords.x\n        });\n      });\n    }\n  }, [coords.x, coords.y]);\n return (\n \u003C>\nTracking ball\n \n        id=\"canvas2\"\n        ref={canvasRef}\n        width=\"400\"\n        height=\"350\"\n        onMouseMove={(e) => {\n          handleCoords((e as unknown) as MouseEvent);\n        }}\n        style={{ border: \"2px solid black\" }}\n      >\n \n  );\n};\nexport default MouseBall;\n",[667,1196,1194],{"__ignoreMap":705},[600,1198,730,1199,1202,1203,1205,1206,1208,1209,1211,1212,1214,1215,1217,1218,631,1221,637],{},[667,1200,1201],{},"MouseBall"," component is pretty similar to the ",[667,1204,1110],{}," component. The only change is that we are executing the ",[667,1207,961],{}," function inside the ",[667,1210,1182],{}," event. Also, we are making use of the ",[667,1213,1133],{}," function to execute the ",[667,1216,1141],{}," handler on the change of ",[667,1219,1220],{},"coords.x",[667,1222,1223],{},"coords.y",[600,1225,1226],{},"The final output will look like the below:",[600,1228,1229],{},[716,1230],{"alt":1231,"src":1232},"A circle that moves with your cursor.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api\u002Fimg-005.gif",[660,1234,1236],{"id":1235},"summary","Summary",[600,1238,1239],{},"In this article, we talked about the following things:",[619,1241,1242,1248,1251,1254,1257,1260,1266],{},[622,1243,1244,1245,1247],{},"What is a ",[667,1246,669],{}," HTML element?",[622,1249,1250],{},"How is a Canvas API used to draw inside the canvas?",[622,1252,1253],{},"How a Canvas API works with the help of a simple example.",[622,1255,1256],{},"Drawing rectangles and circle shapes with the Canvas API.",[622,1258,1259],{},"Building a custom hook to track the position of the cursor.",[622,1261,1262,1263,1265],{},"How the ",[667,1264,1133],{}," function can be used.",[622,1267,1268],{},"Lastly, we also saw how we can make use of the mouse events to interact with shapes present inside the canvas.",[600,1270,1271,1272,1274],{},"So in this way, we can make use of the ",[667,1273,669],{}," HTML element, Canvas API, and React to draw different interactive shapes.",{"title":705,"searchDepth":1276,"depth":1276,"links":1277},2,[1278,1279,1284,1285,1286],{"id":662,"depth":1276,"text":663},{"id":778,"depth":1276,"text":779,"children":1280},[1281,1283],{"id":798,"depth":1282,"text":799},3,{"id":892,"depth":1282,"text":893},{"id":979,"depth":1276,"text":980},{"id":1163,"depth":1276,"text":1164},{"id":1235,"depth":1276,"text":1236},null,"AI & LLM","2022-10-03T00:00:00.000Z","In this blog post, we'll build a React application through which we can draw interactive shapes with the help of the Canvas API.",false,"md","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api\u002Fhero.jpeg","A rectangular hole in a wooden pyramid.",{},"\u002Fblog\u002Fdraw-interactive-shapes-react-canvas-api",{"title":591,"description":1290},"blog\u002Fdraw-interactive-shapes-react-canvas-api","rYWJwNF_-iQV0TjcUWtuAlPRoxiSTWxc5WLzur3OUcY",{"id":1301,"title":592,"body":1302,"description":705,"draft":1291,"extension":1292,"meta":1306,"navigation":20,"path":1307,"photo":1308,"photoAlt":1287,"seo":1309,"stem":1310,"__hash__":1311},"authors\u002Fauthors\u002Fthe-pieces-team.md",{"type":597,"value":1303,"toc":1304},[],{"title":705,"searchDepth":1276,"depth":1276,"links":1305},[],{},"\u002Fauthors\u002Fthe-pieces-team","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fauthors\u002Fthe-pieces-team.png",{"title":592,"description":705},"authors\u002Fthe-pieces-team","_2O_QA8d8RjXlBp0ck4PWDG6iA74zW1kN0R0gkn2Lls"]