کاغذِ مچاله‌شوندهPaper Crumple

تصویری که با نگه‌داشتن، مثل کاغذِ واقعی مچاله می‌شه؛ می‌تونی بکشیش و با رهاکردن، بسته به انتخابت باز می‌شه یا چروک می‌مونه.

محمدجواد

ساخته شده توسط محمدجواد

سازنده فارسی‌فای، بچه دولوپر

وابستگی‌ها

three

نوع تعامل

کاغذ رو با ماوس بگیر و نگه دار؛ مثلِ کاغذِ واقعی توی دستت مچاله می‌شه و با حرکت، کج می‌شه و دنبالت می‌آد. با رهاکردن، بسته به «رفتارِ رهاکردن» یا کامل باز می‌شه یا چروکی از خاطره‌ی مچاله‌شدن روش می‌مونه. با صفحه‌کلید: Space یا Enter رو نگه دار تا مچاله شه، با کلیدهای جهت جابه‌جاش کن (با Shift تندتر) و با Escape بازنشانی کن. با `prefers-reduced-motion` همه‌ی گذارها بی‌درنگ می‌شن.

پراپ‌ها

گزینه‌هایی که می‌تونی به کامپوننت بدی؛ ستاره‌دارها اجباری‌اند.

src
string

نشانیِ تصویری که کاغذ از روش ساخته می‌شه. اجباریه؛ تصویرِ دور باید CORS رو اجازه بده.

alt
stringپیش‌فرض: ""

متنِ جایگزینِ تصویر — هم برای `<img>` جایگزین و هم توی برچسبِ صفحه‌خوانِ دکمه می‌آد.

backSrc
stringپیش‌فرض: ""

تصویرِ پشتِ کاغذ. اگه ندی، پشتِ کاغذ `paperColor`ـه.

width
numberپیش‌فرض: 320

عرضِ کاغذ، پیکسل. با `height` نسبتِ کاغذ رو می‌سازه.

height
numberپیش‌فرض: 400

بلندیِ کاغذ، پیکسل.

sceneHeight
numberپیش‌فرض: 560

بلندیِ کلِ صحنه، پیکسل.

نصب

۱. این آدرس رو یک‌بار توی components.json بذار تا shadcn مخزن فارسی‌فای رو بشناسه.

components.jsonjson
{
  "registries": {
    "@farsify": "https://farsify.ir/r/{name}.json"
  }
}

۲. بعد با دستورِ زیر کامپوننت رو نصب کن.

npx shadcn@latest add @farsify/paper-crumple

پیش‌نیاز: Tailwind CSS v4 و صفحهٔ راست‌به‌چپ dir="rtl".

نمونه

paper-crumple.tsxtsx
"use client";

import { useState } from "react";
import PaperCrumple from "@/components/farsify/paper-crumple";

export function CrumplableNote() {
  // تغییرِ resetKey کاغذ را به حالتِ اول برمی‌گرداند
  const [resetKey, setResetKey] = useState(0);

  return (
    <PaperCrumple
      src="/note.jpg"
      alt="یادداشتِ دست‌نویس"
      width={320}
      height={320}
      sceneHeight={460}
      releaseBehavior="creased" // restore | creased | stay
      creaseStrength={0.25}
      resetKey={resetKey}
      onStateChange={(state) => console.log(state)} // flat | holding | crumpled | creased
    />
  );
}

// پس از رهاکردن با "restore" کاغذ کاملاً باز می‌شود؛
// با "stay" مچاله می‌ماند تا resetKey عوض شود یا Escape بزنند
<PaperCrumple src="/note.jpg" releaseBehavior="stay" />

نکته‌ها

  • این پورت **راست‌به‌چپ نمی‌شه و لازم هم نداره**: صحنه‌ی سه‌بعدی متقارنه؛ فقط برچسب‌ها و وضعیت‌های صفحه‌خوان فارسی شدن.
  • تصویرِ جلو رو `src` می‌ده و رنگِ پشت رو `paperColor` — توی چین‌های مچاله، پشتِ کاغذ از لابه‌لای قات‌وقروها پیدا می‌شه؛ پس رنگِ پشتی که با تصویر فرق داشته باشه مچاله‌شدن رو خواناتر می‌کنه.
  • `releaseBehavior="creased"` برای «یادداشت‌هایی که کهنه می‌شن» عالیه: `creaseStrength` رو کم بگیر تا هر بار فقط کمی چروک‌تر شه.
  • با `releaseBehavior="stay"` کاغذ مچاله می‌مونه تا `resetKey` رو عوض کنی یا `Escape` بزنن — برای بازی‌ها و افکت‌های یک‌بارمصرف.
  • این کامپوننت **تنها دموی بارگذاریِ پویای آرشیوه**: `three` با `next/dynamic` فقط روی همین صفحه لود می‌شه و بقیه‌ی سایت ازش بی‌بهره می‌مونه. اگه صفحه کند بود، `detail` رو کم کن — محاسبه‌ی چین‌ها با اون نمایی می‌شه.
  • کم‌بیننده‌ها هم جا نمی‌مونن: با `prefers-reduced-motion` مچاله و بازشدن بی‌درنگ می‌شه ولی منطقِ نگه‌داشتن و کشیدن دست‌نخورده می‌مونه، و اگه WebGL در دسترس نبود، خودش تصویرِ ساده رو نشون می‌ده و `onError` رو صدا می‌زنه.

مجوز

کد بعد از نصب مالِ خودته؛ هر تغییری خواستی بده و توی پروژه‌ی خودت نگهش دار. برای پروژه‌های شخصی و تجاری آزاده، حتی اگه کدت بسته باشه. فقط اسم و لینک فارسی‌فای رو یه جا توی پروژه نگه دار.