Giter Site home page Giter Site logo

react-animated-cursor's Introduction

React Animated Cursor

A React component that replaces the native cursor with a custom animated jawn. Available options and props allow you to easily craft a unique cursor experience.

Contents

  1. πŸ“Œ Features
  2. 🎯 Quickstart
  3. πŸ€– Commands
  4. 🧬 Options
  5. πŸ•ΉοΈ Usage
  6. 🎨 Cursor Types
  7. πŸ““ Notes
  8. πŸ“… To Dos

πŸ“Œ Features

The custom cursor is comprised of

  • An inner dot (cursorInner)
  • An outer, outlining circle (cursorOuter), with slight opacity based on the dot/primary color
  • A slight trailing animation of the outer outline
  • An inversely scaling effect between the inner and outer cursor parts on click or link hover

Options exist for modifying the color and scaling of the cursor elements (see props/options below). Style props for in the inner and outer cursor allow you to easily create unique cursor types.

Live Demo→


🎯 Quickstart

Install package from npm

npm i react-animated-cursor

Add to you project

Add to a global location, like _app.js

import React from "react";
import AnimatedCursor from "react-animated-cursor"

export default function App() {
  return (
    <div className="App">
      <AnimatedCursor />
    </div>
  );
}

πŸ€– Commands

Install npm i react-animated-cursor
Build: npm run build
Dev: npm run dev
Demo Run: npm run demo:start
Demo Build: npm run demo:build
Demo Clean: npm run demo:clean

Demo

The demo is bundled with Parcel.js and served up at http://localhost:1234/.

Dist

On build, lib populates dist with commonjs, es, umd versions of the component.


πŸ•ΉοΈ Usage

import React from "react";
import AnimatedCursor from "react-animated-cursor"


export default function App() {
  return (
    <div className="App">
      <AnimatedCursor />
    </div>
  );
}

Example Usage - with options

import React from "react";
import AnimatedCursor from "react-animated-cursor"

export default function App() {
  return (
    <div className="App">
    <AnimatedCursor
      innerSize={8}
      outerSize={8}
      color='193, 11, 111'
      outerAlpha={0.2}
      innerScale={0.7}
      outerScale={5}
      clickables={[
        'a',
        'input[type="text"]',
        'input[type="email"]',
        'input[type="number"]',
        'input[type="submit"]',
        'input[type="image"]',
        'label[for]',
        'select',
        'textarea',
        'button',
        '.link'
      ]}
    />
    </div>
  );
}

Example Usage - with simple options and custom config for one class

import React from "react";
import AnimatedCursor from "react-animated-cursor"

export default function App() {
  return (
    <div className="App">
    <AnimatedCursor
      innerSize={8}
      outerSize={8}
      color='193, 11, 111'
      outerAlpha={0.2}
      innerScale={0.7}
      outerScale={5}
      clickables={[
        'a',
        'input[type="text"]',
        'input[type="email"]',
        'input[type="number"]',
        'input[type="submit"]',
        'input[type="image"]',
        'label[for]',
        'select',
        'textarea',
        'button',
        '.link',
        {
          target: '.custom',
          options: {
            innerSize: 12,
            outerSize: 12,
            color: '255, 255, 255',
            outerAlpha: 0.3,
            innerScale: 0.7,
            outerScale: 5
          }
        }
      ]}
    />
    </div>
  );
}

Client Components, Next.js, SSR

In previous versions of the component, integration with Next's SSR environment required using a Dynamic Import. However, as of version 2.10.1, you should be good to go with a simple import.

Relevant updates:

  • Included module directive 'use client' to indicate a client side component.
  • Updated useEventListener hook with window checks.
  • Wrapped the document use in a check.

However, if you do run into any issues, you could try including with Dynamic Import.

Next's Dynamic Import

'use client'; // indicates Client Component

// Import with next's dynamic import
import dynamic from 'next/dynamic';

const AnimatedCursor = dynamic(() => import('react-animated-cursor'), {
    ssr: false,
});

<AnimatedCursor/>

🧬 Options

Option Type Description Default
clickables array Collection of selectors cursor that trigger cursor interaction or object with single target and possibly the rest of the options listed below ['a', 'input[type="text"]', 'input[type="email"]', 'input[type="number"]', 'input[type="submit"]', 'input[type="image"]', 'label[for]', 'select', 'textarea', 'button', '.link']
color string rgb value 220, 90, 90
innerScale number amount dot scales on click or link hover 0.7
innerSize number Size (px) of inner cursor dot 8
innerStyle object provides custom styles / css to inner cursor null
outerAlpha number amount of alpha transparency for outer cursor dot 0.4
outerScale number amount outer dot scales on click or link hover 5
outerSize number Size (px) of outer cursor outline 8
outerStyle object provides custom styles / css to outer cursor null
showSystemCursor boolean Show system/brower cursor false
trailingSpeed number Outer dot's trailing speed 8

🎨 Cursor Types

You can use the innerStyle and outerStyle props to provide custom styles and create a variery of custom cursor types. Additionally, you can pass custom styles and css vars to create unique cursors or update style based on events.

Dynamic Styles

Use CSS variables with innerStyle and outerStyle props to create dynamic styles that you can easily update. For example, perhaps you have a light and dark mode experience and what your cursor to also adapt it's colors.

CSS Vars

html {
  --cursor-color: #333
}

html.dark-mode {
  --cursor-color: #fff
}

Pass CSS Var as Style Props

<AnimatedCursor
  innerSize={8}
  outerSize={35}
  innerScale={1}
  outerScale={1.7}
  outerAlpha={0}
  outerStyle={{
    border: '3px solid var(--cursor-color)'
  }}
  innerStyle={{
    backgroundColor: 'var(--cursor-color)'
  }}
/>

Donut Cursor

A donut style cursor basically resembles a donut. You can easily create on by applying using the outerStyle props to apply an outer border

<AnimatedCursor
  innerSize={8}
  outerSize={35}
  innerScale={1}
  outerScale={2}
  outerAlpha={0}
  hasBlendMode={true}
  innerStyle={{
    backgroundColor: 'var(--cursor-color)'
  }}
  outerStyle={{
    border: '3px solid var(--cursor-color)'
  }}
/>

Donut Demo→


Blend Mode Cursor

You can use CSS mix-blend-mode with the style props to create an intersting cursor effect on hover that inverts the content's color. Works best with white / black cursors.

<AnimatedCursor
  color="#fff"
  innerSize={8}
  outerSize={35}
  innerScale={1}
  outerScale={1.7}
  outerAlpha={0}
  outerStyle={{
    mixBlendMode: 'exclusion'
  }}
/>

Blend Mode Demo→


πŸ““ Notes

Mobile / Touch

helpers/isDevice.js uses UA sniffing to determine if on a common device so we can avoid rendering cursors. Yes... I know, there are other and probably better ways to handle this. Whatevers.


πŸ“… To Dos

  • Either remove on mobile, or provide touch events.

  • Separate click and hover scalings to provide a different scaling when clicking on links/clickables

  • Fix transform blur in Safari, which may mean migrating from scale to a width &height update 4/4/23

  • Make clickables (cursor targets / selectors) a prop

  • Add PropType checks

  • Open cursor styles as props

  • Add ability to maintain system cursor for the squeamish 4/4/23

  • Migrate to TS

  • Allow for different behavior based on the element hovered

  • Options to control cursor transition speed and bezier

  • Solution for impacting state during route changes

  • Add some proper tests


Have fun ya'll.

react-animated-cursor's People

Contributors

201flaviosilva avatar dependabot[bot] avatar dziwuj avatar giorgosxou avatar hasan-aga avatar nico-k3 avatar stephenscaff avatar valerioageno avatar yaseer-13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

react-animated-cursor's Issues

Error: ReferenceError: window is not defined

Hi! I was using your react-animated-cursor library everything went well I was able to put the cursor in the website, however it gives me an error that would be:

  • error node_modules\react-animated-cursor\dist\index.js (43:30) @ useEventListener
  • error ReferenceError: window is not defined
    null
    I am developing this website in Next.js.
    I hope you can help me as soon as possible.
    Thank you.

issues-react-pointer

Element Style Cleanup Incomplete Causes Invisible Cursor

Description

If AnimatedCursor is rendered conditionally, the cursor will stay invisible even when AnimatedCursor is removed from the render tree.

To Produce

import { useState } from "react";
import AnimatedCursor from "react-animated-cursor";

function App() {
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount((count) => count + 1)}>
        count is {count}
      </button>
      {count <= 1 && <AnimatedCursor />}
    </>
  );
}

export default App;

Potential Fix

These lines for removing event listeners seems suspicious. Although they might not directly relate to this issue, they seem wrong. The correct way is to create a named function for the event handler and pass that to the removeEventListener function. Otherwise, the added listeners are separate object than the listeners that are specified to remove.

when passing `color` cursor disappears

There no error i found

// only component i have
import AnimatedCursor from "react-animated-cursor"
export default function App() {
  return (
    <div className="w-[100vw] h-[100vh] bg-red-500">
      <AnimatedCursor
        color='#fff'
      />
    </div>
  )
}

Cursor showing on top left screen on mobile devices

I am having a problem where the custom cursor still shows on mobile devices. In particular, it is visible on the top-left of the screen. I am using Next.js 13.4.

"use client";

import AnimatedCursor from "react-animated-cursor";

const Cursor = () => {
  return (
    <AnimatedCursor
      innerSize={8}
      outerSize={35}
      innerScale={1}
      outerScale={2}
      outerAlpha={0}
      color="255, 255, 255"
      outerStyle={{
        border: "3px solid #fff",
      }}
      clickables={[
        "a",
        'input[type="text"]',
        'input[type="email"]',
        'input[type="number"]',
        'input[type="submit"]',
        'input[type="image"]',
        "label[for]",
        "select",
        "textarea",
        "button",
        ".link",
        {
          target: ".purple",
          innerScale: 0.8,
          outerStyle: {
            border: "4px solid #7a75ff",
          },
        },
        {
          target: ".gray",
          innerScale: 0.8,
          outerStyle: {
            border: "4px solid rgba(255,255,255,0.30)",
          },
        },
      ]}
    />
  );
};
export default Cursor;

A typo in readme file

Hi, there is a typo in the readme file in the Options section. Quick fix: change showSystemCursir to showSystemCursor

Unsupported Server Component type: undefined, using Next.js 13 App router

  • error node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1684:8) @ attemptResolveElement
  • error Error: Unsupported Server Component type: undefined
    null
  • error node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (1684:8) @ attemptResolveElement
  • error Error: Unsupported Server Component type: undefined
    CleanShot 2023-09-18 at 23 22 25@2x

Cursor is not detecting mobile applications accurately.

Hi!
As the current solution for detecting a touch device is not really reliable and there are media queries like (hover:none) or (pointer: coarse) available, I would like to implement a better solution to activate / deactivate the cursor.

Currently I have to build a workaround on sites where I use this package, but I think this should be implemented into the core.

I will probably create a Pull Request shortly to make it happen.

z-index problem

Recently I was developing my own developer portfolio with ReactJs/NextJs, TailwindCSS. On my sidebar I have provided the z-[999999] so in that case the react-animated-cursor got hide like below:
Screenshot_4
Screenshot_5

Apply custom style when hit a target

Hi,

Is there is a way to apply a certain style to the outer when it hit a clickable?
for example I want it to be green without border normally but when it's over a link it should have border with no fill and it scale as well. I hope the border animation still work as well.

I tried to use the clickables option with target.
This is a simple try to change the color to red when it's over a link, but it doesn't work, not sure what am I missing.
I tried to use color and outerStyle both didn't work.

Can you help please.

  <AnimatedCursor
        color="0, 233, 0"
        innerSize={0}
        outerSize={30}
        outerScale={2}
        trailingSpeed={9}
        showSystemCursor={true}
        clickables={[
          "a",
          'input[type="text"]',
          'input[type="email"]',
          'input[type="number"]',
          'input[type="submit"]',
          'input[type="image"]',
          "label[for]",
          "select",
          "textarea",
          "button",
          ".link",
          {
            target: ".custom",
            options: {
              //color: "233, 0, 0",
              outerStyle: { backgroundColor: "red" },
            },
          },
        ]}

Style props aren't applying and are breaking the cursor

Hey,

When I try to use style props, the cursor breaks. no cursor appears at all.

Without any, the cursor works as intended. I tried every example cursors and the same problem appears.

I'm using NextJS. I don't know if there's a special config or not.

apply opacity to inner

would be nice to override the opacity of the inner div

i have tried:

innerStyle={{
            backgroundColor: "#C6C6C6",
            border: "1px solid white",
            opacity: 0.666,
          }}

but this took no effect

iFrames

When moving my animated cursor over an iFrame it stops working

Cursor is not hiding on mobile on static rendered pages

Can't figure out why the cursor is still visible on and interacting on my iPhone safari.
FYI: The whole site is exported static.

My packages:

"dependencies": {
"@mdx-js/loader": "^2.3.0",
"@mdx-js/react": "^2.3.0",
"@motionone/utils": "^10.15.1",
"@next/bundle-analyzer": "^13.3.0",
"chota": "^0.9.2",
"cookies-next": "^4.0.0",
"framer-motion": "^10.12.3",
"keen-slider": "^6.8.6",
"marked-react": "^1.3.2",
"next": "^13.3.0",
"next-image-export-optimizer": "^1.8.3",
"next-themes": "^0.2.1",
"react": "^18.2.0",
"react-animated-cursor": "^2.7.0",
"react-dom": "^18.2.0",
"react-markdown": "^8.0.7",
"react-player": "^2.12.0",
"use-sound": "^4.0.1"
},
"devDependencies": {
"eslint": "7.32.0",
"eslint-config-next": "^13.3.0",
"gray-matter": "^4.0.3",
"marked": "^4.0.14",
"next-seo": "^5.4.0",
"next-sitemap": "^4.1.8",
"sass": "^1.62.0"
}

Check if cursorOuterRef is null

image

Add condition to check if the cursorOuterRef is still define or not to avoid error in console

thanks!

A third-level heading

Invalid hook call on fresh project

Receiving following error:
Screenshot_1
I created a project with create-react-app and installed the package through npm i react-animated-cursor

My App.js component just looks like this:
Screenshot_2

I tried clearing node_modules and npm installing again, but that doesn't help. Maybe I'm just being a dumb-dumb (I'm pretty new to React).
Really hoping to get this fixed, this looks like an awesome package!

The cursor does not disable active mode when I go to a new page in Next JS

The cursor does not disable active mode when I go to a new page in Next JS, It only works if I randomly click anywhere in the body on the new page then it works again, basically when I click a link and on the new page the cursor stays active the active does not go away until I click somewhere in the body.

Any solution to this? The library needs somehow to detect a page change a reset everything in the cursor until it goes over a link again.

Cannot read properties of null (reading 'style') on app refresh

Hello,
I'm having an issue that randomly appears while refreshing my app.
The error is

Uncaught TypeError: Cannot read properties of null (reading 'style') at (index.umd.js?5799:209:1)

    var animateOuterCursor = React.useCallback(function (time) {
      if (previousTimeRef.current !== undefined) {
        coords.x += (endX.current - coords.x) / trailingSpeed;
        coords.y += (endY.current - coords.y) / trailingSpeed;
        cursorOuterRef.current.style.top = "".concat(coords.y, "px");   //cursorOuterRef.current.style is null, hence the error
        cursorOuterRef.current.style.left = "".concat(coords.x, "px");
      }

My app.js returns the following component

return (
	<ThemeProvider>
		<DotRing />
		...
	</ThemeProvider>

and the DotRing component simply returns

return (
	<AnimatedCursor
		innerSize={10}
		outerSize={12}
		color={ cursorColor }
		innerAlpha={1}
		outerAlpha={0.2}
		innerScale={0.7}
		outerScale={2}
	/>
);

Do you have any idea on how to fix this?
Thank you!

{Bug} Getting 'Window is not defined after installing and importing as per docs

image

Using next.js with standard import in custom js file and importing it into the _app.js gives window not defined error. Importing directly gives the same error though. Any solution?

edit: it seems like we still need to turn ssr false to make it work in next.js.

However, i have another question now. I am using both light mode and dark mode based website so is there a way to turn color into something else on light mode?

ReferenceError: document is not defined

Hello, I am currently designing a Framer template that utilizes the "Cursor Follower" Framer module, which imports react-animated-cursor.

The author of 'Cursor Follower' module has stated that the error is associated with the external NPM library react-animated-cursor. Below is the error log from Framer :

Pages that failed to optimize:

### /
document is not defined
ReferenceError: document is not defined
    at u (file:///tmp/framer-ssg-BBjPoi/NLBZRBq3Veei-r9JhD4DCmPfwRKJ6p6rHHkV1lLcBsM.SVONRRR2.mjs:1:8258)
    at br (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:10899)
    at at (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:11638)
    at B (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:13844)
    at at (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:11865)
    at B (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:13844)
    at at (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:11952)
    at B (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:13844)
    at at (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:11865)
    at B (file:///tmp/framer-ssg-BBjPoi/ssgdeps.OVFUYB72.mjs:11:13844)

Please advise.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.