tengbao / vanta

Animated 3D backgrounds for your website
http://vantajs.com/
MIT License
5.45k stars 1.03k forks source link

Typescript Support? #86

Open JasonLandbridge opened 3 years ago

JasonLandbridge commented 3 years ago

Hi,

Are there plans to create some Typescript declaration files? It currently throws errors when used in a Vue Typescript project.

TS7016: Could not find a declaration file for module 'vanta/dist/vanta.waves.min'. '/src/WebUI/node_modules/vanta/dist/vanta.waves.min.js' implicitly has an 'any' type.
  Try `npm install @types/vanta` if it exists or add a new declaration (.d.ts) file containing `declare module 'vanta/dist/vanta.waves.min';`
    144 | import PathsOverview from '@overviews/PathsOverview.vue';
    145 | import * as THREE from 'three';
  > 146 | import WAVES from 'vanta/dist/vanta.waves.min';
        |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
rohitkrishna094 commented 3 years ago

How were you able to fix this?

JasonLandbridge commented 3 years ago
import * as THREE from 'three';
import WAVES from 'vanta/dist/vanta.waves.min';

I just did this and it works, ignoring the error

MightyPhoenix commented 2 years ago

you can also declare it as a module in a .d.ts file

declare module "vanta/dist/vanta.halo.min"; declare module "vanta/dist/vanta.net.min"; declare module "vanta/dist/vanta.dots.min"; declare module "vanta/src/vanta.halo.js";

rajpurohityogesh commented 2 years ago

Hey where should I put this .d.ts file?

I am trying to use this is ts react app and created index.d.ts file in my component file directory. But It didn't seem to work. Please respond asap.

Thank you.

TangoPJ commented 2 years ago

@rajpurohityogesh Hello, did you find the solution? I need help too :)

codrkoaz commented 2 years ago

I'm getting the same error in Nextjs with typescript.

rajpurohityogesh commented 2 years ago

Yes @TangoPJ. I put the file in src folder of react application. It seems to work that way.

knekvasil commented 2 years ago

I had this issue as well. This article was extremely helpful in understanding/solving it.

OThyagoCarvalho commented 1 year ago

this solved my problem, not sure if this is the most appropriate way to handle it; content of the vanta.types.d.ts file in the root folder:

declare module 'vanta/dist/vanta.birds.min' {
    const birds: any;
    export default birds;
}
rajpurohityogesh commented 1 year ago

@rajpurohityogesh Hello, did you find the solution? I need help too :)

Sorry I didn't saw your question. Yes, I did found the solution.

Create a file with '.d.ts' extension in src folder and put (declare module 'vanta/dist/vanta.globe.min.js';) this kind of code inside that for whatever module you need to use.

ghost commented 1 year ago

[Next JS]

Install Vanta and Three dependencies:

npm i vanta
npm i three
npm install --save @types/three

or

Include below script in: "_app.tsx"

import Script from "next/script";
import { useRouter } from "next/router";
<Layout>
{router.pathname === "/" && (
        // load third party scripts only on home page
        <>
          <Script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js" />
          <Script src="https://cdn.jsdelivr.net/npm/vanta/dist/vanta.halo.min.js" />
        </>
      )}
      <Component {...pageProps} />
</Layout>

THEN: Instead including rest of the code under (pages) example: /pages/index.tsx, do this on component level - example: /components/HeroBanner.tsx

Component level example:

import HALO from "vanta/dist/vanta.halo.min"
import * as THREE from "three";

export default function HeroBanner() {

// Here comes Vanta React Hook code

const [vantaEffect, setVantaEffect] = useState(0);
  const vantaRef = useRef(null);
  useEffect(() => {
    if (!vantaEffect) {
      setVantaEffect(
        HALO({
          el: vantaRef.current,
          THREE,
          color: 0x14b679,
          backgroundColor: 0x15173c,
          maxDistance: 34.0,
        })
      );
    }
    return () => {
      if (vantaEffect) vantaEffect.destory();
    };
  }, [vantaEffect]);

  return (
<div className="container" ref={vantaRef}">
  // Rest of your code
</div>
  )
}

Remember to add ref={vantaRef} attribute to your container element.

Hope this will help someone.

majkl-zumberi commented 1 year ago

for whoever is trying to integrate the Halo effect, here's the ts support create a file vantahalo.d.ts and paste the following content

export interface HaloParams {
  el: string
  mouseControls: boolean
  touchControls: boolean
  gyroControls: boolean
  minHeight: number
  minWidth: number
  xOffset?: number
  yOffset?: number
  size?: number
  backgroundColor?: string
}

export interface HaloInstance {
  setOptions: ({
    el,
    mouseControls,
    touchControls,
    gyroControls,
    minHeight,
    minWidth,
    size,
    xOffset,
    yOffset,
    backgroundColor
  }: Omit<HaloParams, 'el'>) => void
  resize: () => void
  destroy: () => void
}

declare global {
  interface Window {
    VANTA: {
      HALO: ({
        el,
        mouseControls,
        touchControls,
        gyroControls,
        minHeight,
        minWidth,
        size,
        xOffset,
        yOffset,
        backgroundColor
      }: HaloParams) => HaloInstance
    }
  }
}

remember to include this file into tsconfig.json into include array in order to be recognised

AJIJIi commented 1 year ago

Additionally @MightyPhoenix answer I will say that I put declaration file to the same directory as the file where I want to import. I named it 'index.d.ts', but for a long time I had an error because I also had a file named 'index.ts' there

joujou144 commented 1 month ago

If anyone having trouble to include three & vanta scripts in Next14++, particularly in the new app router settings with layout module does not allow use client directive, you can create a ScriptLoader component and import it into the root file (in this case layout.tsx)


import { useEffect } from "react";

const ScriptLoader = ({ src, id }: { src: string; id: string }) => {
  useEffect(() => {
    const script = document.createElement("script");
    script.id = id;
    script.src = src;
    script.async = true;

    document.head.appendChild(script);

    return () => {
      document.head.removeChild(script);
    };
  }, [src, id]);

  return null;
};

export default ScriptLoader;

In the layout.tsx, import the


  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" className="!scroll-smooth">
      <body className="relative overflow-x-hidden">
        <ScriptLoader
          id="threeScript"
          src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"
        />
        <ScriptLoader
          id="vantaScript"
          src="https://cdn.jsdelivr.net/npm/vanta/dist/vanta.halo.min.js"
        />
        <Navbar />
        {children}
      </body>
    </html>
  );
}```