Планирование похода
++ Создайте новый маршрут, выберите дату и пригласите участников +
+ + +
+
+ diff --git a/lab1/report/img/planning-screen.png b/lab1/report/img/planning-screen.png new file mode 100644 index 0000000..30bbc3a Binary files /dev/null and b/lab1/report/img/planning-screen.png differ diff --git a/lab1/report/img/planning-screen2.png b/lab1/report/img/planning-screen2.png new file mode 100644 index 0000000..54a13d1 Binary files /dev/null and b/lab1/report/img/planning-screen2.png differ diff --git a/lab1/report/img/planning-screen3.png b/lab1/report/img/planning-screen3.png new file mode 100644 index 0000000..fad5571 Binary files /dev/null and b/lab1/report/img/planning-screen3.png differ diff --git a/lab1/report/report.tex b/lab1/report/report.tex index 634615b..205de62 100644 --- a/lab1/report/report.tex +++ b/lab1/report/report.tex @@ -34,6 +34,7 @@ \renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге \renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице \usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы +\usepackage{subcaption} %для подфигур \usepackage{listings} %листинги \usepackage{xcolor} % цвета \usepackage{hyperref}% для гиперссылок @@ -912,11 +913,57 @@ \begin{figure}[h!] \centering - \includegraphics[width=0.5\linewidth]{img/template-screen.png} + \includegraphics[width=0.6\linewidth]{img/template-screen.png} \caption{Шаблон экранной формы мобильного приложения "По грибы!"} \label{fig:template} \end{figure} + \section{Эскизы экранных форм} + + На основе разработанного шаблона созданы экранные формы для ключевых процессов приложения. Каждая форма реализует описанные ранее функции и соответствует принципам дизайна ISO 9241-161. + + \subsection{Экран планирования похода} + + Экран планирования реализует функции конструктора маршрутов и подготовки к походу. Пользователь (организатор) может выбрать маршрут на карте, установить дату и время, просмотреть прогноз погоды и пригласить участников. + + \textbf{Основные элементы экрана:} + \begin{itemize} + \item \textbf{Предварительный просмотр карты} --- интерактивная область высотой 200pt с наложенным маршрутом, кнопка "Выбрать на карте" для перехода к полноэкранной карте. + \item \textbf{Информация о маршруте} --- карточка с основными параметрами: район (Токсово), расстояние (8.3 км), прогнозируемое время (4ч 30мин). + \item \textbf{Селекторы даты и времени} --- крупные нажимаемые элементы с иконками календаря и часов, отображают выбранные значения. + \item \textbf{Виджет погоды} --- показывает температуру, описание погоды, время восхода/заката, скорость ветра для выбранной даты. + \item \textbf{Список участников} --- карточки с аватарами, именами, ролями и статусами подтверждения. Кнопка "Пригласить ещё" для добавления новых участников. + \item \textbf{Кнопки действий} --- "Сохранить черновик" (вторичная) и "Создать поход" (основная, оранжевая). + \end{itemize} + + Экран оптимизирован для быстрого планирования: все ключевые параметры видны без прокрутки, часто используемые действия доступны крупными кнопками. Прогноз погоды помогает организатору принять решение о целесообразности похода. + +\begin{figure}[h!] + \centering + \begin{subfigure}[b]{0.30\linewidth} + \centering + \includegraphics[width=\textwidth]{img/planning-screen.png} + \caption{Карта} + \label{fig:planning-screen} + \end{subfigure} + \hfill + \begin{subfigure}[b]{0.30\linewidth} + \centering + \includegraphics[width=\textwidth]{img/planning-screen2.png} + \caption{Когда идём?} + \label{fig:planning-screen2} + \end{subfigure} + \hfill + \begin{subfigure}[b]{0.30\linewidth} + \centering + \includegraphics[width=\textwidth]{img/planning-screen3.png} + \caption{Участники похода} + \label{fig:planning-screen3} + \end{subfigure} + \caption{Экран планирования похода} + \label{fig:planning-screens} +\end{figure} + % \section{Выводы} % Описан интерфейс приложения для семейного похода за грибами: выделены заинтересованные лица, их ожидания, требования к платформе, модели пользователей и сценарии. Рассмотрены функции, диалоговые структуры, методы снижения ошибок и особенности дизайна. Подготовленный материал служит основой для создания макета экранов и дальнейшего прототипирования. diff --git a/lab1/screen-forms/common.css b/lab1/screen-forms/common.css new file mode 100644 index 0000000..728a054 --- /dev/null +++ b/lab1/screen-forms/common.css @@ -0,0 +1,412 @@ +/* Общие переменные для всех экранных форм приложения "По грибы!" */ + +:root { + /* Цветовая палитра */ + --color-primary: #2D5F3F; + /* Лесной зелёный */ + --color-primary-light: #3A7A52; + /* Светлый зелёный для градиентов */ + --color-accent: #E67E22; + /* Янтарный оранжевый */ + --color-danger: #C0392B; + /* Тревожный красный */ + --color-info: #3498DB; + /* Небесный голубой */ + + /* Нейтральная палитра */ + --color-text-dark: #2C3E50; + /* Основной цвет текста */ + --color-text-medium: #7F8C8D; + /* Второстепенный текст */ + --color-bg-light: #FAFAFA; + /* Основной фон */ + --color-bg-card: #FFFFFF; + /* Фон карточек */ + --color-border: #ECF0F1; + /* Разделители */ + --color-bg-secondary: #ECF0F1; + /* Вторичный фон */ + + /* Семантические цвета */ + --color-success: #2ECC71; + /* Успех */ + --color-warning: #F39C12; + /* Предупреждение */ + + /* Типографика */ + --font-family: 'Inter', 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + --font-size-base: 16px; + --font-size-small: 14px; + --font-size-tiny: 12px; + --font-size-large: 18px; + --font-size-xlarge: 22px; + --font-size-xxlarge: 24px; + + --font-weight-regular: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + + --line-height-tight: 1.2; + --line-height-normal: 1.4; + --line-height-relaxed: 1.5; + + /* Размеры и отступы */ + --spacing-xs: 4px; + --spacing-sm: 8px; + --spacing-md: 12px; + --spacing-lg: 16px; + --spacing-xl: 20px; + --spacing-xxl: 24px; + --spacing-xxxl: 32px; + + /* Радиусы скругления */ + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 16px; + --radius-full: 50%; + + /* Размеры элементов */ + --touch-target-min: 48px; + /* Минимальный размер для касания */ + --touch-target-large: 56px; + /* Увеличенный размер */ + --sos-button-size: 80px; + /* Размер кнопки SOS */ + + /* Размеры контейнера */ + --app-width: 375px; + --app-height: 700px; + --header-height: 64px; + --nav-height: 72px; + + /* Тени */ + --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.06); + --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08); + --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.1); + --shadow-sos: 0 4px 16px rgba(192, 57, 43, 0.4); + + /* Длительность анимаций */ + --transition-fast: 150ms; + --transition-medium: 250ms; + --transition-slow: 400ms; +} + +/* Общие стили сброса */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: var(--font-family); + background-color: var(--color-bg-light); + color: var(--color-text-dark); + font-size: var(--font-size-base); + line-height: var(--line-height-normal); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Контейнер приложения */ +.app-container { + width: var(--app-width); + height: var(--app-height); + margin: 20px auto; + background: var(--color-bg-light); + position: relative; + display: flex; + flex-direction: column; + box-shadow: var(--shadow-lg); + border-radius: 20px; + overflow: hidden; +} + +/* Шапка приложения */ +.app-header { + background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-light) 100%); + padding: var(--spacing-lg) var(--spacing-xl) var(--spacing-md); + box-shadow: var(--shadow-md); +} + +.header-content { + display: flex; + align-items: center; + gap: var(--spacing-md); +} + +.app-logo { + width: 36px; + height: 36px; + object-fit: contain; +} + +.app-title { + font-size: var(--font-size-xxlarge); + font-weight: var(--font-weight-bold); + color: var(--color-bg-card); + letter-spacing: -0.5px; +} + +/* Основной контент */ +.app-main { + flex: 1; + overflow-y: auto; + padding-bottom: calc(var(--nav-height) + var(--spacing-sm)); +} + +.content-container { + padding: var(--spacing-xl); +} + +/* Скроллбар */ +.app-main::-webkit-scrollbar { + width: 4px; +} + +.app-main::-webkit-scrollbar-track { + background: transparent; +} + +.app-main::-webkit-scrollbar-thumb { + background: #BDC3C7; + border-radius: 2px; +} + +.app-main::-webkit-scrollbar-thumb:hover { + background: #95A5A6; +} + +/* Заголовки */ +.screen-title { + font-size: var(--font-size-xlarge); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); + margin-bottom: var(--spacing-sm); +} + +.screen-description { + font-size: var(--font-size-base); + line-height: var(--line-height-relaxed); + color: var(--color-text-medium); + margin-bottom: var(--spacing-xxl); +} + +/* Карточки */ +.card { + background: var(--color-bg-card); + border-radius: var(--radius-md); + padding: var(--spacing-lg); + margin-bottom: var(--spacing-lg); + box-shadow: var(--shadow-md); +} + +.card-title { + font-size: var(--font-size-large); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); + margin-bottom: var(--spacing-sm); +} + +.card-text { + font-size: var(--font-size-base); + line-height: var(--line-height-normal); + color: var(--color-text-medium); +} + +/* Элементы списка */ +.list-item { + display: flex; + align-items: center; + gap: var(--spacing-md); + background: var(--color-bg-card); + border-radius: var(--radius-md); + padding: 14px var(--spacing-lg); + margin-bottom: var(--spacing-md); + box-shadow: var(--shadow-sm); + transition: transform var(--transition-fast) ease, box-shadow var(--transition-fast) ease; + cursor: pointer; +} + +.list-item:active { + transform: scale(0.98); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.list-item-icon { + font-size: 28px; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-bg-secondary); + border-radius: 10px; + flex-shrink: 0; +} + +.list-item-content { + flex: 1; +} + +.list-item-title { + font-size: 17px; + font-weight: var(--font-weight-medium); + color: var(--color-text-dark); + margin-bottom: 3px; +} + +.list-item-subtitle { + font-size: var(--font-size-small); + color: var(--color-text-medium); +} + +/* Кнопки */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + padding: var(--spacing-md) var(--spacing-xxl); + border: none; + border-radius: var(--radius-sm); + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + cursor: pointer; + transition: all var(--transition-fast) ease; + min-height: var(--touch-target-min); +} + +.btn-primary { + background: var(--color-accent); + color: var(--color-bg-card); +} + +.btn-primary:active { + background: #D35400; + transform: scale(0.97); +} + +.btn-secondary { + background: var(--color-bg-secondary); + color: var(--color-text-dark); +} + +.btn-secondary:active { + background: #D5DBDB; + transform: scale(0.97); +} + +.btn-full { + width: 100%; +} + +/* Нижняя навигация */ +.app-navigation { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: var(--nav-height); + background: var(--color-bg-card); + border-top: 1px solid var(--color-border); + display: flex; + justify-content: space-around; + align-items: center; + padding: var(--spacing-sm) 0; + box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05); +} + +.nav-button { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: var(--spacing-xs); + background: none; + border: none; + padding: 6px 10px; + cursor: pointer; + transition: transform var(--transition-fast) ease; + min-width: 56px; +} + +.nav-button:active { + transform: scale(0.95); +} + +.nav-icon { + font-size: 24px; + line-height: 1; +} + +.nav-label { + font-size: 11px; + color: var(--color-text-medium); + font-weight: var(--font-weight-medium); +} + +.nav-button-active .nav-label { + color: var(--color-primary); + font-weight: var(--font-weight-semibold); +} + +.nav-button-active { + position: relative; +} + +.nav-button-active::after { + content: ''; + position: absolute; + bottom: -8px; + left: 50%; + transform: translateX(-50%); + width: 32px; + height: 3px; + background: var(--color-primary); + border-radius: 2px 2px 0 0; +} + +/* Кнопка SOS */ +.sos-button { + position: absolute; + bottom: calc(var(--nav-height) + var(--spacing-lg)); + right: var(--spacing-xl); + width: var(--sos-button-size); + height: var(--sos-button-size); + background: var(--color-danger); + border: 4px solid var(--color-bg-card); + border-radius: var(--radius-full); + display: flex; + align-items: center; + justify-content: center; + box-shadow: var(--shadow-sos); + cursor: pointer; + transition: transform var(--transition-fast) ease, box-shadow var(--transition-fast) ease; + z-index: 100; + animation: pulse 2s ease-in-out infinite; +} + +.sos-button:active { + transform: scale(0.95); + box-shadow: 0 2px 8px rgba(192, 57, 43, 0.5); +} + +.sos-icon { + font-size: 32px; + color: var(--color-bg-card); + font-weight: bold; +} + +@keyframes pulse { + + 0%, + 100% { + box-shadow: 0 4px 16px rgba(192, 57, 43, 0.4); + } + + 50% { + box-shadow: 0 4px 24px rgba(192, 57, 43, 0.6); + } +} \ No newline at end of file diff --git a/lab1/screen-forms/img/map-preview.png b/lab1/screen-forms/img/map-preview.png new file mode 100644 index 0000000..c95b8b0 Binary files /dev/null and b/lab1/screen-forms/img/map-preview.png differ diff --git a/lab1/screen-forms/planning-screen.css b/lab1/screen-forms/planning-screen.css new file mode 100644 index 0000000..f0a7ad8 --- /dev/null +++ b/lab1/screen-forms/planning-screen.css @@ -0,0 +1,304 @@ +/* Специфичные стили для экрана планирования похода */ + +/* Контейнер карты */ +.map-container { + position: relative; + width: 100%; + height: 200px; + border-radius: var(--radius-md); + overflow: hidden; + margin-bottom: var(--spacing-lg); + box-shadow: var(--shadow-md); +} + +.map-preview { + width: 100%; + height: 100%; + object-fit: cover; +} + +.map-action-btn { + position: absolute; + bottom: var(--spacing-md); + right: var(--spacing-md); + display: flex; + align-items: center; + gap: var(--spacing-sm); + padding: var(--spacing-sm) var(--spacing-lg); + background: var(--color-bg-card); + border: none; + border-radius: var(--radius-sm); + font-size: var(--font-size-small); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); + box-shadow: var(--shadow-md); + cursor: pointer; + transition: transform var(--transition-fast) ease; +} + +.map-action-btn:active { + transform: scale(0.95); +} + +.btn-icon { + font-size: 16px; + line-height: 1; +} + +/* Информация о маршруте */ +.route-info { + margin-bottom: var(--spacing-lg); +} + +.info-row { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--spacing-md) 0; + border-bottom: 1px solid var(--color-border); +} + +.info-row:last-child { + border-bottom: none; + padding-bottom: 0; +} + +.info-row:first-child { + padding-top: 0; +} + +.info-label { + font-size: var(--font-size-base); + color: var(--color-text-medium); +} + +.info-value { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); +} + +/* Секции */ +.date-time-section, +.participants-section { + margin-bottom: var(--spacing-xxl); +} + +.section-title { + font-size: var(--font-size-large); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); + margin-bottom: var(--spacing-md); +} + +/* Селекторы даты и времени */ +.date-selector, +.time-selector { + display: flex; + align-items: center; + gap: var(--spacing-md); + padding: var(--spacing-lg); + cursor: pointer; + transition: transform var(--transition-fast) ease; +} + +.date-selector { + margin-bottom: var(--spacing-md); +} + +.date-selector:active, +.time-selector:active { + transform: scale(0.98); +} + +.selector-icon { + font-size: 28px; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-bg-secondary); + border-radius: 10px; + flex-shrink: 0; +} + +.selector-content { + flex: 1; +} + +.selector-label { + font-size: var(--font-size-small); + color: var(--color-text-medium); + margin-bottom: 2px; +} + +.selector-value { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); +} + +.selector-arrow { + font-size: 24px; + color: var(--color-text-medium); + line-height: 1; +} + +/* Карточка погоды */ +.weather-card { + margin-bottom: var(--spacing-xxl); +} + +.weather-header { + display: flex; + align-items: center; + gap: var(--spacing-md); + margin-bottom: var(--spacing-lg); +} + +.weather-icon { + font-size: 48px; + line-height: 1; +} + +.weather-info { + flex: 1; +} + +.weather-temp { + font-size: var(--font-size-xlarge); + font-weight: var(--font-weight-bold); + color: var(--color-text-dark); + margin-bottom: 2px; +} + +.weather-desc { + font-size: var(--font-size-base); + color: var(--color-text-medium); +} + +.weather-details { + display: flex; + justify-content: space-between; + padding-top: var(--spacing-md); + border-top: 1px solid var(--color-border); +} + +.weather-detail { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-xs); +} + +.detail-label { + font-size: var(--font-size-small); + color: var(--color-text-medium); +} + +.detail-value { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); +} + +/* Участники */ +.participant-item { + display: flex; + align-items: center; + gap: var(--spacing-md); + background: var(--color-bg-card); + border-radius: var(--radius-md); + padding: var(--spacing-md) var(--spacing-lg); + margin-bottom: var(--spacing-md); + box-shadow: var(--shadow-sm); +} + +.participant-avatar { + font-size: 32px; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-bg-secondary); + border-radius: var(--radius-full); + flex-shrink: 0; +} + +.participant-info { + flex: 1; +} + +.participant-name { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + color: var(--color-text-dark); + margin-bottom: 2px; +} + +.participant-role { + font-size: var(--font-size-small); + color: var(--color-text-medium); +} + +.participant-status { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-full); + font-size: 16px; + font-weight: var(--font-weight-bold); + flex-shrink: 0; +} + +.status-confirmed { + background: #D5F4E6; + color: var(--color-success); +} + +.status-pending { + background: #FEF5E7; + color: var(--color-warning); +} + +/* Кнопка добавления участника */ +.btn-add-participant { + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + width: 100%; + padding: var(--spacing-md); + background: transparent; + border: 2px dashed var(--color-border); + border-radius: var(--radius-md); + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + color: var(--color-text-medium); + cursor: pointer; + transition: all var(--transition-fast) ease; + margin-top: var(--spacing-sm); +} + +.btn-add-participant:active { + transform: scale(0.98); + border-color: var(--color-primary); + color: var(--color-primary); +} + +/* Секция действий */ +.actions { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + margin-top: var(--spacing-xxl); +} + +/* Нижний отступ для прокрутки */ +.bottom-spacer { + height: var(--spacing-xl); +} \ No newline at end of file diff --git a/lab1/screen-forms/planning-screen.html b/lab1/screen-forms/planning-screen.html new file mode 100644 index 0000000..48c3aaa --- /dev/null +++ b/lab1/screen-forms/planning-screen.html @@ -0,0 +1,177 @@ + + + +
+ + +
+ + Создайте новый маршрут, выберите дату и пригласите участников +
+ + +
+
+