برنامه نویسی

بارگیری تصاویر با React/JavaScript – انجمن DEV 👩‍💻👨‍💻

[NOTE: The live web app that encompasses this functionality can be found here: https://www.paintmap.studio. All of the underlying code for that site can be found here: https://github.com/bytebodger/color-map.]

در اولین مقاله از این مجموعه، من در مورد چالش های مربوط به گرفتن کدهای رنگ دیجیتال از اشیاء دنیای واقعی صحبت کردم. (یا همانطور که به این آموزش مربوط می شود، نمونه های دنیای واقعی از رنگ.) اما هنگامی که من یک نمایش دیجیتال معقول از هر رنگ موجودی خود داشتم، مجبور شدم در واقع تصاویری را که می‌خواستم دستکاری کنم، بگیرم.

توضیحات تصویر

در حال بارگذاری تصویر

من بحث کردم که آیا این مقاله را بنویسم زیرا آپلود فایل ها یک کار بسیار اساسی در جعبه ابزار یک توسعه دهنده است. اما بیشتر آموزش هایی که در مورد پردازش فایل ها می بینید، فرض می کنند که شما واقعاً اینطور هستید در حال آپلود تصویر – به برخی از سرورها.

اما در این مورد، ما در حال ساخت یک برنامه React هستیم و نیاز خاصی به ذخیره تصاویر در سرور نداریم. ما فقط باید آنها را بگیریم تا بتوان آنها را به صورت برنامه ای مدیریت کرد. بنابراین من می خواهم نشان دهم که چگونه این کار را در اینجا انجام می دهم.

این یک نسخه کاملاً حذف شده از مؤلفه UI است که من در Paint Map Studio از آن استفاده می کنم:

/* UI.js */

export const UIState = createContext({});

export const UI = props => {
   const blob = useRef(null);
   const file = useRef(null);
   const [stats, setStats] = useState({});

   return <>
      <UIState.Provider value={{
         blob,
         file,
         setStats,
         stats,
      }}>
         <IndexContainer/>
         <div>
            <canvas id={'canvas'}></canvas>
         </div>
      </UIState.Provider>
   </>;
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کل برنامه تحت این مؤلفه UI زندگی می کند. در اینجا فقط به چند نکته اشاره می کنم:

  1. من از زمینه برای تداوم متغیرها و اشتراک‌گذاری وضعیت استفاده می‌کنم. به همین دلیل داوری برای وجود دارد blob و file. stats اطلاعات مربوط به تصویر پردازش شده را نگه می دارد. من می‌خواهم آن مقادیر در حافظه باقی بمانند تا کاربر مجبور نباشد دائماً همان فایل را هر بار که می‌خواهد تنظیمات را تغییر دهد دوباره بارگذاری کند.

  2. توجه داشته باشید که یک وجود دارد <canvas> عنصر درست در اینجا در بالای برنامه جاسازی شده است. آن عنصر در نهایت تصویر پردازش شده ما را نگه می دارد و نمایش می دهد.

حالا بیایید به مؤلفه IndexContainer نگاه کنیم:

/* IndexContainer.js */

export const IndexState = createContext({});

export const IndexContainer = () => {
   return <>
      <IndexState.Provider value={{}}>
         <Index/>
      </IndexState.Provider>
   </>
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به نظر می رسد یک جزء بسیار بی معنی است، درست است؟ خوب، در حال حاضر فقط یک مکان نگهدارنده است. IndexContainer Index را می پیچد زیرا در نهایت من از آن برای ذخیره همه متغیرهای فرم موجود در مؤلفه Index استفاده خواهم کرد. آنها از طریق زمینه قابل دسترسی خواهند بود. اما در حال حاضر، واقعاً هیچ کاری برای این مؤلفه وجود ندارد، به جز فراخوانی Index.

حالا بیایید به مؤلفه Index نگاه کنیم:

/* Index.js */

export const Index = () => {
   const selectImageInputRef = useRef(null);
   const file = useFile();

   const handleFile = (event = {}) => {
      const [source] = event.target.files;
      file.read(source);
   };

   const handleImageButton = () => {
      selectImageInputRef.current && selectImageInputRef.current.click();
   }

   return <>
      <input
         accept={'image/*'}
         className={'displayNone'}
         onChange={handleFile}
         ref={selectImageInputRef}
         type={inputType.file}
      />
      <Button
         onClick={handleImageButton}
         variant={'contained'}
      >
         Select Image
      </Button>
   </>;
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا ما یک پنهان داریم <input> عنصری که در واقع کار گرفتن تصویر انتخابی کاربر را انجام می دهد. ما همچنین یک رابط کاربری Material UI داریم <Button> که کنترل می کند <input> عنصر به همین دلیل است که ما آن را داریم selectImageInputRef مرجع.

این handleFile() تابع چیزی است که در واقع پردازش فایل تصویر را شروع می کند. به طور خاص، آن را صدا می کند read() عملکرد در useFile قلاب.

پس بیایید نگاه کنیم useFile قلاب:

/* useFile.js */

export const useFile = () => {
   const image = useImage();
   const uiState = useContext(UIState);

   const read = (chosenFile = {}) => {
      const fileReader = new FileReader();
      fileReader.onloadend = event => {
         uiState.file.current = chosenFile;
         uiState.blob.current = event.target.result;
         image.create(uiState.blob.current);
      };
      try {
         fileReader.readAsDataURL(chosenFile);
      } catch (e) {
         // no file - do nothing
      }
   };

   return {
      read,
   };
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

یک نیز وجود دارد reload() عملکرد در نسخه نهایی از useFile قلاب. اما در حال حاضر، ما فقط نیاز داریم read(). توجه کنید که read() مکان فایل و داده ها را در ref هایی که در آن ایجاد کردیم ذخیره می کند UI جزء.

دارم یک نمونه جدید میسازم FileReader و سپس با استفاده از readAsDataURL() برای بارگذاری محتویات پس از بارگیری، onloadend شلیک خواهد کرد، که در نهایت به create() عملکرد در useImage قلاب.

در اینجا یک نسخه بدون استخوان از آن است useImage قلاب:

/* useImage.js */

export const useImage = () => {
   const canvas = useRef(null);
   const context = useRef(null);
   const image = useRef(null);

   useEffect(() => {
      canvas.current = document.getElementById('canvas');
   }, []);

   const create = (src = '') => {
      const source = src === '' ? image.current.src : src;
      const newImage = new Image();
      newImage.src = source;
      newImage.onload = () => {
         image.current = newImage;
         canvas.current.width = newImage.width;
         canvas.current.height = newImage.height;
         context.current = canvas.current.getContext('2d', {alpha: false, willReadFrequently: true});
         context.current.drawImage(newImage, 0, 0);
      }
   };

   return {
      create,
   };
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اینجا جایی است که جادوی رندر رخ می دهد. منبع از read() عملکرد در useFile قلاب. سپس از آن منبع برای ایجاد یک تصویر مجازی در حافظه استفاده می شود new Image().

هنگامی که تصویر مجازی بارگذاری شد، onload آتش سوزی های رویداد در آن تابع من از canvas ref که داخلش وصل بود useEffect. هنگامی که یک زمینه بوم جدید ایجاد کردم، می توانم از آن استفاده کنم newImage برای رندر کردن آن مقادیر در داخل متن.

این فایل تصویر انتخابی کاربر را می گیرد و روی صفحه نمایش می دهد. در این مرحله، تمام کاری که ما انجام داده ایم این است که تصویر خام را ارائه کنیم. اما این مرحله اولیه مهم است. زیرا اکنون که بوم را رندر کرده ایم (و در حافظه باقی مانده است)، می توانیم آن را برای نیازهای خود دستکاری کنیم.

توضیحات تصویر

در قسط بعدی…

اکنون که تصویر را بارگذاری کردیم، مرحله بعدی پیکسل کردن آن خواهد بود. در مقاله بعدی نحوه انجام این کار را به صورت برنامه ای نشان خواهم داد.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا