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

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

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

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]删除
最新教程 更多>
  • Python元类工作原理及类创建与定制
    Python元类工作原理及类创建与定制
    python中的metaclasses是什么? Metaclasses负责在Python中创建类对象。就像类创建实例一样,元类也创建类。他们提供了对类创建过程的控制层,允许自定义类行为和属性。在Python中理解类作为对象的概念,类是描述用于创建新实例或对象的蓝图的对象。这意味着类本身是使用类关...
    编程 发布于2025-04-27
  • 将图片浮动到底部右侧并环绕文字的技巧
    将图片浮动到底部右侧并环绕文字的技巧
    在Web设计中围绕在Web设计中,有时可以将图像浮动到页面右下角,从而使文本围绕它缠绕。这可以在有效地展示图像的同时创建一个吸引人的视觉效果。 css位置在右下角,使用css float and clear properties: img { 浮点:对; ...
    编程 发布于2025-04-27
  • Python中何时用"try"而非"if"检测变量值?
    Python中何时用"try"而非"if"检测变量值?
    使用“ try“ vs.” if”来测试python 在python中的变量值,在某些情况下,您可能需要在处理之前检查变量是否具有值。在使用“如果”或“ try”构建体之间决定。“ if” constructs result = function() 如果结果: 对于结果: ...
    编程 发布于2025-04-27
  • 如何处理PHP文件系统功能中的UTF-8文件名?
    如何处理PHP文件系统功能中的UTF-8文件名?
    在PHP的Filesystem functions中处理UTF-8 FileNames 在使用PHP的MKDIR函数中含有UTF-8字符的文件很多flusf-8字符时,您可能会在Windows Explorer中遇到comploreer grounder grounder grounder gro...
    编程 发布于2025-04-27
  • 如何在GO编译器中自定义编译优化?
    如何在GO编译器中自定义编译优化?
    在GO编译器中自定义编译优化 GO中的默认编译过程遵循特定的优化策略。 However, users may need to adjust these optimizations for specific requirements.Optimization Control in Go Compi...
    编程 发布于2025-04-27
  • 使用jQuery如何有效修改":after"伪元素的CSS属性?
    使用jQuery如何有效修改":after"伪元素的CSS属性?
    在jquery中了解伪元素的限制:访问“ selector 尝试修改“:”选择器的CSS属性时,您可能会遇到困难。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    编程 发布于2025-04-27
  • 人脸检测失败原因及解决方案:Error -215
    人脸检测失败原因及解决方案:Error -215
    错误处理:解决“ error:( - 215)!empty()in Function openCv in Function MultSiscale中的“检测”中的错误:在功能检测中。”当Face Cascade分类器(即面部检测至关重要的组件)未正确加载时,通常会出现此错误。要解决此问题,必须...
    编程 发布于2025-04-27
  • 为什么PYTZ最初显示出意外的时区偏移?
    为什么PYTZ最初显示出意外的时区偏移?
    与pytz 最初从pytz获得特定的偏移。例如,亚洲/hong_kong最初显示一个七个小时37分钟的偏移: 差异源利用本地化将时区分配给日期,使用了适当的时区名称和偏移量。但是,直接使用DateTime构造器分配时区不允许进行正确的调整。 example pytz.timezone(...
    编程 发布于2025-04-27
  • CSS强类型语言解析
    CSS强类型语言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    编程 发布于2025-04-27
  • 在JavaScript中如何获取实际渲染的字体,当CSS字体属性未定义时?
    在JavaScript中如何获取实际渲染的字体,当CSS字体属性未定义时?
    Accessing Actual Rendered Font when Undefined in CSSWhen accessing the font properties of an element, the JavaScript object.style.fontFamily and objec...
    编程 发布于2025-04-27
  • 反射动态实现Go接口用于RPC方法探索
    反射动态实现Go接口用于RPC方法探索
    在GO 使用反射来实现定义RPC式方法的界面。例如,考虑一个接口,例如:键入myService接口{ 登录(用户名,密码字符串)(sessionId int,错误错误) helloworld(sessionid int)(hi String,错误错误) } 替代方案而不是依靠反射...
    编程 发布于2025-04-27
  • 如何在无序集合中为元组实现通用哈希功能?
    如何在无序集合中为元组实现通用哈希功能?
    在未订购的集合中的元素要纠正此问题,一种方法是手动为特定元组类型定义哈希函数,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    编程 发布于2025-04-27
  • MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    在两个条件下插入或更新或更新 solution:的答案在于mysql的插入中...在重复键更新语法上。如果不存在匹配行或更新现有行,则此功能强大的功能可以通过插入新行来进行有效的数据操作。如果违反了唯一的密钥约束。实现所需的行为,该表必须具有唯一的键定义(在这种情况下为'名称'...
    编程 发布于2025-04-27
  • 如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    How to Resolve "General error: 2006 MySQL server has gone away" While Inserting RecordsIntroduction:Inserting data into a MySQL database can...
    编程 发布于2025-04-27
  • 在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在C中的显式删除 在C中的动态内存分配时,开发人员通常会想知道是否有必要在heap-procal extrable exit exit上进行手动调用“ delete”操作员,但开发人员通常会想知道是否需要手动调用“ delete”操作员。本文深入研究了这个主题。 在C主函数中,使用了动态分配变量(H...
    编程 发布于2025-04-27

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

Copyright© 2022 湘ICP备2022001581号-3