2025 내일배움캠프

노코드 툴 Framer 배우기 #4

sihyun22 2025. 12. 11. 20:25

Framer로 화면을 제작했다면, 더욱 실감나는 웹을 위해 다양한 인터렉션을 사용해볼 수 있다. 오늘은 Framer에서 구현할 수 있는 다양한 인터렉션들을 배워보았다.

 


 

Top Button

머티리얼 아이콘으로 Top Button을 제작하고 컴포넌트로 만들어준다. 

 

 

컴포넌트에서 아이콘을 복사해주고 보이지 않는 하단에 배치, Hover 상태의 버튼을 하나 더 만들어 보이지 않는 상단에 배치해주면, 마우스 Hover 시 인터렉션이 생긴 것을 확인할 수 있다.

 

 

 

버튼을 클릭하면 페이지의 상단으로 이동할 수 있도록 Hero SectionScrool Section을 만들어주고, 버튼 컴포넌트에 Link To를 설정해주면, 잘 작동이 되는 것을 확인할 수 있다.

 

 

에셋 페널에서 버튼을 불러와주고 배치시켜준 뒤, 포지션을 Fixed로 고정, Z Index를 2로 올려주면 가장 높은 레이어로 설정된다.(하단 Footer가 Z Index 1로 설정되어 있어 2로 올린 상황)

 

 

Mouse Cursor

Frame으로 원형 Mouse Follower을 제작해준 뒤, 컴포넌트로 만들어준다. Variant로 클릭 가능한 곳에 마우스를 올렸을 시, 나타날 Mouse Follower을 제작한다. 클릭할 요소가 뒤에 보일 수 있도록 투명도를 주었다.

 

 

클릭 될 요소들이 포함된 컴포넌트에 들어가 클릭할 요소들 모두 Cursor 옵션을 일일이 넣어주면 설정은 완료된다.

 

 

이제 화면에서 Cursor 옵션이 잘 적용되도록 데스트탑 전체 영역에는 Cursor Variant1을 설정해주고,

 

 

클릭이 가능한 요소가 포함된 모듈에는 Cursor Variant2를 적용해주면 완료된다.

 

 

Lottie

"Lottie는 JSON 기반의 벡터 애니메이션 파일 형식입니다. After Effects에서 만든 애니메이션을 Bodymovin 플러그인을 통해 JSON으로 내보내고, 이걸 웹, iOS, Android, React Native, Windows 등 다양한 플랫폼에서 실시간 렌더링할 수 있게 해 주는 기술입니다."

 

웹사이트에서 원하는 Lottie JSON 파일을 다운로드 해주고,

🔗 Lottiefiles

 

 

Framer에서 Insert → Lottie 검색 후 꺼내주어 다운로드 받은 파일을 업로드 해주면 원하는 페이지 위치에 배치 후 바로 Lottie를 사용할 수 있다.

 

 

Spline 3D 연동하기

"Spline이란 웹 기반 3D 디자인 툴로, 디자이너가 코드 없이 인터랙티브한 3D 콘텐츠를 만들 수 있게 해주는 도구입니다. 피그마, 프레이머, 비전 프로, 앱 빌드 등 다양한 플랫폼에 연동이 가능합니다."

 

먼저 Spline 홈페이지에서 원하는 3D를 데스트탑/모바일 화면의 링크를 복사하여 준비해주고,

🔗 Spline -Desktop

🔗 Spline -Mobile

 

 

Framer에서 Insert → Embed 검색 후 활성화, 좌측 패널에서 복사해 둔 링크를 삽입해주면 3D를 가져올 수 있다.

 

 

가져온 3D 화면은 Hero Section 배경에 배치해주고, Position을 Absolute, 값을 모두 0으로 설정해주면 반응형에도 대응하게 된다. Z Index는 0으로 낮춰주어 가장 뒤에 배경으로 위치할 수 있게 한다.

 

 

데스크탑에 가져온 화면은 모바일 환경에는 맞지 않기 때문에 Embed 컴포넌트를 복사, Mobile로 하나를 더 만들어주고, 모바일 3D 화면 링크를 삽입, 데스크탑에선 비활성화 해준다.

 

 

모바일 화면에선 Desktop Embed를 비활성화, Mobile Enbed를 활성화해주면 된다.

 

 

스크롤별 인터렉션 구현

! 인터렉션은 일일이 효과를 넣어주는 것으로 설정값을 잘 확인하며 설정하는게 중요하다. 설정값 캡쳐사진을 참고하며 다음에도 적용할 수 있도록 기록하였다.

 

상단 네비게이션 바 인터렉션을 위해 Fixed로 고정 후 좌측 패널에서 Effects를 설정해주면 완성이다.

설정값 확인

 

 

 

텍스트 인터렉션은 텍스트 선택 후 Effects → Text로 효과를 넣어준다.

 

 

타이틀 밑 서브 텍스트와 버튼은 0.4 딜레이를 주어 타이틀 이후에 효과가 들어갈 수 있도록 한다.

 

 

중간 타이틀에선 Layer in View로 레이어가 보일 때 효과가 나타나도록 설정해준다.

 

 

타이틀 옆 이미지도 효과를 넣어주고,

 

 

밑 이미지에도 효과를 넣어주면, 완성된다.

 

 

CMS 레이아웃 변경

CMS를 불러온 뒤, 디자인을 변경한다. Date의 경우 S~XL까지 스타일을 지정할 수 있으며 Locale도 한국식 날짜 표기로 지정할 수 있었다.

 

 

이미지의 경우 Positon Type을 Absolute로, Positon 값을 모두 0으로 해주고 아래 Size를 원하는 사이즈로 Fixed해주면 크기에 대응하여 이미지 크기가 맞춰진다.

 

 

각 디바이스마다 알맞은 디자인으로 변경해준 뒤, 컴포넌트로 제작한다.

 

 

Primary(Desktop)에 Hover를 만들어 4가지 포지션 값에 -40 값을 적용해주면, 마우스 Hover 시 이미지가 확대되는 인터페이스가 만들어진다.

 

 

CMS 공유하기 기능

소셜 플랫폼 아이콘을 제작, 컴포넌트로 인터렉션을 만들어 준 뒤,

 

 

아이콘 컴포넌트에 Code를 삽입하여 SNS로 공유하게 해줄 code 컴포넌트를 만든다.

🔽 소셜 공유하기 코드 컴포넌트

더보기

import { useCallback } from "react"
import type { ComponentType } from "react"

// X 공유
export function x_Share(Component): ComponentType {
    return (props) => {
        const handleTap = useCallback(() => {
            if (
                typeof window !== "undefined" &&
                typeof document !== "undefined"
            ) {
                const pageTitle = document.title
                const url = `https://twitter.com/intent/tweet?text=${encodeURIComponent(
                    `Notion Mail ${pageTitle}. `
                )}&url=${encodeURIComponent(window.location.href)}`
                window.open(url)
            }
        }, [])

        return <Component {...props} onTap={handleTap} />
    }
}

// Facebook 공유
export function Facebook_Share(Component): ComponentType {
    return (props) => {
        const handleTap = useCallback(() => {
            if (
                typeof window !== "undefined" &&
                typeof document !== "undefined"
            ) {
                const pageTitle = document.title
                const url = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(
                    window.location.href
                )}&quote=${encodeURIComponent(`Notion Mail "${pageTitle}"`)}`
                window.open(url)
            }
        }, [])

        return <Component {...props} onTap={handleTap} />
    }
}

// LinkedIn 공유
export function LinkedIn_Share(Component): ComponentType {
    return (props) => {
        const handleTap = useCallback(() => {
            if (
                typeof window !== "undefined" &&
                typeof document !== "undefined"
            ) {
                const pageTitle = document.title
                const url = `https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(
                    window.location.href
                )}&title=${encodeURIComponent(pageTitle)}&source=framer.com`
                window.open(url)
            }
        }, [])

        return (
            <Component
                {...props}
                onTap={handleTap}
                style={{ ...props.style, cursor: "pointer" }}
            />
        )
    }
}

// WhatsApp 공유
export function Whatsapp_Share(Component): ComponentType {
    return (props) => {
        const handleTap = useCallback(() => {
            if (typeof window !== "undefined") {
                const url = `https://api.whatsapp.com/send?text=${encodeURIComponent(
                    `Notion Mail : ${window.location.href}`
                )}`
                window.open(url)
            }
        }, [])

        return <Component {...props} onTap={handleTap} />
    }
}

// Email 공유
export function Email_Share(Component): ComponentType {
    return (props) => {
        const handleTap = useCallback(() => {
            if (typeof window !== "undefined") {
                const subject = encodeURIComponent("Check out this link!")
                const body = encodeURIComponent(
                    `Notion Mail : ${window.location.href}`
                )
                window.open(`mailto:?subject=${subject}&body=${body}`)
            }
        }, [])

        return <Component {...props} onTap={handleTap} />
    }
}

// 클립보드 복사
export function Clipboard_Share(Component): ComponentType {
    return (props) => {
        const handleTap = useCallback(() => {
            if (
                typeof window !== "undefined" &&
                typeof document !== "undefined"
            ) {
                const textField = document.createElement("textarea")
                textField.innerText = window.location.href
                document.body.appendChild(textField)
                textField.select()
                document.execCommand("copy")
                textField.remove()
                alert("링크복사가 완료되었어요!")
            }
        }, [])

        return <Component {...props} onTap={handleTap} />
    }
}

 

 

컴포넌트를 복제해서 클립보드 복사 / X 공유 / Facebook 공유 버튼 컴포넌트를 만들어주고, Code Overrides를 맞게 연결해주면 퍼블리쉬된 페이지에서 소셜 공유가 가능한 것을 확인할 수 있다.

 


 

오늘은 Framer에서 더욱 다이나믹하고 실감나는 웹 사용을 위한 인터렉션들과 기능들을 학습했다. 한 번만 해선 외우기 어려운 속성들이지만 화면에 적용됐을 때 확실히 웹이 생동감 있게 느껴졌다. 적용 방법을 위에 잘 정리해두어 필요할 때마다 다시 확인하며 익히는 과정이 필요할 것 같다.