Мне нужно получить галерею живых изображений на основе постоянно отслеживаемой папки. Он будет работать на моем локальном компьютере. Вот как это должно работать:
Я сделал это на основе некоторых примеров, найденных в Stackoverflow. Но img не обновляется. И если я хорошо понимаю код, он не удалит изображение, если файл исчезнет. Что вы думаете? (Как видите, я не очень разбираюсь в новых технологиях... Я старый веб-мастер html/css)
<!doctype html>
<html lang = "fr">
<head>
<meta charset = "utf-8">
<title>Titre de la page</title>
<link rel = "stylesheet" href = "style.css">
<script>
function refresh(node)
{
var times = 1000; // gap in Milli Seconds;
(function startRefresh()
{
var address;
if (node.src.indexOf('?')>-1)
address = node.src.split('?')[0];
else
address = node.src;
node.src = address+"?time = "+new Date().getTime();
setTimeout(startRefresh,times);
})();
}
window.onload = function()
{
var node = document.getElementsByClassName('img');
refresh(node);
// you can refresh as many images you want just repeat above steps
}
</script>
</head>
<body>
<div class = "ajax-inserted-content">
<section class = "section gallery grid layout-4-col">
<div class = "container">
<div class = "row" id='gallery-items'>
</div>
</div>
</section>
</div>
<script>
function doPortItem(n) {
let img = document.createElement('img');
img.src = './imgportfolio/test-' + n + '.jpg';
img.addEventListener('load', () => {
let div = `<div class = "col-3 col-lg-4 col-md-6 col-sm-12">
<div class = "gallery-item">
<div class = "gallery-img">
<img class = "img" data-lazy-image data-src = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzIDIiPjwvc3ZnPg= = " src = "${img.src}" alt = "Demo img">
</div>
</div>
</div>`;
document.querySelector('#gallery-items').innerHTML += div;
doPortItem(++n)
})
}
doPortItem(1)
</script>
</body>
</html>
Как сказал @Keith, вам нужно будет сделать это на стороне сервера, посмотрите здесь: stackoverflow.com/a/44588417/4191561
Хорошо. Но если достичь всей моей цели невозможно, что возможно только на стороне клиента JavaScript? На основе того, что я уже сделал (или с лучшим подходом)? Фактически, я не могу запустить PHP-сервер. Он должен работать на локальном компьютере, отслеживая папку на том же локальном компьютере.
Короче говоря: вы не можете читать каталог полностью на основе клиента, потому что это было бы кошмаром безопасности: вы могли бы легко просканировать файловую систему пользователя.
Если вы действительно не можете запустить локальный сервер, поддерживающий серверные сценарии, такие как php
, ваш единственный шанс, вероятно, состоит в том, чтобы развернуть согласованную схему числовых имен файлов изображений и скрыть несуществующие изображения в представлении галереи, например от img-1
до img-100
:
let dir = 'https://picsum.photos/id';
let suffix = '/100/100';
let start = -3;
let end = 3;
// init
loadImages(dir);
// reload
let interval = 60 * 1000;
setInterval(loadImages, interval);
function loadImages(dir) {
let html = '';
//reset content
imageGrid.innerHTML = '';
for (let i = start; i < end; i++) {
let src = `${dir}/${i}${suffix}`;
html +=
`<a href = "${dir}/${i}${suffix}" data-lg-size = "100-100">
<img onerror = "this.parentNode.classList.add('broken-image')" src = "${src}">
</a>`;
}
imageGrid.insertAdjacentHTML('beforeend', html);
}
.imageGrid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1em;
}
img {
width: 100%;
aspect-ratio: 1;
border: 1px solid #ccc;
}
.broken-image {
display: none;
}
<h3>3 images are hidden as they don't exist</h3>
<div id = "imageGrid" class = "imageGrid"></div>
Если изображение не может быть загружено, оно скрыто с помощью функции обратного вызова onerror
.
Если вы можете контролировать соглашения об именах файлов — это, вероятно, лучшее, что вы можете получить от 100% клиентского подхода.
Обновления списка каталогов будут зависеть от повторяющегося вызова метода, например setInterval()
. Вы не можете получить правильное обновление в режиме реального времени, и вам, вероятно, следует избегать слишком большого количества обновлений — например, обновление каждую минуту (или каждые 5 минут) более разумно, чем обновление каждую секунду.
При обновлении галереи вам обычно необходимо инициализировать скрипт галереи (привязка событий лайтбокса и т. д.).
Я настоятельно рекомендую установить локальный сервер, обеспечивающий, например, функциональность php
. Например, через такое приложение, как xampp, mampp и т. д.
В этом случае вы можете написать скрипт php
, отвечающий на вызов JS fetch()
, например:
JavaScript
Мы отправляем запрос POST через fetch()
на PHP-скрипт, который возвращает список файлов для указанного каталога, включая только определенные типы файлов.
// directory to search for image files
let dir = 'img';
// allowed file extensions
let extensions = ['webp', 'png', 'jpg', 'gif'];
// php script url for directory listing
let phpScan = 'filelist.php';
// update interval: ever minute = 60000ms
let interval = 60 * 1000;
let fileList;
// init async call
(async () => {
//init
fileList = await getFilelist(dir, phpScan, extensions);
updateGallery(fileList);
setInterval(async () => {
fileList = await getFilelist(dir, phpScan, extensions);
updateGallery(fileList)
}, interval)
})();
// dummy update function
function updateGallery(fileList) {
console.info(fileList);
}
/**
* retrieve file directory info
* via php script
*/
async function getFilelist(dir, phpScan, extensions) {
let list = await (await fetch(
phpScan,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
dir: dir,
extensions: extensions
})
})).json();
return list;
}
Если вы используете локальный сервер, вы также можете использовать этот подход, как описано в fmacdee: «Как составить список файлов внутри папки с помощью выборки?».
Этот подход предполагает, что на вашем локальном сервере включен список каталогов. Другими словами: сервер автоматически сгенерирует представление таблицы HTML, которое вы можете «проанализировать» с помощью получения результата. Вот модифицированная версия:
async function getDirectory(dir, extensions) {
let response = await fetch(dir);
let html = await response.text();
let doc = new DOMParser().parseFromString(html, 'text/html');
console.info(doc);
let files = [...doc.querySelectorAll("a")].map(a => {
// filter allowed extenstion
let ext = a.href.split('.').slice(-1)[0];
if (extensions.includes(ext)) {
let filename = a.href.split('/').slice(-1)[0];
let mod = a.parentNode.nextElementSibling.textContent.trim()
return { filename: filename, href: a.href, mod: mod }
}
return
}
).filter(Boolean)
return files;
}
В общем: настоятельно рекомендую потратить время на установку локального сервера.
Мы определенно не увидим никаких новых функций JS, позволяющих просматривать каталоги на стороне клиента, поскольку это будет иметь огромные последствия для безопасности.
Спасибо за такой подробный ответ :D Я попробовал ваш обходной путь только для клиента: он работает. Но поскольку мне нужно получать новые изображения в реальном времени, я вынужден установить интервал в 1 секунду. Итак, я не могу добавить сценарий щелчка и масштабирования к каждому изображению, потому что оно будет обновляться и исчезать каждую секунду. Попробую найти, можно ли установить локальный сервер. Спасибо :)
К сожалению, это не то, что вы можете сделать только на стороне клиента. То, что вы описываете, можно сделать с использованием какого-либо процесса на стороне сервера, а затем, возможно, использовать что-то вроде протокола Websocket. Но будьте осторожны: это нетривиальный процесс.