Страницы

Поиск по вопросам

понедельник, 4 марта 2019 г.

feof() и пустой файл

Имеется пустой файл (0 байт). Почему feof() не возвращает true?


Ответ

Представьте, что поток чтения - это чёрный ящик (а в общем так оно и есть). Только попробовав прочитать очередной байт и получив шиш с маслом, узнаешь, что файл кончился...

Как скопировать данные из tableWidget в tableWidget_1?

Добрый день, создал программу которая забирает данные из БД и выводит их в qtableWidget_1 в котором выведенные строки можно отметить с помощью Check Box. Рядом есть qtablewidget_2 куда отмеченные строки нужно скопировать, подскажите как такое можно реализовать ? Сам код вывода запроса из БД.
void MainWindow::on_pushButton_2_clicked() {
ui->tableWidget->setColumnCount(5); // Указываем число колонок ui->tableWidget->setShowGrid(true); // Включаем сетку ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); // Разрешаем выделение только одного элемента ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);// Разрешаем выделение построчно //ui->tableWidget->setHorizontalHeaderLabels(headers);// Устанавливаем заголовки колонок ui->tableWidget->horizontalHeader()->setStretchLastSection(false);// Растягиваем последнюю колонку на всё доступное пространство // ui->tableWidget->hideColumn(0);// Скрываем колонку под номером 0 ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);//Запрещаем редактировать данные в полях таблицы // Создаём запрос для для выборки записей из базы данных
QSqlQuery query = QSqlQuery(db); if (!query.exec("SELECT * FROM mytable")) { QMessageBox::information(this,"Окно информации","Не удалось выполнить запрос возможно нет соеденеия с базой данных."); qDebug() << query.lastError().databaseText(); qDebug() << query.lastError().driverText(); return;
}else{
/* Выполняем заполнение QTableWidget записями с помощью цикла * */ for(int i = 0; query.next(); i++){
ui->tableWidget->insertRow(i);// Вставляем строку
/* Устанавливаем в первую колонку id забирая его из результата SQL-запроса * Эта колонка будет скрыта * */ ui->tableWidget->setItem(i,0, new QTableWidgetItem(query.value(0).toString()));
QTableWidgetItem *item = new QTableWidgetItem();// Создаём элемент, который будет выполнять роль чекбокса item->data(Qt::CheckStateRole);
/* Проверяем, на статус нечетности, если нечетное устройство, то * выставляем состояние чекбокса в Checked, иначе в Unchecked * */ if(query.value(1).toInt() == 1){ item->setCheckState(Qt::Checked); } else { item->setCheckState(Qt::Unchecked); }
ui->tableWidget->setItem(i,0, item);// Устанавливаем чекбокс во вторую колонку
// Забираем все данные из результата запроса и устанавливаем в остальные поля ui->tableWidget->setItem(i,1, new QTableWidgetItem(query.value(1).toString())); ui->tableWidget->setItem(i,2, new QTableWidgetItem(query.value(2).toString())); ui->tableWidget->setItem(i,3, new QTableWidgetItem(query.value(3).toString())); ui->tableWidget->setItem(i,4, new QTableWidgetItem(query.value(4).toString())); ui->tableWidget->setItem(i,5, new QTableWidgetItem(query.value(5).toString()));
}
ui->tableWidget->resizeColumnsToContents(); db.close(); }
}


Ответ

Задача решена:
ui->tableWidget_1->setItem(i,1, new QTableWidgetItem(ui->tableWidget->item(i, 1)->text()));
как вариант можно использовать так же данную конструкцию
ui->tableWidget_1->setItem(i,1, ui->tableWidget->item(i, 1)->clone());

Дублирование файлов в ветках

При создании файла/директории в локальном репозитории git, файл копируется во все ветки, а не в ту в которой создается (через консоль и редактор). Как этого избежать?


Ответ

вообще, создаёте вы файлы/каталоги не в репозитории/хранилище, а в рабочем каталоге (working directory/tree).
в хранилище файлы (точнее, их содержимое) «попадают» только после команды git commit
при переключении между ветками/коммитами программа git «вычисляет», какие изменения следует внести в рабочий каталог:
файлы/каталоги, которые есть в текущей ветке/коммите, но отсутствуют в той, на которую переключаетесь, удаляются; файлы/каталоги, которых нет в текущей ветке/коммите, но которые присутствуют в той, на которую переключаетесь, извлекаются из содержимого хранилища; аналогично извлекается и содержимое файлов, которое отличается: в текущей ветке/коммите — одно, в той, на которую переключаетесь — другое.
все же остальные файлы/каталоги при переключении между ветками/коммитами вообще никак не будут затронуты.
это относится и к тем файлам/каталогам, которых нет ни в текущей ветке/коммите, ни в той, на которую переключаетесь.

Как этого избежать?
пока вы не сохранили эти файлы/каталоги внутри хранилища, программа git, по крайней мере, выполняя команду checkout, не будет «касаться» таких «неотслеживаемых» файлов/каталогов внутри рабочего каталога.
так что краткий ответ: никак не избежать. так задумано.

Как получить hwnd по имени процесса?

Как получить hwnd окна по имени процесса. Вот например я могу получить hwnd по имени окна
hwnd = win32gui.FindWindow(None, "Notepad")
Можно ли так же легко получить hwnd по имени процесса?


Ответ

Совсем просто не получится, потому что:
Может быть несколько процессов с одним именем (например, можно открыть несколько окон Блокнота). У процесса может быть несколько окон
Поэтому сначала нужно получить список процессов с заданными именем файла (или для простоты первый попавшийся процесс, подходящий по этому условию), потом список окон для данного процесса (процессов).
1. Получаем список процессов, у которых имя файла равно notepad.exe
Можно воспользоваться пакетом psutil
import psutil
# Список процессов с именем файла notepad.exe: notepads = [item for item in psutil.process_iter() if item.name() == 'notepad.exe'] print(notepads) # []
# Просто pid первого попавшегося процесса с именем файла notepad.exe: pid = next(item for item in psutil.process_iter() if item.name() == 'notepad.exe').pid # (вызовет исключение StopIteration, если Блокнот не запущен)
print(pid) # 4416
2. Получаем список окон процесса с заданным pid
Чтобы получить список окон процесса, можно воспользоваться функцией EnumWindows
Например, нужно получить все окна процесса с ID 4416:
import win32gui import win32process
def enum_window_callback(hwnd, pid): tid, current_pid = win32process.GetWindowThreadProcessId(hwnd) if pid == current_pid and win32gui.IsWindowVisible(hwnd): windows.append(hwnd)
# pid = 4416 # pid уже получен на предыдущем этапе windows = []
win32gui.EnumWindows(enum_window_callback, pid)
# Выводим заголовки всех полученных окон print([win32gui.GetWindowText(item) for item in windows])
Вывод:
['Безымянный — Блокнот']
Если в Блокноте открыть еще настройку параметров страницы, то список будет такой:
['Параметры страницы', 'Безымянный — Блокнот']

Сохранить картику с Bitmap C#

Мне нужно из Bitmap создать картинку формата *.png или *.jpg Помогите!


Ответ

Помог метод Image.Save (String, ImageFormat)
Bitmap PictureImg = new Bitmap(2560, 1920);
PictureImg.Save("img.png", System.Drawing.Imaging.ImageFormat.Png);

Gitlab pages для своего Gitlab

Gitlab pages позволяет публиковать index.html туда.
Есть свой развернутый GitLab последней версии. что мне нужно делать, чтобы я смог использовать свой основной DNS и опубликовал также сайт?


Ответ

Нужно установить и запустить GitLab Pages daemon — это их собственный вебсервер. Он может быть установлен как на одном хосте с гитлабом, так и на отдельном.
Поставляется он в пакете Omnibus или отдельно.
Подробные инструкции есть в GitLab Pages configuration
Также можно установить и сконфигурировать с помощью роли Ansible debops.ansible-gitlab

Opencv python конвертация изображения

После выполнения, кода я получаю черно-белое изображение, которое состоит из двух измерений (ширина высота) и само значение от 0 до 255 - от черного до белого. Для дальнейшего использования мне необходимо конвертировать его в rgb8. Например функция cv2.floodFill не принимает изображение, которое я получил. Вот сам код:
import sys import cv2 import numpy as np import time from matplotlib import pyplot as plt
img = cv2.imread('2.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # noise removal kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations = 2) # sure background area sure_bg = cv2.dilate(opening, kernel, iterations=3) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.55 * dist_transform.max(), 255, 0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1
markers = markers+10 # Now, mark the region of unknown with zero markers[unknown == 255] = 0 markers = cv2.watershed(img, markers) img[markers == -1] = [255, 0, 0] cv2.imwrite('6.jpg', markers)
Есть ли возможность конвертировать markers в нормальное изображение?


Ответ

Команда
np.ndarray.astype(np.uint8)
помогла

Как положить в сессию не весь объект а только 3 поля?

Здравствуйте
У меня в форме авторизации после всех проверок идет вот такая запись
$_SESSION['user'] = $user;
в сессию сохраняется весь объект $user, то есть логин, пароль и полностью все данные с записи таблицы. если записать так:
$_SESSION['user'] = $user['id'];
в сессию сохраниться только его id
Вопрос: как сохранить в сессию id,login и image? как правильно нужно написать?
прошу помощи в реализации.


Ответ

Например так:
$_SESSION['user'] = [ 'id' => $user['id'], 'login' => $user['login'], 'image' => $user['image'], ];

Как работает SSL в мобильных приложениях?

В браузере все понятно, у него заранее есть список вшитых сертификатов CA, которыми он проверяет сертификат сервера... Но как происходит проверка в мобильных приложениях? Или, допустим, когда я отправляю запрос, допустим, через BurpSuite?


Ответ

Общие принципы SSL (а точнее, инфраструктуры ключей) продолжают работать и в контексте мобильных приложений. Набор CA (или, по-русски, ЦС – центров сертификации):
может быть размещен в ОС (чаще всего, т. к. он используется по умолчанию [обычно]). может поставляться с приложением (что не такая уж редкость, см. Firefox). может отсутствовать вовсе, если клиент заранее знает публичный ключ сервера сам, или может попросить пользователя проверить отпечаток ключа в интерфейсе (привет, SSH!), или просто плевать хотел на безопасность (и такое бывает! ¯\_(ツ)_/¯).
Может использоваться несколько вариантов сразу. Например, Яндекс.Браузер использует гибрид: он рассчитывает на системное хранилище, но отпечатки (хэши) сертификатов ЦСов оттуда сравнивает с известными ему (за уточнение механизма спасибо Abyx). Их немного, поэтому зашить в бинарник не проблема. Таким образом ЯБ пытается предупреждать ситуации, в которых соединение пользователя компрометируется через сторонний ЦС, установленный в систему без его ведома.

Так что, как видите, SSL довольно хорошо гнётся под разные ситуации. Но реально этим богатством редко пользуются.
В подавляющем большинстве случаев сервер имеет ключ, заверенный известным ЦС, а клиент имеет только пачку известных ЦС в ОС. Сервер предоставляет доказательства, указывающие через известные ЦС на подлинность своего ключа. Так клиент понимает, что это тот самый сервер.

Расчет диапазона значений между двумя ползунками

Есть имитация input type="range" на javascript.
function Range(container) { this.container = container; if (!this.container) return; this.inputMin = container.querySelector('[data-type=input-min]'); this.inputMax = container.querySelector('[data-type=input-max]'); this.minValue = parseFloat(container.querySelector('[data-type=min-val]').textContent.replace(/\s/g, '')); this.maxValue = parseFloat(container.querySelector('[data-type=max-val]').textContent.replace(/\s/g, '')); this.inner = container.querySelector('[data-type=range-inner-element]'); this.valuesElem = container.querySelector('[data-type=range-element]'); this.minBtn = container.querySelector('[data-type=min-btn]'); this.maxBtn = container.querySelector('[data-type=max-btn]'); //console.log(this); this.init(); } Range.prototype.drag = function(event) { function move(event) { var left = event.pageX - elemX - boxX; if (elem == this.minBtn) { this.inner.style.left = elem.offsetLeft + elem.offsetWidth / 2 + 'px'; if (left < 0) { left = 0; } if (left > this.maxBtn.offsetLeft - elem.offsetWidth) { left = this.maxBtn.offsetLeft - elem.offsetWidth; } } else if (elem == this.maxBtn) { this.inner.style.right = elem.offsetLeft - elem.offsetWidth / 2 + 'px'; if (left < this.minBtn.offsetLeft + elem.offsetWidth) { left = this.minBtn.offsetLeft + elem.offsetWidth; } if (left > this.valuesElem.offsetWidth - elem.offsetWidth) { left = this.valuesElem.offsetWidth - elem.offsetWidth; } } elem.style.left = left + 'px'; this.inner.style.width = this.maxBtn.offsetLeft - this.minBtn.offsetLeft + 'px'; } function removeMove() { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', removeMove); } if (event.target == this.minBtn || event.target == this.maxBtn) { var elem = event.target; var elemX = event.pageX - elem.getBoundingClientRect().left; var boxX = this.valuesElem.getBoundingClientRect().left; var coord = event.target.offsetLeft; move = move.bind(this); document.addEventListener('mousemove', move); document.addEventListener('mouseup', removeMove); event.target.ondragstart = function() { return false; }; } } Range.prototype.setValue = function() { this.inputMin.value = this.minValue; this.inputMax.value = this.maxValue; } Range.prototype.init = function() { this.inner.style.left = this.minBtn.offsetLeft + this.minBtn.offsetWidth / 2 + 'px'; this.inner.style.right = this.maxBtn.offsetLeft - this.maxBtn.offsetWidth / 2 + 'px'; this.setValue(); this.valuesElem.addEventListener('mousedown', this.drag.bind(this)); } var range = new Range(document.querySelector('[data-type=range]')); .filters_section_list { width: 300px; list-style: none } .filters_section_item .range { height: 6px; background-color: #AEAEAE; border-radius: 4px; position: relative; } .filters_section_item .range_inner { height: inherit; background-color: #FD2016; } .filters_section_item .range_btn { width: 18px; height: 18px; border-radius: 50%; box-shadow: 0 0 3px rgba(0, 0, 0, 0.6); position: absolute; top: -7px; background-color: #fff; cursor: pointer; } .filters_section_item .range_inner { position: absolute; width: 100%; } .filters_section_item .range_btn[data-type=min-btn] { left: 0; } .filters_section_item .range_btn[data-type=max-btn] { left: 100%; } .filters_section_item .values { overflow: hidden; margin-top: 40px; } .filters_section_item .values .min-value { float: left; width: 35%; text-align: left; padding-bottom: 14px; padding-left: 10px; padding-right: 10px; border-bottom: 1px solid #ACACAC; } .filters_section_item .values .max-value { float: right; width: 35%; text-align: right; padding-bottom: 14px; padding-left: 10px; padding-right: 10px; border-bottom: 1px solid #ACACAC; }

  • 0 1000000

Подскажите алгоритм как рассчитывать теперь диапазон значений между ползунками при их перемещении?


Ответ

function Range(container) { this.container = container; if (!this.container) return; this.inputMin = container.querySelector('[data-type=input-min]'); this.inputMax = container.querySelector('[data-type=input-max]'); this.minValue = parseFloat(container.querySelector('[data-type=min-val]').textContent.replace(/\s/g, '')); this.maxValue = parseFloat(container.querySelector('[data-type=max-val]').textContent.replace(/\s/g, '')); this.inner = container.querySelector('[data-type=range-inner-element]'); this.valuesElem = container.querySelector('[data-type=range-element]'); this.minBtn = container.querySelector('[data-type=min-btn]'); this.maxBtn = container.querySelector('[data-type=max-btn]'); //console.log(this); this.init(); } Range.prototype.drag = function(event) { function move(event) { var left = event.pageX - elemX - boxX; var target; if (elem == this.minBtn) { this.inner.style.left = elem.offsetLeft + elem.offsetWidth / 2 + 'px'; if (left < 0) { left = 0; } if (left > this.maxBtn.offsetLeft - elem.offsetWidth) { left = this.maxBtn.offsetLeft - elem.offsetWidth; } target = this.container.querySelector('[data-type=min-val]'); } else if (elem == this.maxBtn) { this.inner.style.right = elem.offsetLeft - elem.offsetWidth / 2 + 'px'; if (left < this.minBtn.offsetLeft + elem.offsetWidth) { left = this.minBtn.offsetLeft + elem.offsetWidth; } if (left > this.valuesElem.offsetWidth - elem.offsetWidth) { left = this.valuesElem.offsetWidth - elem.offsetWidth; } target = this.container.querySelector('[data-type=max-val]'); } elem.style.left = left + 'px'; this.inner.style.width = this.maxBtn.offsetLeft - this.minBtn.offsetLeft + 'px'; target.innerText = this.minValue + (this.maxValue - this.minValue)*(left/this.valuesElem.offsetWidth); } function removeMove() { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', removeMove); } if (event.target == this.minBtn || event.target == this.maxBtn) { var elem = event.target; var elemX = event.pageX - elem.getBoundingClientRect().left; var boxX = this.valuesElem.getBoundingClientRect().left; var coord = event.target.offsetLeft; move = move.bind(this); document.addEventListener('mousemove', move); document.addEventListener('mouseup', removeMove); event.target.ondragstart = function() { return false; }; } } Range.prototype.setValue = function() { this.inputMin.value = this.minValue; this.inputMax.value = this.maxValue; } Range.prototype.init = function() { this.inner.style.left = this.minBtn.offsetLeft + this.minBtn.offsetWidth / 2 + 'px'; this.inner.style.right = this.maxBtn.offsetLeft - this.maxBtn.offsetWidth / 2 + 'px'; this.setValue(); this.valuesElem.addEventListener('mousedown', this.drag.bind(this)); } var range = new Range(document.querySelector('[data-type=range]')); .filters_section_list { width: 300px; list-style: none } .filters_section_item .range { height: 6px; background-color: #AEAEAE; border-radius: 4px; position: relative; } .filters_section_item .range_inner { height: inherit; background-color: #FD2016; } .filters_section_item .range_btn { width: 18px; height: 18px; border-radius: 50%; box-shadow: 0 0 3px rgba(0, 0, 0, 0.6); position: absolute; top: -7px; background-color: #fff; cursor: pointer; } .filters_section_item .range_inner { position: absolute; width: 100%; } .filters_section_item .range_btn[data-type=min-btn] { left: 0; } .filters_section_item .range_btn[data-type=max-btn] { left: 100%; } .filters_section_item .values { overflow: hidden; margin-top: 40px; } .filters_section_item .values .min-value { float: left; width: 35%; text-align: left; padding-bottom: 14px; padding-left: 10px; padding-right: 10px; border-bottom: 1px solid #ACACAC; } .filters_section_item .values .max-value { float: right; width: 35%; text-align: right; padding-bottom: 14px; padding-left: 10px; padding-right: 10px; border-bottom: 1px solid #ACACAC; }

  • 0 1000000

UP: Для тех, кто слишком давно учился в школе:
left // расстояние от минимального значения до текущего значения в пикселях. // Всё, что нам нужно сделать - это перевести его из пикселей в шкалу, заданную минимальным и максимальным значением - this.valuesElem.offsetWidth //размер шкалы в пикселях scale = maxValue - minValue; // размер шкалы в еденицах шкалы percent = left/offsetWidth // отношение отрезка значения к размеру шкалы (безразмерное, тк пиксели делим на пиксели - получаем разы) value = minValue + scale*percent; // осталось домножить эти разы на размер шкалы в нужных единицах и прибавить к значению, с которого шкала начинается. // Выкидываем лишние промежуточные переменные, получается - value = this.minValue + (this.maxValue - this.minValue)*(left/this.valuesElem.offsetWidth);

java Calendar возвращает неправильный день недели

При программировании на java столкнулся с проблемой, что календарь не всегда правильно возвращает день недели. Пробовал использовать как Calendar, так и GregorianCalendar, но результат одинаковый.
Для примера:
GregorianCalendar calendar1 = new GregorianCalendar(196, 0, 1); System.out.println(calendar1.get(GregorianCalendar.DAY_OF_WEEK));
Результатом в выводе будет 5, хотя по календарю: 01 января 196 - пятница, а значит мы должны были получить значение 6. Такая же проблема с годами:
1036 (1 января - воскресенье, а возвращает 5) 1316 (1 января - среда, а возвращает 5) 1456 (1 января - вторник, а возвращает 5)
и др.
Но иногда возвращает и правильные значения. Например:
GregorianCalendar calendar2 = new GregorianCalendar(1600, 0, 1); System.out.println(calendar2.get(GregorianCalendar.DAY_OF_WEEK));
вернет 7, и по календарю это суббота.


Ответ

Отвечу сам на собственный вопрос.
Такая неразбериха с календарями получилась из-за отличий Григорианского и Юлианского календарей. В Юлианском календаре високосный год наступает каждый год, который кратный 4, а в Григорианском - високосными считаются года, которые делятся на 4, но не кратные 100 (за исключением годов, которые делятся на 400). Это означает, что постепенно разница между этими календарями увеличивается на 3 дня каждые 400 лет.
Т.к. на Григорианский практически все страны перешли только с 1582 года, то до этого времени все ресурсы и языки программирования (помимо Java сравнивал еще с Python) по-своему высчитывают этот период.
Что касается Java, то, как я понял, до 1582 года включительно в языке используется Юлианский календарь, а с 1583 - Григорианский.

Передвижение по svg (path)

Как организовать движение картинок по path друг за другом, как угодно, только не друг на друге (задать координаты в цикле не получилось, где-то ошибаюсь..). Фрагмент кода:
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var W = window.innerWidth, H = window.innerHeight; canvas.width = W; canvas.height = H; var angle = 0; var currentAngle = 0; var TO_RADIANS = Math.PI / 180; var particles = []; var counter = 0; var svg = document.getElementById("k9");//path из svg var straightLength = svg.getTotalLength(); function Particle() { this.radius = 20; this.x = svg.getPointAtLength(straightLength).x; this.y = svg.getPointAtLength(straightLength).y; this.move = function() { for ( var g = 0; g < particles.length; g++){ this.x = svg.getPointAtLength(counter*straightLength).x; this.y = svg.getPointAtLength(counter*straightLength).y; } counter+=0.0003;//так картинки передвигаются по path друг на друге, как организовать нечто вроде "паровозика"? Перебрал много вариантов в цикле, но ничего не вышло.. context.beginPath(); context.globalCompositeOperation = "source-over"; context.save(); context.translate(this.x, this.y); context.rotate(Gangle * TO_RADIANS); var image = new Image(); image.src = 'img/bag.png'; context.drawImage(image,20, -20, 40, 40); context.restore(); angle+=0.1; } }; for (var i = 0; i < 10; i++) { var particle = new Particle(); particles.push(particle); } function animate() { context.clearRect(0, 0, canvas.width, canvas.height); for (var i = 0; i < particles.length; i++) { particles[i].move(); } requestAnimFrame(animate); } animate();


Ответ

Как организовать движение картинок по path друг за другом
Для решения этой задачи необходимо нарисовать path в векторном редакторе или вручную.

Движение вдоль этого пути реализуется командой
С привязкой объектов движения к пути посредством ID этого пути с помощью команды Фрагмент кода:
` `
Начало движения при наведении на кнопку "Start" begin="startButton.mouseover" Окончание анимации при наведении на кнопку "Stop" end="stopGreen.mouseover"
Далее добавляются еще два подобных блока кода для двух других объектов движения.
Для реализации движения друг за другом нескольких объектов, задается пауза до начала анимации для второго и третьего шарика. begin="startButton.mouseover+0.25s"
Необязательные украшательства:
Добавлены маркеры для указания направления движения, паттерн фона и блок радиокнопок остановки объектов движения. Ниже пример кода:
Start Stop
Анимация адаптивна, пробуйте изменять размер окна браузера.
Вариант #2
Объекты движения заменены на более сложные (ведьмы на метлах) Изменена траектория движения (заменяем патч Start Stop
Начало анимации при наведении на кнопку "Start"
Приостановка объектов анимации при наведении на соответствующую радиокнопку.

Как сжать видео под размер экрана.

Красным это видео. Черным это размер экрана телефона. Я использую SurfaceView.
Как мне подогнать видео под размер экрана. орентировываясь по ширине Экрана телефона. Сохраняю пропорции.
В ImageView все просто. Добавил картинку и она сама с сохранением пропорций отображается.


Ответ

Если вы хотите использовать именно SurfaceView, то стоит сделать так:
Например у нас есть такая разметка:

Подключаем необходимые нам элементы:
surfaceViewFrame = (SurfaceView) findViewById(R.id.surfaceViewFrame); player = new MediaPlayer(); player.setDisplay(holder); А теперь немного расчетов добавим в ваш MediaPlayer в onPreparedListener и пересчитаем высоту и ширину видео фрагмента в соответствии с текущими размерами экрана, избежав растягивания.
player.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared (MediaPlayer mp){ int videoWidth = player.getVideoWidth(); int videoHeight = player.getVideoHeight(); float videoProportion = (float) videoWidth / (float) videoHeight; int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); float screenProportion = (float) screenWidth / (float) screenHeight; android.view.ViewGroup.LayoutParams lp = surfaceViewFrame.getLayoutParams();
if (videoProportion > screenProportion) { lp.width = screenWidth; lp.height = (int) ((float) screenWidth / videoProportion); } else { lp.width = (int) (videoProportion * (float) screenHeight); lp.height = screenHeight; } surfaceViewFrame.setLayoutParams(lp);
if (!player.isPlaying()) { player.start(); } } });

Атрибут is в HTML

Недавно читал статьи по созданию собственных тегов в HTML и натолкнулся на неизвестный мне атрибут is. Статья: https://learn.javascript.ru/...
Зачем этот атрибут? Можно ли его использовать, к примеру, для вставки иконок (..)? Насколько он валиден в старых браузерах?


Ответ

is является частью W3C спецификации и используется для создания пользовательских элементов HTML с пользовательским поведением.
В частности, is используется при расширении свойств встроенного элемента, например ,

Как сложить два массива в массиве объектов

Есть массив в котором находятся объекты с массивом данных.
Нужно получить сумму всех элементов массива объектов и добавить каждую сумму в объект, затем нужно получить сумму двух объектов и так же добавить в объект.
Так же нужно сложить элементы из массива первого объекта с элементами из массива второго эл и добавить в массив с суммой каждого свойства т.е объект а) [1,2,3] и объект б) [4,5,6] сложить их и получить на выходе [ 5,7,9]
Смог получить сумму двух элементов массива но вариант оказался весьма деревянным, т.к привязан к свойству первого объекта
function chartSumm(arr) { let obj, firstArr = [], lastArr = [], sumArray = [] arr.forEach(function(item, index) { for (let el in item.data) { if (item.label === 'Эккономия на аннуляции') { firstArr = item.data; } else { lastArr = item.data } } }); let firstObjSum = firstArr.reduce(function(prev, curr, index) { return prev + curr }); let twoObjSum = lastArr.reduce(function(prev, curr, index) { return prev + curr }); obj = { 'Цена у стойки': firstObjSum, 'Аннуляция без штрафа': twoObjSum, 'Общая экономия': firstObjSum + twoObjSum }; console.log(obj) } chartSumm([{ label: 'Эккономия на аннуляции', backgroundColor: '#ef9d4d', data: [1000, 400, 1500, 1500, 3000, 4000] }, { label: 'Экономия на цене у стойки', backgroundColor: '#476e8f', data: [1170, 460, 2000, 2500, 2700, 4000] }, ])


Ответ

Так как лейблы разные, то их в любом случае придется прописывать. Чтобы сделать функцию более универсальной ( и не для только лишь 2 обхектов) можно вынести лейбл результата в объект. Я так же вынес лейбл Общая Экономия отдельно из функцию, но можно задавать его и внутри.
function chartSumm(arr, sumLabel, elementSumLabel) { var result = {}; result[sumLabel] = 0; result[elementSumLabel] = [0, 0, 0, 0, 0, 0] arr.forEach(function(item, index) { result[item.resultLabel] = 0; for (var i = 0; i < item.data.length; i++) { result[elementSumLabel][i] += item.data[i]; result[item.resultLabel] += item.data[i] } result[sumLabel] += result[item.resultLabel]; }); return result; } var info = chartSumm([{ label: 'Эккономия на аннуляции', resultLabel: 'Цена у стойки', backgroundColor: '#ef9d4d', data: [1000, 400, 1500, 1500, 3000, 4000] }, { label: 'Экономия на цене у стойки', resultLabel: 'Аннуляция без штрафа', backgroundColor: '#476e8f', data: [1170, 460, 2000, 2500, 2700, 4000] }, ], 'Общая экономия', 'Сумма элементов'); console.log(info);

Как сделать так, чтобы переходить между страницами без перезагрузки, но так чтобы url страницы менялся?

Как сделать так, чтобы переходить между страницами без перезагрузки, но так чтобы url страницы менялся?


Ответ

В HTML документе метод history.pushState() добавляет новое состояние в историю браузера
Метод pushState() принимает 3 параметра: state, title (который в данный момент игнорируется), URL. Давайте рассмотрим каждый параметр подробнее:
State — JavaScript объект, который связан с новой записью в истории браузера, созданной при помощи pushState(). Всякий раз, когда пользователь перемещается на новое состояние истории браузера при помощи таких функций, как, например history.back() или history.go(), срабатывает событие popstate, а в объект event передаётся свойство state. Title — в данный момент Firefox игнорирует данный параметр. Тем не менее аргумент может передаваться. Передача пустой строки вместо title должна быть безопасной с учётом будущих изменений метода. В качестве альтернативы можно передавать title в объекте state и использовать его оттуда. URL — URL новой записи в истории браузера передаётся в этом аргументе. Обратите внимание, что браузер не будет пытаться загрузить данный URL после вызова pushState(), но эту попытку можно сделать позднее, например, после перезапуска браузера. Новый URL не обязательно должен быть абсолютным. Если он относительный, тогда он образуется от текущего URL.
var state = { 'page_id': 1, 'user_id': 5 }; var title = 'Hello World'; var url = 'hello-world.html';
history.pushState(state, title, url);

Функция блокировка изменения размера окна в Qt

Существует ли функция в PyQt5 блокировка расширения окна как в tkinter .resizable(False, False)?
Пример:
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import *
app = QApplication(sys.argv) root = QMainWindow() root.resize(500, 700) root.setWindowTitle('Детские кружки') root.show()
sys.exit(app.exec())


Ответ

Функцией setFixedSize(x, y)
import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import *
app = QApplication(sys.argv) root = QMainWindow() root.setFixedSize(500, 700) root.setWindowTitle('Детские кружки') root.show()
sys.exit(app.exec())

Ошибка “non-static variable this cannot be referenced from a static context”

Учусь программировать по учебнику и попытался понять принципы ООП. Написал следующий код в Main.java:
public class Main {
public static void main (String [] args) {
Dog chakki = new Dog(); Dog muhtar = new Dog(); muhtar.bark(); chakki.setAge(12); System.out.println(muhtar.getAge()); System.out.println(chakki.getAge()); } }
И в той же директории создал Dog.java и код из неё:
public class Dog {
private static int age = 10;
public static void bark() { System.out.println("Gaf Gaf"); }
public static int getAge() { return age; }
public static void setAge(int age) { this.age = age; } }
И когда пытался скомпилировать в командной строке выдаёт ошибку:
.\Dog.java:19: error: non-static variable this cannot be referenced from a static context this.age = age;
^ 1 error
Вопросы:
Почему так происходит? И когда я пытался скомпилировать без методов, просто меняя значение age напрямую, то у меня менялись значения обоих объектов muhtar и chakki, то есть они были равны последнему значению. Отсюда и вопрос почему значения переменных двух объектов(muhtar, chakki) были равны последнему измененному значению. Ведь я создал класс Dog и объявил 2 объекта(muhtar, chakki), и думал что значения будут для этих объектов отдельными и разными. Но, видимо, я что-то не так понял.
Помогите разобраться и понять)))


Ответ

Чем отличается static и не-static
Когда вы объявляете переменную как static, она принадлежит всему классу целиком, а не каждому объекту. И существует эта переменная в единственном экземпляре, сколько бы ни было экземпляров класса.
Вот это — возраст всех собак вообще. У вас на двух собак — один возраст. Не годится, потому что у собак бывают разные возраста.
private static int age = 10;
А этот метод устанавливает возраст всех собак разом:
public static void setAge...
А нужен возраст каждой отдельно взятой собаки из класса собак:
private int age = 10;
Причины ошибки “non-static variable this cannot be referenced from a static context”
Далее: this.age означает значение переменной age в данном конкретном (this) экземпляре класса. Но вы выполняете этот код в статическом методе, принадлежащем классу. Поскольку метод относится ко всему классу, конкретные экземпляры ему неизвестны.
Поэтому возникает ошибка “non-static variable this cannot be referenced from a static context”. Дословно: вы обращаетесь к нестатической переменной, но делаете это без уважения из статического контекста, и это не имеет смысла.

Как сделать чтоб NavigationView не затеняла основной экран

Добрый день. При открытии NavigationView основной экран затеняется, можно ли как нибудь отключить этот эффект?


Ответ

Согласно en-SO надо так:
mDrawerLayout.setScrimColor(getResources().getColor(android.R.color.transparent));

Присвоить значение выше прокси

В следующем коде прокси с get-перехватчиком в прототип (__proto__) объекта. Соответственно, по схеме чтения свойств в js, до перехватчика очередь доходит только в том случае, если в непосредственно в объекте такого свойства нет. После присваивания свойство появляется в объекте и до прокси дело не доходит. Это так задумано.
var x = Object.create(new Proxy({}, { get(obj, key) { if (typeof key !== 'symbol') { console.log('Reading a nonexisting property: ' + key); } } })); var temp; console.log(1, Object.prototype.hasOwnProperty.call(x, 'a')); temp = x.a; console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp); temp = x.a; console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp); x.a = 12; console.log(4, Object.prototype.hasOwnProperty.call(x, 'a')); temp = x.a; console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp); .as-console-wrapper.as-console-wrapper { max-height: 100vh }
Теперь я в этот код добавляю перехватчик set
var x = Object.create(new Proxy({}, { get(obj, key) { if (typeof key !== 'symbol') { console.log('Reading a nonexisting property: ' + key); } }, set(obj, key, val, receiver) { console.log('Assigning a property: ' + key); Reflect.set(obj, key, val); // Inside of proxy, not outside //Reflect.set(receiver, key, val); // Infinite recursion return true; } })); var temp; console.log(1, Object.prototype.hasOwnProperty.call(x, 'a')); temp = x.a; console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp); temp = x.a; console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp); x.a = 12; console.log(4, Object.prototype.hasOwnProperty.call(x, 'a')); temp = x.a; console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp); .as-console-wrapper.as-console-wrapper { max-height: 100vh }
Проблема в том, что не получается записать свойство в сам объект - свойство записывается либо в тот объект, который находится внутри прокси, либо всё уходит в рекурсию метода set. Как это можно исправить? Т. е. результат должен быть такой же, как в предыдущем сниппете, только с появлением строки Assigning a property: a
PS: Этот вопрос на английском.


Ответ

Перевод ответа от @Bergi
Для создания свойства надо воспользоваться Object.defineProperty (или Reflect.defineProperty). Просто попытка установить свойство присваиванием или Reflect.set будет вызывать проход по цепочке прототипов и попадать в перехватчик set, что приведёт к бесконечной рекурсии.
new Proxy({}, { get(target, key) { if (typeof key !== 'symbol') { console.log('Reading a nonexisting property: ' + key); } }, set(target, key, val, receiver) { console.log('Assigning a property: ' + key); return Reflect.defineProperty(receiver, key, { value: val, writable: true, enumerable: true, configurable: true }); } });
Полный пример:
var x = Object.create(new Proxy({}, { get(obj, key) { if (typeof key !== 'symbol') { console.log('Reading a nonexisting property: ' + key); } }, set(obj, key, val, receiver) { console.log('Assigning a nonexisting property: ' + key); return Reflect.defineProperty(receiver, key, { value: val, writable: true, enumerable: true, configurable: true }); } })); var temp; console.log(1, Object.prototype.hasOwnProperty.call(x, 'a')); temp = x.a; // get trap console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp); temp = x.a; // get trap console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp); x.a = 12; // set trap creates a property and sets it console.log(4, Object.prototype.hasOwnProperty.call(x, 'a')); temp = x.a; // direct read - no traps console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp); x.a = 42; // direct write - no traps console.log(6, Object.prototype.hasOwnProperty.call(x, 'a')); temp = x.a; // direct read - no traps console.log(7, Object.prototype.hasOwnProperty.call(x, 'a'), temp); .as-console-wrapper.as-console-wrapper { max-height: 100vh }

Как создать аналог malloc, free, check, init

Есть задание, где стоит реализовать функции malloc, free, check, init. Можно использовать любые функции, кроме вышесказанных. Вот мои попытки реализации malloc:
void *malloc(unsigned int len){ char *arr; for(int i=0; iЯ понимаю, что он не верный, но это пока все, что приходит в голову. Уважаемые знатоки, не могли Вы мне дать направления, как это сделать? Любая помощь, ссылка или алгоритм приветствуется. Есть догадка, чтобы реализовать free, нужно пройтись циклом и задать значение NULL. Но это работает на интерпретированных языках (без типизации, таких как Js, PHP...). А вот как на С это сделать правильно? Изображения задания


Ответ

Ну смотрите.
Откуда брать память, вам заботиться не нужно: у вас память передаётся вашему алгоритму (см. пример, в котором она выделяется на стеке), так что вы просто работаете с переданной памятью.
Теперь, вам нужно организовать список блоков памяти. Для этого вам нужно написать структуру данных, описывающую блок памяти: его размер, положение, признак того, он занят или нет, и указатель на следующий блок. Где размещать этот список? Понятно, где: в вашей выделенной памяти! Внутри блока, кроме вот этой вот служебной информации, должна быть ещё и сама память (она у вас, понятно, будет по фиксированному смещению от начала блока).
Процедура инициализации сводится при этом к помещению в список одного большого блока памяти.
Более сложным является malloc: вам необходимо пройти по связному списку блоков (вначале в нём только один блок, но потом будет больше), найти первый подходящий по размеру, и откусить от него кусок нужного размера. При этом найденный блок разобьётся на два: выделенный кусок и остаток. Впрочем, остаток может быть настолько мал, что в него не поместится заголовок блока, и тогда вы отдадите целый кусок. Не забывайте, что вы отдаёте юзеру не указатель на весь блок памяти (зачем он ему?), а на начало памяти в нём.
free должно быть симметричным: вы получаете на вход указатель на кусок памяти, и помечаете его свободным. Не забудьте от указателя на память вашего блока перейти к указателю на сам блок. Если до него или после него находятся свободные блоки, их можно слить в один блок.
Код и структуры данных намеренно не даю, это ж учебное задание. Дерзайте, у вас хороший предмет и хороший преподаватель, вы многому научитесь!

Стоит ли заменить подход std:thread на std::async?

В проекте (многоагентная система для работы с потоком разнотиповых данных в реальном времени) используется многопоточность из стандартной библиотеки C++, а именно подход на основе потоков std::thread
Функционал каждого агента исполняется в отдельном потоке. Учитывая соотношение между количеством агентов и характеристиками железа, на котором работает эта система - такое разделение (на потоки) имеет логический характер, а не производительный (это будет решаться позже).
Прочитал недавно про подход на основе задач std::async
Вопросы:
Может ли мне дать какое-то преимущество этот подход? И какие сложности могут возникнуть в рамках описанной системы? Где прочитать про эту технологию? Я смотрел только пару обзорных статей.


Ответ

Эффективность std::async сильно зависит от реализации. В старых версиях gcc, например, std::async вообще всегда работает в том же потоке, где вызывается future.get(), несмотря на флаг launch_async. Но даже если реализация хорошая, в лучшем случае std::async будет отправлять задачу в обычный пул потоков. В этом случае проще взять сразу готовый пул потоков и работать с ним, тем более есть пулы потоков с поддержкой std::future, что делает их интерфейс похожим на std::async. Одна из реализаций есть тут
Возможно, для вашей задачи будет удобно использовать в качестве пула потоков boost::asio, поскольку помимо обычных возможностей пула потоков там есть таймеры и асинхронный ввод-вывод (ради чего библиотека и создавалась).

Утечка памяти в перегрузке бинарных операторов

Создаю класс для работы со множествами, для расчет кол-ва тиков clock() прогоняю одну и ту же операцию N (const) раз. В итоге происходит огромная утечка памяти. Возможно дело в том, что в бинарных операциях & и | я создаю новый экземпляр класса с помощью дин. памяти каждую итерацию цикла. Но как освободить динамическую память в таком случае?
#include "stdafx.h" #include #include #include #include using namespace std;
const unsigned int N = 100000;
//Массив символов class Set { int n; //Мощность множества static int U; //Мощность универсума char litera; //Обозначение множества A,B,C,D и так далее char* universe; //Указатель на множество public: Set(char _litera); ~Set(); Set(); void print(); int power() { return n; } //Операции над множествами Set& operator & (const Set& B) const; Set& operator ~ () const; //Операторы копирования и присваивания с переносом Set(Set &); Set& operator = (Set& B); };
Set::Set() : litera('0'), n(0), universe(new char[U + 1]) { //cout << "Создание пустого множества " << litera << " = []
"; universe[0] = '\0'; }; Set ::~Set() { //cout << "Удаление множества " << litera << '
'; delete[] universe; } Set:: Set(char _litera): litera(_litera),n(0),universe(new char[U+1]) { for (int i = 0; i < U; i++) { if (rand() % 2) { universe[n++] = '0' + i; } } universe[n] = '\0'; //cout << "Создание множества " << litera << " = [" << universe << "]
"; } void Set::print() { cout << litera << " = [" << universe << "]" << '
'; } //Операции над множествами Set& Set:: operator & (const Set& B) const { Set *C = new Set; for (int i = 0; i < n; i++) { for (int j = 0; j < B.n; j++) { if (universe[i] == B.universe[j]) C->universe[C->n++] = universe[i]; } } C->universe[C->n] = 0; //cout << "Результат пересечения множества " << litera << " = [" << universe << "]" // << " со множеством " << B.litera << " = [" << B.universe << "]" << " => " << C->litera << " = [" << C->universe << "]
"; return *C; } Set& Set:: operator ~ () const { Set *C = new Set; for (char ch = '0'; ch <= '9'; ch++) { bool flag = true; for (int j = 0; j < n; j++) { if (ch == universe[j]) { flag = false; break; } } if (flag) C->universe[C->n++] = ch; } C->universe[C->n] = '\0'; //cout << "Результат инверсии множества " << litera << " = [" << universe << "]" // << " => " << C->litera << " = [" << C->universe << "]
"; return *C; } //Операторы перегрузки и присваивания с переносом Set:: Set(Set & B): litera(B.litera), n(B.n), universe(B.universe) { //cout << "Конструктор копирования множества c переносом " << B.litera << '
'; B.universe = NULL; } Set& Set:: operator = (Set& B) { //cout << "Конструктор присваивания множества с переносом" << B.litera << '
'; if (this != &B) { n = B.n; universe = B.universe; litera = 'R'; B.universe = NULL; } return *this; }
//Поместить после include int Set::U = 10; //Мощность универсума для десятичных цифр
int main() { setlocale(LC_ALL, ""); srand(time(NULL)); time_t start, stop; Set A('A'), B('B'), C('C'), D('D'), E; A.print(); B.print(); C.print(); D.print(); system("pause"); //Обработка множеств start = clock(); for (int i = 0; i < N; i++) E = ((A & ~(B & C)) & ~D); stop = clock(); //Вывод итогового множества E.print(); //Вывод средней мощности и времени cout << "Average power = " << (A.power() + B.power() + C.power() + D.power() + E.power()) / 5 << '
'; cout << "Time = " << stop - start << '/' << N << '
'; system("pause"); return 0; }


Ответ

У Вас в "операторах" ~ и & выделяется динамическая память:
Set& Set:: operator ~ () const { Set *C = new Set;
Но она нигде не освобождается. Сразу возникает вопрос, а зачем Вам понадобилась здесь динамическое выделение памяти? Может всё-таки переделать без динамической памяти?
Set Set:: operator & (const Set& B) const { Set C; //работа с C return C; } Set Set:: operator ~ () const { Set C; //работа с C return C; }
(объявления тоже необходимо переделать под новые условия). Во-первых, избавились от динамической аллокации, во-вторых, нормальный компилятор применит NRVO, устранив, тем самым, копирование в возвращаемое значение.
Также стоит учесть, что Ваши operator= и конструктор копирования повторяют печальную судьбу auto_ptr, когда присваивание и копирование захватывает ресурсы исходного объекта. Стоило бы сделать дополнительно перемещающие версии, предоставив пользователю больше средств.

Кастомный горизонтальный скролл с animate.css

Есть такой код:
$(window).load(function(){ // Horizontal scroll if($(".js-page-scroll").length){ $(".js-page-scroll").mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, callbacks:{ whileScrolling:function(){ new WOW().init(); } } }); } }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; width: 300px; border: 1px solid #000; padding: 1rem; } .js-page-scroll { width: 100%; overflow-x: auto; }

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?


Использую кастомный скролл (горизонтальный) - malihu custom scrollbar
Для анимации - animate.css и wow.js
Суть в том, что при горизонтальном скролле, текст в блоках появлялся (анимировался) плавно и соответственно последовательно (как при использовании wow.js). Т.е. wow.js но для горизонтальной прокрутки.
Вопрос: как настроить wow.js (или, возможно, есть какой другой плагин) для горизонтального скролла? || Как настроить animate.css для кастомного скролла (при прокрутке блоки появлялись плавно, последовательно)?


Ответ

Можно сделать обычную проверку на наличие элемента в зоне видимости, без всяких доп плагинов.
$(this).offset().left < windowWidth - проверяем вошел ли элемент в зону видимости "справа"
$(this).offset().left > -$(this).width() - проверяем вошел ли элемент в зону видимости "слева"
Если вошел, до добавляем ему класс анимации, если ушел, то удаляем
$(window).load(function(){ var windowWidth = $(window).width(); var thisLeft, thisWidth; function animateBlocks(){ $('.animated').each(function(){ thisLeft = $(this).offset().left; thisWidth = $(this).width(); if(thisLeft < windowWidth && thisLeft > -thisWidth){ $(this).addClass('fadeInUp'); }else{ $(this).removeClass('fadeInUp'); } }); } animateBlocks(); // Horizontal scroll if($(".js-page-scroll").length){ $(".js-page-scroll").mCustomScrollbar({ axis:"x", theme:"dark-3", // scrollbarPosition: 'outside', advanced:{ autoExpandHorizontalScroll:true }, callbacks:{ whileScrolling:function(){ animateBlocks(); } } }); } }); main { display: flex; flex-flow: row nowrap; align-items: center; align-content: center; justify-content: space-between; } section { display: block; min-width: 300px; border: 1px solid #000; padding: 1rem; } .js-page-scroll { width: 100%; overflow-x: auto; }

1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?

5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima dolorum cumque fugiat ducimus rem dicta sequi neque laudantium, facilis explicabo?