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

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

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

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]删除
最新教程 更多>
  • 版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    在时间戳列上使用current_timestamp或MySQL版本中的current_timestamp或在5.6.5 此限制源于遗留实现的关注,这些限制需要对当前的_timestamp功能进行特定的实现。 创建表`foo`( `Productid` int(10)unsigned not n...
    编程 发布于2025-05-18
  • 表单刷新后如何防止重复提交?
    表单刷新后如何防止重复提交?
    在Web开发中预防重复提交 在表格提交后刷新页面时,遇到重复提交的问题是常见的。要解决这个问题,请考虑以下方法: 想象一下具有这样的代码段,看起来像这样的代码段:)){ //数据库操作... 回声“操作完成”; 死(); } ?> ...
    编程 发布于2025-05-18
  • 解决Spring Security 4.1及以上版本CORS问题指南
    解决Spring Security 4.1及以上版本CORS问题指南
    弹簧安全性cors filter:故障排除常见问题 在将Spring Security集成到现有项目中时,您可能会遇到与CORS相关的错误,如果像“访问Control-allo-allow-Origin”之类的标头,则无法设置在响应中。为了解决此问题,您可以实现自定义过滤器,例如代码段中的MyFi...
    编程 发布于2025-05-18
  • 在UTF8 MySQL表中正确将Latin1字符转换为UTF8的方法
    在UTF8 MySQL表中正确将Latin1字符转换为UTF8的方法
    在UTF8表中将latin1字符转换为utf8 ,您遇到了一个问题,其中含义的字符(例如,“jáuòiñe”)在utf8 table tabled tablesset中被extect(例如,“致电。为了解决此问题,您正在尝试使用“ mb_convert_encoding”和“ iconv”转换受...
    编程 发布于2025-05-18
  • 如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    postgresql:为每个唯一标识符在postgresql中提取最后一行,您可能需要遇到与数据集合中每个不同标识的信息相关的信息。考虑以下数据:[ 1 2014-02-01 kjkj 在数据集中的每个唯一ID中检索最后一行的信息,您可以在操作员上使用Postgres的有效效率: id dat...
    编程 发布于2025-05-18
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法表示的字符串时,您可能会遇到错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && ...
    编程 发布于2025-05-18
  • `console.log`显示修改后对象值异常的原因
    `console.log`显示修改后对象值异常的原因
    foo = [{id:1},{id:2},{id:3},{id:4},{id:id:5},],]; console.log('foo1',foo,foo.length); foo.splice(2,1); console.log('foo2', foo, foo....
    编程 发布于2025-05-18
  • 如何高效地在一个事务中插入数据到多个MySQL表?
    如何高效地在一个事务中插入数据到多个MySQL表?
    mySQL插入到多个表中,该数据可能会产生意外的结果。虽然似乎有多个查询可以解决问题,但将从用户表的自动信息ID与配置文件表的手动用户ID相关联提出了挑战。使用Transactions和last_insert_id() 插入用户(用户名,密码)值('test','test...
    编程 发布于2025-05-18
  • 如何使用组在MySQL中旋转数据?
    如何使用组在MySQL中旋转数据?
    在关系数据库中使用mySQL组使用mySQL组进行查询结果,在关系数据库中使用MySQL组,转移数据的数据是指重新排列的行和列的重排以增强数据可视化。在这里,我们面对一个共同的挑战:使用组的组将数据从基于行的基于列的转换为基于列。 Let's consider the following ...
    编程 发布于2025-05-18
  • 如何从PHP中的数组中提取随机元素?
    如何从PHP中的数组中提取随机元素?
    从阵列中的随机选择,可以轻松从数组中获取随机项目。考虑以下数组:; 从此数组中检索一个随机项目,利用array_rand( array_rand()函数从数组返回一个随机键。通过将$项目数组索引使用此键,我们可以从数组中访问一个随机元素。这种方法为选择随机项目提供了一种直接且可靠的方法。
    编程 发布于2025-05-18
  • Java的Map.Entry和SimpleEntry如何简化键值对管理?
    Java的Map.Entry和SimpleEntry如何简化键值对管理?
    A Comprehensive Collection for Value Pairs: Introducing Java's Map.Entry and SimpleEntryIn Java, when defining a collection where each element com...
    编程 发布于2025-05-18
  • PHP未来:适应与创新
    PHP未来:适应与创新
    PHP的未来将通过适应新技术趋势和引入创新特性来实现:1)适应云计算、容器化和微服务架构,支持Docker和Kubernetes;2)引入JIT编译器和枚举类型,提升性能和数据处理效率;3)持续优化性能和推广最佳实践。 引言在编程世界中,PHP一直是网页开发的中流砥柱。作为一个从1994年就开始发展...
    编程 发布于2025-05-18
  • 在Python中如何创建动态变量?
    在Python中如何创建动态变量?
    在Python 中,动态创建变量的功能可以是一种强大的工具,尤其是在使用复杂的数据结构或算法时,Dynamic Variable Creation的动态变量创建。 Python提供了几种创造性的方法来实现这一目标。利用dictionaries 一种有效的方法是利用字典。字典允许您动态创建密钥并分...
    编程 发布于2025-05-18
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。要解决此问题并确保在后续页面访问中执行脚本,Firefox用户应设置一个空功能。 警报'); }; alert('inline Alert')...
    编程 发布于2025-05-18
  • MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    在两个条件下插入或更新或更新 solution:的答案在于mysql的插入中...在重复键更新语法上。如果不存在匹配行或更新现有行,则此功能强大的功能可以通过插入新行来进行有效的数据操作。如果违反了唯一的密钥约束。实现所需的行为,该表必须具有唯一的键定义(在这种情况下为'名称'...
    编程 发布于2025-05-18

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

Copyright© 2022 湘ICP备2022001581号-3