В своем последнем посте я настроил бэкэнд для приложения Bearcam Companion с помощью AWS Amplify Studio. В этот раз я напишу о коде фронтенда и его подключении к бэкенду с помощью Amplify CLI.

Существует множество интерфейсных фреймворков на выбор. Поскольку я создаю веб-приложение с помощью AWS Amplify и знаком с JavaScript, мне удалось значительно сузить круг вопросов. В конце концов я выбрал React (главным образом потому, что я обнаружил, что в большинстве примеров AWS Amplify используется React).

Ознакомьтесь с разделом Начало работы с React в Amplify, чтобы узнать об основах.

Настраивать

Я начал с пустого приложения React (вы можете изменить имя с myapp на то, что вы хотите назвать своим приложением):

npx create-react-app@latest myapp
cd myapp

У меня уже был установлен Amplify CLI из предыдущего учебника, поэтому мне просто нужно вытащить свой проект. Я получил соответствующую команду от Amplify Studio, щелкнув ссылку Инструкция по локальной настройке в правом верхнем углу страницы Studio. Команда будет выглядеть примерно так:

amplify pull --appId <app-ID> --envName <environment>

<app-ID> будет заполнено для вас, и вы сможете выбирать между своими <environments> (у меня пока только среда staging).

Приложение

Я следовал различным руководствам, чтобы соединить интерфейс React с серверной частью Amplify. После того, как у меня была базовая настройка, я отредактировал App.js (под src/App.js), добавив файл FrameView. Это будет основной вид приложения Bearcam Companion. Мне нужно импортировать его в App.js и добавить JSX в функцию return():

import FrameView from './FrameView';

function App() {
  return (
    <div className="App">
      <h2>Bearcam Companion</h2>
      <FrameView/>
    </div>
  );
}

export default App;

Вид кадра

В FrameView я хочу использовать FrameCollection, который я создал в Amplify Studio, чтобы отображать последние видеокадры в моей таблице Изображения. Я уже подключил компонент FrameCollection к модели данных с помощью Amplify Studio. Код был снят, когда я сделал amplify pull. Фактически, все компоненты из исходных примеров Figma, а также те, которые я создал, отображаются под src/ui-components. Вот мой исходный код FrameView, включая компонент FrameCollection:

import { FrameCollection } from './ui-components'

export default function FrameView () {

    return(
      <div>
        <FrameCollection width={"100vw"} itemsPerPage={4} />
      </div>
    )
}

Примечание. itemsPerPage предоставляет простой способ переопределить, сколько изображений вы хотите включить в коллекцию.

Просмотр в браузере

На данный момент я могу запустить npm:

npm start

Теперь я могу просматривать свое приложение в браузере (я использую Chrome) по адресу http://localhost:3000/. Пока это выглядит так:

Основная цель FrameView — отобразить кадр ( FrameCollection будет использоваться для выбора кадра). Я также хочу иметь возможность рисовать ограничивающие рамки из модели данных Objects на фрейме. Сначала я поработаю над отображением и выбором кадра.

Добавьте изображение рамки

Я добавил <img> в FrameView, изначально жестко запрограммировав источник изображения на одно из изображений из моего набора Amplify Content. Теперь приложение начинает обретать форму:

Выберите кадр из коллекции FrameCollection

Я добавил событие onClick к FrameCollection, используя следующий код в FrameView.js (см. эту страницу для получения дополнительной информации):

  <FrameCollection width={"100vw"} itemsPerPage={4}
   overrideItems={({ item, index }) => 
                  ({onClick: () => {updateFrame(item)}
  })} />

Затем я создал updateFrame, который обновляет источник изображения:

  function updateFrame(item) {
    document.getElementById("refImage").src = item.url
  }

Теперь, когда я нажимаю на изображение в FrameCollection, вид основного кадра обновляется до этого изображения.

Нарисуйте ограничивающие рамки

Мне все еще нужно добавить ограничивающие рамки на изображение. Моей первой мыслью было использовать элемент HTML Canvas. Я добавил <canvas> вместо элемента <img> и спрятал <img>. Поскольку браузер уже позаботился о загрузке <img>, мне не нужно было беспокоиться о загрузке логики. Я мог бы сослаться на него с помощью document.getElementById и нарисовать его на холсте. Я использовал image.id для поиска всех ограничивающих рамок для этого изображения в Objects с помощью такой строки:

const boxes = await DataStore.query(Objects, c => c.imagesID("eq", imageID));

Теперь я перебрал boxes и нарисовал каждый на <canvas>. Я закончил с чем-то вроде этого:

Я не доволен этим решением по двум основным причинам:

  1. Это действительно должно было выглядеть хорошо.
  2. Я не могу легко обрабатывать действия наведения или щелчка для полей, что будет важно, когда мне нужна дополнительная информация или щелчок для редактирования.

Должен быть лучший способ

Для вдохновения я посмотрел на демо для Amazon Rekognition (которое я использовал, чтобы получить ограничивающие рамки для своего тестового контента). Демонстрация Rekognition использует относительное расположение <div> со стилизованными границами для каждого блока. Это выглядит намного лучше (и может быть изменено с помощью CSS) и должно упростить обработку действий пользователя.

Я углублюсь в это в следующий раз…

Первоначально опубликовано на https://dev.to 31 мая 2022 г.