”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > API 每小时数据的响应式 JavaScript 轮播

API 每小时数据的响应式 JavaScript 轮播

发布于2024-11-06
浏览:904

Responsive JavaScript Carousel for API Hourly Data

I almost mistook an incomplete solution for a finished one and moved on to work on other parts of my weather app! While working on the carousel that was supposed to show 12 hours of weather, I wanted to add the feature which would help in fetching the next day’s hours in case the current day was finished. However, instead of transitioning to the next day, the carousel kept looping back to the beginning of the current day's hours, and I mistakenly thought the task was complete. Yikes!

Initial Challenges

I thought about two ‘for loops’ but I don’t think that ‘j’ printing all its elements for the length of the entire ‘i’ was correct. I found a lot of blogs online about the use of modulus operator for "circular array" But I did not know how that would help my case. I needed to loop through the current day's hours and then switch to the next day once the hours reset to zero. A lot was happening and I needed to make it more concise and place everything in one function. Tough!

Recognizing Incomplete Solutions and Mistakes

I found something really cool online though, it may solve a big problem for me. It helped me understand how modulus operator works for circular arrays. Here is the example on the website:

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
// Function to cycle through the days of the week
function cycleDays(index) {
  return daysOfWeek[index % daysOfWeek.length];
}
// Let's cycle through the days:
for (let i = 0; i 



The result is like:
Day 1: Monday
Day 2: Tuesday
...

What I wanted was, instead of going back to the daysOfWeek array, and start from ‘Monday’, it should go to a completely different array. So, I took the code to the code editor and changed it a bit. First, I made a variable called ‘currentIndex’ and stored the modulus operation in it. Then I logged it to the console. It reset after 6 and became zero again.

Though, I was logging the wrong variable to the console. Because, if I wrote the if condition like this: if(currentIndex === 0), it would actually move toward a new array right at the beginning of the loop. So, now I logged the "index" instead, and finally I found the answer! In order to test the new code, I made a new array for ‘months’ and then tried to make the switch. But I made another mistake—let me show you:

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
const months = [
  'Jan',
  'Feb',
  'March'
];
// Function to cycle through the days of the week
function cycleDays(index) {
  let currentIndex = index % daysOfWeek.length
  console.log(index)
 if(index === 7){
   return months[currentIndex]
 } else {
     return daysOfWeek[currentIndex];
 }
}
// Let's cycle through the days:
for (let i = 0; i 



After logging "Jan", it switched back to the original array. The mistake was strict equality check, I should have used ‘greater than or equal to’ instead. When I plugged that in, it successfully switched to the new array!

Now, I wanted the loop to start from the current hour and continue without stopping, with a marker in place to switch between the arrays. That marker will be the modulus operator instead of the length of the array. I could also use the length of the array, which in this case is 24, but I’m sticking to the hard-coded value of 24 for now.

currentIndex = (currentIndex 1) % 9

This line allows me to switch from day one to day two during the loop without stopping it. Here's another trial (I updated the arrays to resemble API results):

const dayOne = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
const dayTwo = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
let hours = dayOne;
let currentHour = 5;
function cycleDays(currentHour) {
  let currentIndex = currentHour
  for (let i = 0; i 



Notice something interesting in the results:

index is 5 and monday is six and i is 0
index is 6 and monday is seven and i is 1
index is 7 and monday is eight and i is 2
index is 8 and monday is nine and i is 3
index is 9 and monday is ten and i is 4
index is 0 and monday is one and i is 5
index is 0 and tuesday is 11
index is 1 and monday is 12 and i is 6
index is 2 and monday is 13 and i is 7
index is 3 and monday is 14 and i is 8
index is 4 and monday is ¬15 and i is 9

The issue here is that the loop runs once from the start, and when it reaches the condition (if(currentIndex === 0)), it switches the array. However, when currentIndex = 0 (i.e., 10 % 10 = 0), the hours[currentIndex] is accessed before the if condition is executed. That’s why you see values from dayOne (like "one") even after the switch.

To fix this, the if condition needs to be checked right after currentIndex becomes 0, so that the array switch happens before logging:

console.log(index is ${currentIndex} and monday is ${hours[currentIndex]} and i is ${i})...

By changing the position of the condition, it can be ensured that the switch occurs at the correct time without first accessing the wrong array.

const monday = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
const tuesday = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
let hours = monday;
let currentHour = 5;
function cycleDays(currentHour) {
  let currentIndex = currentHour
  for (let i = 0; i 



My code is almost there. Here, the only mistake I am making is logging ‘Monday’ instead of ‘Tuesday’. The values are from the ‘Tuesday’ array though, but it keeps saying ‘Monday’ because of the wrong way of writing the console.log statement. I guess, It is quite hard to put two and two together and picture logging VS actually putting in values into html elements. Here is a bit of improvement using ternary operator (yes, I switched the elements of the array, again!):

const monday = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
const tuesday = ['apple', 'orange', 'banana', 'pineapple', 'grapes', 'cherries', 'strawberries', 'mangoes', 'blueberries', 'pears'];
let hours = monday;
let currentHour = 9;
function cycleDays(currentHour) {
  let currentIndex = currentHour
  for (let i = 0; i 



Finally, I can construct my code for the 3-day data I am retrieving from the api, here is the refined version:

function createHours(days){
        if (!days || days.length === 0) {
            console.error("Days array is undefined or empty");
            return; // Prevent further execution if data is missing
        }
        const btnNext = document.querySelector('.next');
        const btnPrev = document.querySelector('.previous');
        const hourContainer = document.querySelector('.tfour_hours');
        const currentHour = new Date().getHours()
        function getHoursForDay(index) {
         return days[index].hour; 
        }
        let dayIndex = 0;
        let hours = getHoursForDay(dayIndex);
        let index = currentHour;
        let displayHours = [];
        for (let i = 0; i 
                        

Next Day

${hourNum}

icon

${hourData.temp_c}°C

`); } else { displayHours.push(`

${hourNum}

icon

${hourData.temp_c}°C

`); } index = (index 1) % 24; if(index === 0 && dayIndex === 0){ dayIndex = 1; hours = getHoursForDay(dayIndex) } } //for loop displayHours = displayHours.join(''); hourContainer.innerHTML = displayHours; … };

Creating Dynamic HTML Elements

Let’s talk about generating the 12 divs. I couldn’t picture how to get the buttons on either side of the parent div while the 12 hours just float in between them. If I were to generate the 12 divs in the same parent as the buttons, then the button elements would need a different justification setting than the 12 divs.

It only made sense to let them have their own container. It took me a while to figure this out—I actually had to sleep on it. Then next day, I typed .btn-container and hit tab and from there, everything clicked. I had seen every grouped item and their own containers inside parent containers in John Smilga's tutorials, I did not know why such grouping would be necessary until I started to design the 24-hour container. It was a real 'gotcha moment'.

Now came another problem that lingered for days. The slider that I designed in the tutorials was not as challenging as these divs. In the tutorials, there was a simple translate value, but right now I have quite a few issues. On smaller screens, the divs were sticking together and starting to look like spaghetti.

And, when I used a simple translateX property, meaning when I 'guessed’ the pixels, there was a lot of space left after the divs had completely translated to the left. It meant they were translating more than their combined width. I needed to find a proper value to ensure the divs stopped exactly at the end without leaving that extra space. After searching for a long time, I came across a blog that offered various solutions.

There were a lot of solutions. A few of them were using modulo operator, which reminded me of the circular array logic I had applied when switching days in the ‘for loop’. There were a lot comments here that used Math.min and Math.max. Which basically would make the container translate until the end of its length was reached. Excellent! So no more white space? Not so fast...

One thing that differed from these examples was that my container would initially display 3 or 4 divs. So, when the offset is 0, there is already a certain amount of length in the parent container.

They were showing the image by adding the number 1. So, their carousel would slide 1 image forward according to the index number of the images in the array. For example, if there are 10 images in a container, and we add one to the currentImage variable, the value calculated by Math.min will be '1'. Then, when we add another '1', the current image will be 2 and the value will be 2 by Math.min because 2 mod 10 is 2. This particular example would change the game of the slider that I am trying to make. This was the code that caught my eye:

const imageData = [ 'image1.png', 'img2.png', 'img3.png', ... ];
let currentImage = 0;
____
const handleImageChange = (imageShift) => {
  currentImage = Math.max(
    0,
    Math.min(
      imageData.length - 1,
      (currentImage   imageShift) % imageData.length
    )
  );
}
____
const firstImage = () => handleImageChange(-imageData.length);
const prevImage = () => handleImageChange(-1);
const nextImage = () => handleImageChange(1);
const lastImage = () => handleImageChange(imageData.length);

The brilliance behind Richard Kichenama's solution, found in the comments, lies in the use of Math.max to ensure the value doesn’t drop below 0 and Math.min to calculate the translation value until it reaches the maximum length of the image array.

Now, how was I to solve the problem of the white space? I had to consider the margins of all of the child divs and add them together to get the entire length of the children divs. Then, the slider should stop moving once the last child is reached. This means the total width is the sum of all the children's widths plus their margins.

However, I ran into another issue: some of the divs were already displayed in the container, which left me stuck again. Luckily, a friend of mine came to the rescue. After discussing the problem with them, here's what I understood:

I could not consider the entire length of the children divs. There was almost as much of white space left as the container length. The solution was to subtract the parent container's length from the total length of the children (including margins). This adjustment helped resolve the white space issue—phew!

Some of the code examples had a variable that was kind of like a ‘counter’. It acted as a ‘counter’ for translate property. When this variable increased, the translate property increased and so on. I separated the Math.min and Math.max properties for the next and previous buttons. It was more helpful and easier that way.

In the examples I referenced, the code was using the length of the array to determine the slide distance, but, as per my previous discussion with my friend, I needed to consider the white space so I have to subtract the length of the container. This way, I ensured that my divs could only move by a specific amount, avoiding the extra space at the end.

Also, thanks to john smilga's tutorials, I learned how to get the width, height, top properties of items. It was a struggle to apply the right one, it was also a struggle to find out that some of the values are strings and needed to be turned into numbers. I found that easily on google and got introduced to ‘parseFloat’.

I also came across another helpful resource that taught me how to display only three divs for large screens and two divs for small screens. The trick was to divide 100% of the container’s width by 3 (or 2 for small screens) and subtract the margins. This allowed for equally sized divs that fit perfectly within the container (so clever!). Finally, to check out the final function, please visit my GitHub. Here is the link to my repository.

The window event listener for resizing was crucial in fixing the alignment issues in my container. It addressed the "Flash of Unstyled Content" (FOUC) problem by resetting the offset on resize. I have to thank my friend for helping me understand how to calculate maxOffset—that was a real game changer.

Lastly, a shout-out to all experienced developers: every word you share helps someone new to the field. So, keep posting the information from your end, as we are waiting on the other side eager to learn. Thank you!

版本声明 本文转载于:https://dev.to/uroobacodes/responsive-javascript-carousel-for-api-hourly-data-55in?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 购买亚马逊评论
    购买亚马逊评论
    https://dmhelpshop.com/product/buy-amazon-reviews/ 购买亚马逊评论 当谈到在亚马逊上进行商务和销售产品时,评论的重要性怎么强调都不为过。一条评论就可以决定购买的成败,而潜在的买家往往会犹豫是否购买缺乏评论的产品。缺乏评论可以起到威慑作用,这就是为什么...
    编程 发布于2024-11-07
  • 使用 DTO 简化 Laravel 中的数据传输
    使用 DTO 简化 Laravel 中的数据传输
    这是有关如何使用 Laravel Data: 创建数据传输对象 (DTO) 的分步示例 1. 安装Laravel数据包 首先,使用 Composer 安装 spatie/laravel-data 包。该软件包有助于创建 DTO 并有效管理数据。 composer require sp...
    编程 发布于2024-11-07
  • Go中如何查找与源文件相关的文件?
    Go中如何查找与源文件相关的文件?
    在Go中查找相对于源文件的文件与解释性语言不同,Go程序是经过编译的,执行时不需要源文件。因此,Ruby 中使用 __FILE__ 来相对于源文件定位文件的概念在 Go 中并不适用。相反,Go 提供了 runtime.Caller 函数,该函数返回调用时的文件名。汇编。但是,此信息对于动态定位文件并...
    编程 发布于2024-11-07
  • 如何在 Python 中高效地统计项目出现次数?
    如何在 Python 中高效地统计项目出现次数?
    提高效率的 Python 中项目频率计数计算列表中项目的出现次数是一项常见的编程任务。这个问题探讨了在 Python 中解决此问题的更有效方法。最初提供的代码虽然功能强大,但涉及到对列表进行两次迭代,从而导致性能不佳。关键的挑战在于找到一种 Pythonic 方法来计算项目出现次数,而无需重复遍历列...
    编程 发布于2024-11-07
  • 探索异步 Deepgram API:使用 Python 进行语音转文本
    探索异步 Deepgram API:使用 Python 进行语音转文本
    今天将探索用于将语音转换为文本的 Deepgram API [转录]。无论是构建语音助手、转录会议还是创建语音控制应用程序,Deepgram 都让入门变得比以往更容易。 什么是 Deepgram? Deepgram 是一个强大的语音识别平台,它使用先进的机器学习模型来实时转录音频。它...
    编程 发布于2024-11-07
  • 如何处理 PHP JSON 编码中格式错误的 UTF-8 字符?
    如何处理 PHP JSON 编码中格式错误的 UTF-8 字符?
    处理 PHP JSON 编码中格式错误的 UTF-8 字符使用 json_encode() 序列化包含俄语字符的数组时,您可能会遇到与格式错误的 UTF-8 字符相关的错误。要解决此问题,请执行以下步骤:步骤 1:识别字符编码使用 mb_detect_encoding() 确定包含俄语字符的字段的编...
    编程 发布于2024-11-07
  • 在 Java 认证考试中使用 Var 的 ips
    在 Java 认证考试中使用 Var 的 ips
    Java 认证考试需要深入了解该语言及其各种功能,包括使用 var 进行局部变量类型推断。虽然这看起来像是一个小细节,但它会极大地影响代码的可读性和效率。为了帮助您在 Java 认证考试中取得好成绩,这里有四个在代码中使用 var 的技巧: 1.在增强的 for 循环中使用 var: 由于循环控制变...
    编程 发布于2024-11-07
  • 通过制作(愚蠢的)故事生成器来学习状态管理(学习 Modulo.js - 第 f 部分
    通过制作(愚蠢的)故事生成器来学习状态管理(学习 Modulo.js - 第 f 部分
    ?欢迎回来!没听懂第 1 部分吗?不用担心,您可以从头开始,也可以直接从这里开始! 简介:SillyStory Web 组件 本教程中我们的任务是构建一个故事生成组件。这将为我们提供大量使用 State 的练习。上次我们以一个有点像下面的片段结束。然而,在本教程中,我们更改了“模板”...
    编程 发布于2024-11-07
  • 获取下一行学习如何处理文件描述符和系统 I/O 的项目
    获取下一行学习如何处理文件描述符和系统 I/O 的项目
    在 C 编程领域,有效管理输入、输出和内存是基础。为了帮助您掌握这些关键概念,您将在 get_next_line 项目中编写一个使用文件描述符逐行读取文件的函数。每次调用该函数都会从文件中读取下一行,从而允许您一次一行处理整个文件内容。 了解系统中的文件描述符和 I/O ...
    编程 发布于2024-11-07
  • 为什么Go的main函数有死循环?
    为什么Go的main函数有死循环?
    Go 运行时:主函数中无限循环之谜Go 运行时的核心位于 src/runtime/proc.go,其中有一个令人费解的功能:主函数末尾有一个无限的 for 循环。人们可能想知道为什么运行时中存在这样一个看似毫无意义的构造。目的:检测致命错误深入研究代码,很明显循环服务于错误处理的关键目的。当发生致命...
    编程 发布于2024-11-07
  • iostream 与 iostream.h:在现代 C++ 中应该使用哪个?
    iostream 与 iostream.h:在现代 C++ 中应该使用哪个?
    iostream 和 iostream.h 之间的区别在 C 中,程序员可能会遇到两个具有类似目的的术语:iostream 和 iostream.h 。本指南旨在阐明两者之间的根本区别。iostream.h:已弃用的旧版本iostream.h 是 C 库中的一个头文件,它提供一组输入/输出函数。对于...
    编程 发布于2024-11-07
  • VLONE Clothing:重新定义都市时尚的街头服饰品牌
    VLONE Clothing:重新定义都市时尚的街头服饰品牌
    VLONE 是少数几个在快速变化的市场中取得超越街头服饰行业所能想象的成就的品牌之一。 VLONE 由 A$AP Mob 集体的电影制片人之一 A$AP Bari 创立,现已发展成为一个小众项目,有时甚至成为都市时尚界的国际知名品牌。 VLONE 凭借大胆的图案、深厚的文化联系和限量版发售,在时尚界...
    编程 发布于2024-11-07
  • 如何使用PDO查询单行中的单列?
    如何使用PDO查询单行中的单列?
    使用 PDO 查询单行中的单列处理针对单行中特定列的 SQL 查询时,通常需要检索直接取值,无需循环。要使用 PDO 完成此操作,fetchColumn() 方法就派上用场了。fetchColumn() 的语法为:$col_value = $stmt->fetchColumn([column_...
    编程 发布于2024-11-07
  • 我是如何构建 PeerSplit:一款免费的点对点费用分摊应用程序 — 从构思到发布仅需数周时间
    我是如何构建 PeerSplit:一款免费的点对点费用分摊应用程序 — 从构思到发布仅需数周时间
    我构建了 PeerSplit——一个免费的、点对点的 Splitwise 替代品——从想法到发布仅用了两周时间! PeerSplit 是一款本地优先的应用程序,用于分配团体费用。它可以离线工作,100% 免费且私密,不需要注册或任何个人数据。 以下是我如何构建它以及我在此过程中学到的一切。 ...
    编程 发布于2024-11-07

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3