const clientId = "CLIENT-ID";
const clientSecret = "CLIENT-SECRET";
async function fetchPosts() {
const response = await fetch(
"https://www.reddit.com/r/memes/hot.json?limit=10"
);
const data = await response.json();
// Exclude stickied posts
const nonStickiedPosts = data.data.children.filter(post => !post.data.stickied);
return nonStickiedPosts;
}
function filterValidPosts(posts) {
return posts.filter(
(post) =>
post.data.title &&
post.data.url &&
post.data.url.startsWith("http") &&
post.data.url.includes(".gif") &&
post.data.url.includes("v.redd.it") &&
post.data.self && // Exclude self-posts
!post.data.removed // Exclude deleted posts
);
}
function convertToDirectLink(redditMediaLink) {
const url = new URL(redditMediaLink);
// Check if it's a Reddit preview link
if (url.hostname === "preview.redd.it") {
const [mediaId, format] = url.pathname.split("/").pop().split(".");
if (mediaId && format) {
// Build the direct link
return `https://i.redd.it/${mediaId}.${format}`;
}
}
// If it's not a Reddit preview link, return the original link
return redditMediaLink;
}
// ...
// Function to render posts as cards on the webpage
async function renderPosts(posts) {
const container = document.getElementById("postsContainer");
container.innerHTML = "";
for (let i = 0; i < posts.length; i += 3) {
const row = document.createElement("div");
row.classList.add("row");
for (let j = i; j < i + 3 && j < posts.length; j++) {
const post = posts[j];
const card = document.createElement("div");
card.classList.add("card");
const cardContent = document.createElement("div");
cardContent.classList.add("card-content");
if (post.data.is_gallery) {
// Handle Reddit galleries
if (post.data.media_metadata) {
// Iterate over media_metadata to get direct links
for (const mediaId in post.data.media_metadata) {
const galleryImage = post.data.media_metadata[mediaId];
const directLink = convertToDirectLink(galleryImage.s.u); // Use the s.u field for direct link
const image = document.createElement("img");
image.src = directLink;
image.alt = post.data.title;
cardContent.appendChild(image);
}
}
} else if (post.data.url) {
// Handle posts with a single image or external links
const image = document.createElement("img");
image.src = await convertToDirectLink(post.data.url);
image.alt = post.data.title;
cardContent.appendChild(image);
}
cardContent.innerHTML += `<h3>${post.data.title}</h3>`;
card.appendChild(cardContent);
row.appendChild(card);
}
container.appendChild(row);
}
}
async function fetchAndRenderNewPosts() {
try {
const posts = await fetchPosts();
const validPosts = filterValidPosts(posts);
if (validPosts.length > 0) {
renderPosts(validPosts);
} else {
console.warn("No valid posts fetched. Trying again with new posts.");
const newPosts = await fetchPosts();
renderPosts(newPosts);
}
} catch (error) {
console.error("Error fetching or rendering posts:", error);
}
}
window.onload = function () {
fetchAndRenderNewPosts();
setInterval(fetchAndRenderNewPosts, 300000); // Fetch new posts every 5 minutes (adjust as needed)
};
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: flex-start;
max-height: 100vh; /* Set a maximum height for the container */
overflow-y: auto; /* Add vertical scroll if needed */
}
.row {
display: flex;
justify-content: space-around;
margin-bottom: 20px; /* Adjust as needed for spacing between rows */
}
.card {
margin: 10px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
transition: box-shadow 0.3s ease-in-out;
overflow: hidden;
width: calc(33% - 20px); /* Adjust as needed for spacing between cards */
max-width: 300px; /* Limit the maximum width of each card */
}
.card:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}
.card-content {
position: relative;
}
.card img {
width: 100%;
height: 100%;
object-fit: cover; /* Ensure the image covers the entire container */
}
<div class="container" id="postsContainer"></div>
我创建了一个 Reddit 帖子获取网站,我可以在卡片中获取画廊(包含多个图像的帖子),其中放置了所有图像,并且将单个图像作为卡片及其标题发布。现在对于画廊类型的帖子,我想制作一个滑动器,这样我就可以滑动而不是在一个卡盒中连续看到多个图像,但我不知道该怎么做。
function convertToDirectLink(redditMediaLink) {
const url = new URL(redditMediaLink);
// Check if it's a Reddit preview link
if (url.hostname === "preview.redd.it") {
const [mediaId, format] = url.pathname.split("/").pop().split(".");
if (mediaId && format) {
// Build the direct link
return `https://i.redd.it/${mediaId}.${format}`;
}
}
// If it's not a Reddit preview link, return the original link
return redditMediaLink;
}
// ...
// Function to render posts as cards on the webpage
async function renderPosts(posts) {
const container = document.getElementById("postsContainer");
container.innerHTML = "";
for (let i = 0; i < posts.length; i += 3) {
const row = document.createElement("div");
row.classList.add("row");
for (let j = i; j < i + 3 && j < posts.length; j++) {
const post = posts[j];
const card = document.createElement("div");
card.classList.add("card");
const cardContent = document.createElement("div");
cardContent.classList.add("card-content");
if (post.data.is_gallery) {
// Handle Reddit galleries
if (post.data.media_metadata) {
// Iterate over media_metadata to get direct links
for (const mediaId in post.data.media_metadata) {
const galleryImage = post.data.media_metadata[mediaId];
const directLink = convertToDirectLink(galleryImage.s.u); // Use the s.u field for direct link
const image = document.createElement("img");
image.src = directLink;
image.alt = post.data.title;
cardContent.appendChild(image);
}
}
} else if (post.data.url) {
// Handle posts with a single image or external links
const image = document.createElement("img");
image.src = await convertToDirectLink(post.data.url);
image.alt = post.data.title;
cardContent.appendChild(image);
}
cardContent.innerHTML += `<h3>${post.data.title}</h3>`;
card.appendChild(cardContent);
row.appendChild(card);
}
container.appendChild(row);
}
}
// ...
async function fetchAndRenderNewPosts() {
try {
const posts = await fetchPosts();
const validPosts = filterValidPosts(posts);
if (validPosts.length > 0) {
renderPosts(validPosts);
} else {
console.warn("No valid posts fetched. Trying again with new posts.");
const newPosts = await fetchPosts();
renderPosts(newPosts);
}
} catch (error) {
console.error("Error fetching or rendering posts:", error);
}
}
window.onload = function () {
fetchAndRenderNewPosts();
setInterval(fetchAndRenderNewPosts, 300000); // Fetch new posts every 5 minutes (adjust as needed)
};
代码摘要:这就是我到目前为止所做的一切。链接转换器将
preview.redd.it
链接转换为 i.redd.it
,以便更轻松地进行高分辨率显示。渲染部分只是将图像渲染在卡片中,每行 3 张卡片。
这可能是一种方法。
async function fetchPosts() {
let data = {"kind":"Listing","data":{"children":[{"kind":"t3","data":{"subreddit":"memes","is_gallery":false,"title":"r/Memes is looking for new moderators! Interested? Fill out our application!","id":"18zq3y5","url":"https://docs.google.com/forms/d/e/1FAIpQLSfBlrL6LVOktwIdGubvbJ7REeh9vANiBTIpUecW63PHINQECg/viewform","stickied":false}},{"kind":"t3","data":{"subreddit":"memes","is_gallery":false,"title":"It was the 9/one- one of British TV","id":"19c1wez","url":"https://i.redd.it/hoqa37i19sdc1.jpeg","stickied":false}},{"kind":"t3","data":{"subreddit":"McMansionHell","is_gallery":true,"title":"Look at the upper left corner of the bathroom","media_metadata":{"5j8l66lt27b61":{"s":{"y":576,"x":768,"u":"https://preview.redd.it/5j8l66lt27b61.jpg?width=768&format=pjpg&auto=webp&s=ba0c95d8ce7cf1d325dfac2564c2fdd55b036508"},"id":"5j8l66lt27b61"},"797pwyft27b61":{"s":{"y":413,"x":550,"u":"https://preview.redd.it/797pwyft27b61.jpg?width=550&format=pjpg&auto=webp&s=a6dc4d0e1fac886c901e662b08662c100a5ee4e7"},"id":"797pwyft27b61"},"pj9sc1st27b61":{"s":{"y":576,"x":768,"u":"https://preview.redd.it/pj9sc1st27b61.jpg?width=768&format=pjpg&auto=webp&s=637aed513c30179864c5a33302f44bd035771e0b"},"id":"pj9sc1st27b61"}},"gallery_data":{"items":[{"media_id":"5j8l66lt27b61","id":22269281},{"media_id":"797pwyft27b61","id":22269279},{"media_id":"pj9sc1st27b61","id":22269284}]},"id":"kwudba","url":"https://www.reddit.com/gallery/kwudba","stickied":false}},{"kind":"t3","data":{"subreddit":"McMansionHell","is_gallery":true,"title":"This is a dummy gallery","media_metadata":{"f9gczent27b61":{"s":{"y":576,"x":768,"u":"https://preview.redd.it/f9gczent27b61.jpg?width=768&format=pjpg&auto=webp&s=1a6cc9447c9b8bac8b5a91de7c8c32247d558eaa"},"id":"f9gczent27b61"},"v2fyorvt27b61":{"s":{"y":576,"x":768,"u":"https://preview.redd.it/v2fyorvt27b61.jpg?width=768&format=pjpg&auto=webp&s=76fb9f6db49dd5a379eebd9a0ae7d3fa86c88745"},"id":"v2fyorvt27b61"}},"gallery_data":{"items":[{"media_id":"5j8l66lt27b61","id":22269281},{"media_id":"v2fyorvt27b61","id":22269285}]},"id":"dummygal","url":"https://www.reddit.com/gallery/dummygal","stickied":false}}],"before":null}};
// Exclude stickied posts
const nonStickiedPosts = data.data.children.filter(post => !post.data.stickied);
return nonStickiedPosts;
}
function filterValidPosts(posts) {
return posts.filter(
(post) =>
post.data.title &&
post.data.url &&
post.data.url.startsWith("http") &&
post.data.url.includes(".gif") &&
post.data.url.includes("v.redd.it") &&
post.data.self && // Exclude self-posts
!post.data.removed // Exclude deleted posts
);
}
function convertToDirectLink(redditMediaLink) {
const url = new URL(redditMediaLink);
// Check if it's a Reddit preview link
if (url.hostname === "preview.redd.it") {
const [mediaId, format] = url.pathname.split("/").pop().split(".");
if (mediaId && format) {
// Build the direct link
return `https://i.redd.it/${mediaId}.${format}`;
}
}
// If it's not a Reddit preview link, return the original link
return redditMediaLink;
}
// ...
// Function to render posts as cards on the webpage
async function renderPosts(posts) {
const container = document.getElementById("postsContainer");
container.innerHTML = "";
for (let i = 0; i < posts.length; i += 3) {
const row = document.createElement("div");
row.classList.add("row");
for (let j = i; j < i + 3 && j < posts.length; j++) {
const post = posts[j];
const card = document.createElement("div");
card.classList.add("card");
const cardContent = document.createElement("div");
cardContent.classList.add("card-content");
let customClass = "";
let swiperStart = `
<!-- Slider main container -->
<div class="swiper">
<!-- Additional required wrapper -->
<div class="swiper-wrapper">
<!-- Slides -->
`;
let swiperContent = "";
let swiperEnd = `
</div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
<!-- If we need navigation buttons -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- If we need scrollbar -->
<div class="swiper-scrollbar"></div>
</div>
`;
if (post.data.is_gallery) {
// Handle Reddit galleries
if (post.data.media_metadata) {
customClass = " gallery-post";
// Iterate over media_metadata to get direct links
for (const mediaId in post.data.media_metadata) {
const galleryImage = post.data.media_metadata[mediaId];
const directLink = convertToDirectLink(galleryImage.s.u); // Use the s.u field for direct link
swiperContent += `
<div class="swiper-slide">
<img alt="`+post.data.title+`" src="`+directLink+`">
</div>
`;
}
const divElem = document.createElement("DIV");
divElem.innerHTML = swiperStart + swiperContent + swiperEnd;
cardContent.appendChild(divElem);
cardContent.className += customClass;
}
} else if (post.data.url) {
// Handle posts with a single image or external links
const image = document.createElement("img");
image.src = await convertToDirectLink(post.data.url);
image.alt = post.data.title;
cardContent.appendChild(image);
}
cardContent.innerHTML += `<h3>${post.data.title}</h3>`;
card.appendChild(cardContent);
row.appendChild(card);
}
container.appendChild(row);
}
initSwiper();
}
async function fetchAndRenderNewPosts() {
try {
const posts = await fetchPosts();
const validPosts = filterValidPosts(posts);
if (validPosts.length > 0) {
renderPosts(validPosts);
} else {
console.warn("No valid posts fetched. Trying again with new posts.");
const newPosts = await fetchPosts();
renderPosts(newPosts);
}
} catch (error) {
console.error("Error fetching or rendering posts:", JSON.stringify(error));
}
}
window.onload = function () {
fetchAndRenderNewPosts();
};
function initSwiper() {
if(document.querySelectorAll(".gallery-post").length > 0) {
console.log("I'm in....");
const swiper = new Swiper('.swiper', {
// Optional parameters
direction: 'horizontal',
loop: true,
// If we need pagination
pagination: {
el: '.swiper-pagination',
},
// Navigation arrows
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
});
} else {
console.log("I'm not in :(");
}
}
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: flex-start;
max-height: 100vh; /* Set a maximum height for the container */
overflow-y: auto; /* Add vertical scroll if needed */
}
.row {
display: flex;
justify-content: space-around;
margin-bottom: 20px; /* Adjust as needed for spacing between rows */
min-width: 98vw;
}
.card {
margin: 10px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
transition: box-shadow 0.3s ease-in-out;
overflow: hidden;
width: calc(33% - 20px); /* Adjust as needed for spacing between cards */
max-width: 300px; /* Limit the maximum width of each card */
}
.card:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}
.card-content {
position: relative;
}
.card img {
width: 100%;
height: 100%;
object-fit: cover; /* Ensure the image covers the entire container */
}
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css"
/>
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
<div class="container" id="postsContainer"></div>
为了简单起见,对原始代码进行了更改
您会注意到我已经删除了您最初的获取逻辑。这样做是为了测试目的 - 使用大大简化的 JSON 来模拟原始 URL 的响应。
此外,由于可用代码中未使用它们,因此我冒昧地从代码中删除了
clientId
和 clientSecret
。当然,如果有需要,您会使用它们。
setInterval
也已被删除,因为我提供的代码仅用于测试目的 - 当然,您会将其包含在原始代码中。
CSS 也有一些细微的变化,以适应滑动器的样式(
min-width
是为您的 .row
类设置的 - 删除它,您就会明白为什么添加它)。
对原始代码进行的更改,包括 swiper.js
函数
renderPosts
已被改编为包含创建 swiper 容器的逻辑,该容器将保存从 reddit 检索到的图像。为此,我依赖于官方文档。请注意,这只是一种方法 - 如果您发现我提供的解决方案不适合您的需要,请随意尝试。
向包含画廊的卡片添加自定义类,以便我们知道是否需要初始化滑动器。
最后,在
renderPosts
函数的最后,我添加了一个新函数 - initSwiper
。该功能很简单,改编自官方文档中的内容(无滚动条,水平滑动,如果有画廊帖子,则初始化滑动器等)。