Шаблон планировщика
Шаблон планировщика событий на шкале времени.
Иногда дизайнеры наворотят нечто такое, что сложно превратить в удобную адаптивную веб страницу. Мы бросаем им вызов!
Структура
HTML структура будет состоять из трёх основных элементов: шакалы времени div.timeline
для событий (09:00, 09:30, ..), контейнера событий div.events
и модального окна div.event-modal
с подробной информацией о выбранном событии.
<div class="cd-schedule"> <div class="timeline"> <ul> <li><span>09:00</span></li> <li><span>09:30</span></li> <!-- additional elements here --> </ul> </div> <div class="events"> <ul> <li class="events-group"> <div class="top-info"><span>Monday</span></div> <ul> <li class="single-event" data-start="09:30" data-end="10:30" data-content="event-abs-circuit" data-event="event-1"> <a href="#0"> <em class="event-name">Abs Circuit</em> </a> </li> <!-- other events here --> </ul> </li> <li class="events-group"> <div class="top-info"><span>Tuesday</span></div> <ul> <!-- events here --> </ul> </li> <!-- additional li.events-group here --> </ul> </div> <div class="event-modal"> <header class="header"> <div class="content"> <span class="event-date"></span> <h3 class="event-name"></h3> </div> <div class="header-bg"></div> </header> <div class="body"> <div class="event-info"></div> <div class="body-bg"></div> </div> <a href="#0" class="close">Close</a> </div> </div>
Стили
На устройствах с небольшим экраном (< 800px) все события в .events-group
расположены в горизонтальном порядке: Выставляем display: flex
элементу .events-group > ul
значение overflow-x: scroll
чтобы события можно было прокручивать.
.cd-schedule .events .events-group > ul { position: relative; padding: 0 5%; /* force its children to stay on one line */ display: flex; overflow-x: scroll; -webkit-overflow-scrolling: touch; } .cd-schedule .events .single-event { /* force them to stay on one line */ flex-shrink: 0; float: left; height: 150px; width: 70%; max-width: 300px; }
При клике по событию класс .modal-is-open
спровоцирует преобразование объекта .event-modal
.
.cd-schedule .event-modal { position: fixed; z-index: 3; top: 0; right: 0; height: 100%; width: 100%; visibility: hidden; transform: translateX(100%); transition: transform .4s, visibility .4s; } .cd-schedule.modal-is-open .event-modal { /* .modal-is-open class is added as soon as an event is selected */ transform: translateX(0); visibility: visible; }
На устройствах с большими экранами все события будут позиционироваться абсолютно.
@media only screen and (min-width: 800px) { .cd-schedule .events { float: left; width: 100%; } .cd-schedule .events .events-group { width: 20%; float: left; } .cd-schedule .events .single-event { position: absolute; z-index: 3; /* top position and height will be set using js */ width: calc(100% + 2px); left: -1px; } }
Анимация .event-modal
реализована через jQuery и CSS Трансформациях.
Обработка событий
Планировщик будем реализовывать в объекте SchedulePlan
.
function SchedulePlan( element ) { this.element = element; this.timeline = this.element.find('.timeline'); //... this.eventsWrapper = this.element.find('.events'); this.eventsGroup = this.eventsWrapper.find('.events-group'); this.singleEvents = this.eventsGroup.find('.single-event'); //.. this.scheduleReset(); this.initEvents(); }
В функции scheduleReset()
мы займёмся позиционированием событий на шкале времени.
var self = this; this.singleEvents.each(function(){ //place each event in the grid -> need to set top position and height var start = getScheduleTimestamp($(this).attr('data-start')), //getScheduleTimestamp converts hh:mm to timestamp duration = getScheduleTimestamp($(this).attr('data-end')) - start; var eventTop = self.eventUnitHeight*(start - self.timelineStart)/self.timelineUnitDuration, eventHeight = self.eventUnitHeight*duration/self.timelineUnitDuration; $(this).css({ top: (eventTop -1) +'px', height: (eventHeight+1)+'px' }); });
При клике по событию сработает функция jQuery load()
, чтобы подгрузить данные.
SchedulePlan.prototype.openModal = function(event) { var self = this; var mq = self.mq(); this.animating = true; //update event name and time this.modalHeader.find('.event-name').text(event.find('.event-name').text()); this.modalHeader.find('.event-date').text(event.find('.event-date').text()); this.modal.attr('data-event', event.parent().attr('data-event')); //update event content this.modalBody.find('.event-info').load(event.parent().attr('data-content')+'.html .event-info > *', function(data){ //once the event content has been loaded self.element.addClass('content-loaded'); }); this.element.addClass('modal-is-open'); if( mq == 'mobile' ) { self.modal.one(transitionEnd, function(){ self.modal.off(transitionEnd); self.animating = false; }); } else { //change modal height/width and translate it self.modal.css({ top: eventTop+'px', //this is the selected event top position left: eventLeft+'px', //this is the selected event left position height: modalHeight+'px', //this is the modal final height width: modalWidth+'px', //this is the modal final width }); transformElement(self.modal, 'translateY('+modalTranslateY+'px) translateX('+modalTranslateX+'px)'); //set modalHeader width self.modalHeader.css({ width: eventWidth+'px', //this is the selected event width }); //set modalBody left margin self.modalBody.css({ marginLeft: eventWidth+'px', }); //change modalBodyBg height/width and scale it self.modalBodyBg.css({ height: eventHeight+'px', width: '1px', }); transformElement(self.modalBodyBg, 'scaleY('+HeaderBgScaleY+') scaleX('+BodyBgScaleX+')'); //change modal modalHeaderBg height/width and scale it self.modalHeaderBg.css({ height: eventHeight+'px', width: eventWidth+'px', }); transformElement(self.modalHeaderBg, 'scaleY('+HeaderBgScaleY+')'); self.modalHeaderBg.one(transitionEnd, function(){ //wait for the end of the modalHeaderBg transformation and show the modal content self.modalHeaderBg.off(transitionEnd); self.animating = false; self.element.addClass('animation-completed'); }); } };
Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: https://codyhouse.co/gem/schedule-template/
Перевел: Станислав Протасевич
Урок создан: 9 Января 2017
Просмотров: 5339
Правила перепечатки
5 последних уроков рубрики "CSS"
-
Забавные эффекты для букв
Небольшой эффект с интерактивной анимацией букв.
-
Реализация забавных подсказок
Небольшой концепт забавных подсказок, которые реализованы на SVG и anime.js. Помимо особого стиля в примере реализована анимация и трансформация графических объектов.
-
Анимированные буквы
Эксперимент: анимированные SVG буквы на базе библиотеки anime.js.
-
Солнцезащитные очки от первого лица
Прикольный эксперимент веб страницы отображение которой осуществляется “от первого лица” через солнцезащитные очки.
-
Раскрывающаяся навигация
Экспериментальный скрипт раскрывающейся навигации.