」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > API 每小時資料的響應式 JavaScript 輪播

API 每小時資料的響應式 JavaScript 輪播

發佈於2024-11-06
瀏覽:673

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 spa...
    程式設計 發佈於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