API 每小时数据的响应式 JavaScript 轮播
我差点把一个不完整的解决方案误认为是一个已完成的解决方案,然后继续研究我的天气应用程序的其他部分!在制作应该显示 12 小时天气的轮播时,我想添加一项功能,该功能将有助于在当天结束时获取第二天的时间。然而,轮播并没有过渡到第二天,而是不断循环回到当天的开始时间,我错误地认为任务已经完成。哎呀!
最初的挑战
我考虑过两个“for 循环”,但我不认为“j”打印整个“i”长度的所有元素是正确的。我在网上找到了很多关于“圆形数组”中模数运算符的使用的博客,但我不知道这对我的情况有什么帮助。我需要循环当前一天的时间,然后在时间重置为零后切换到第二天。发生了很多事情,我需要使其更加简洁,并将所有内容都放在一个函数中。艰难的!
认识不完整的解决方案和错误
我在网上发现了一些非常酷的东西,它可能会解决我的一个大问题。它帮助我了解模数运算符如何适用于圆形数组。这是网站上的示例:
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 <p><strong>结果如下:</strong><br> 第一天:星期一<br> 第 2 天:星期二<br> ...<br><br> 我想要的是,它不应该返回到 <strong>daysofweek</strong> 数组,并从 <strong>'monday'</strong> 开始,而是应该转到一个完全不同的数组。因此,我将代码带到代码编辑器中并进行了一些更改。首先,我创建了一个名为 <strong>‘currentindex’</strong> 的变量,并将模数运算存储在其中。然后我将其记录到控制台。 6点后重置并再次变为零。 </p> <p>但是,我将错误的变量记录到控制台。因为,如果我这样编写 if 条件: <strong>if(currentindex === 0)</strong>,它实际上会在循环开始时移向新数组。所以,现在我改为记录“索引”,终于找到了答案!为了测试新代码,我为 <strong>‘months’</strong> 创建了一个新数组,然后尝试进行切换。但我又犯了一个错误——让我告诉你:<br></p>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 <p>记录“jan”后,它切换回原始数组。错误是严格的相等检查,我应该使用<strong>‘大于或等于’</strong>来代替。当我插入它时,它成功切换到新阵列!</p> <p>现在,我希望循环从当前小时开始并继续而不停止,并使用标记在数组之间切换。该标记将是模运算符而不是数组的长度。我还可以使用数组的长度,在本例中为 9(对于我的 api 数据,为 24),但我现在坚持使用硬编码值 9。</p> <p><strong>当前索引 = (当前索引 + 1) % 9</strong></p> <p>这条线允许我在循环期间从第一天切换到第二天而不停止它。这是另一个试验(我更新了数组以类似于 api 结果):<br></p>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 <p>注意结果中一些有趣的东西:</p> <p>索引为 5,dayone 为 6,i 为 0<br> 索引为 6,dayone 为 7,i 为 1<br> 索引是 7,dayone 是 8,i 是 2<br> 索引是 8,dayone 是 9,i 是 3<br> 索引是 9,dayone 是 10,i 是 4<br> 索引为 0,dayone 为 1,i 为 5<br><strong>索引为 0,daytwo 为 11</strong><br> 索引为 1,dayone 为 12,i 为 6<br> 索引为 2,dayone 为 13,i 为 7<br> 索引为 3,dayone 为 14,i 为 8<br> 索引为 4,dayone 为 15,i 为 9</p> <p>这里的问题是,即使将时间从 dayone 切换到 daytwo 后,日志在日志语句中仍然引用 dayone。发生这种情况是因为日志记录语句被硬编码为“dayone”,即使数组已切换到 daytwo。</p> <p>为了解决这个问题,我们可以为这一天设置另一个标记,并使其在切换数组的同时进行切换。我将把 dayone 和 daytwo 分别切换为“星期一”和“星期二”:<br></p>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; let day = 'monday'; function cycledays(currenthour) { let currentindex = currenthour; for (let i = 0; i <p>我的代码快完成了。使此代码有效的两个重要更改是跟踪日期并将模数运算置于 for 循环内。 </p> <p>最后,我可以为从 api 检索的 3 天数据构建代码,这是精炼版本:<br></p>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 <p class="next-day">next day</p> <p class="next-hour-num">${hournum}</p> @@##@@ <p class="temp">${hourdata.temp_c}°c</p> `); } else { displayhours.push(` <div class="hour-${i} child"> <p class="hour-num">${hournum}</p> @@##@@ <p class="temp">${hourdata.temp_c}°c</p> </div> `); } index = (index + 1) % 24; if(index === 0 && dayindex === 0){ dayindex = 1; hours = gethoursforday(dayindex) } } //for loop displayhours = displayhours.join(''); hourcontainer.innerhtml = displayhours; … };创建动态 html 元素
我们来谈谈生成 12 个 div。我无法想象如何获取父 div 两侧的按钮,而 12 小时就漂浮在它们之间。如果我要在与按钮相同的父级中生成 12 个 div,则按钮元素将需要与 12 个 div 不同的对齐设置。
只有让他们拥有自己的容器才有意义。我花了一段时间才弄清楚这一点——实际上我不得不睡觉。然后第二天,我输入 .btn-container 并点击 tab,从那里开始,一切都点击了。我在 john smilga 的教程中看到了每个分组的项目以及它们自己的容器位于父容器内,直到我开始设计 24 小时容器时我才知道为什么需要这样的分组。这真是一个“陷阱时刻”。
现在又出现了一个困扰了好几天的问题。我在教程中设计的滑块并不像这些 div 那样具有挑战性。在教程中,有一个简单的翻译值,但现在我有很多问题。在较小的屏幕上,div 粘在一起,开始看起来像意大利面条。
而且,当我使用一个简单的translatex属性时,这意味着当我“猜测”像素时,div完全向左平移后留下了很多空间。这意味着他们平移的宽度超过了它们的总宽度。我需要找到一个合适的值来确保 div 完全停止在末尾而不留下额外的空间。找了好久,发现一个博客,提供了各种解决方案。
有很多解决方案。其中一些使用了模运算符,这让我想起了在“for 循环”中切换日期时应用的循环数组逻辑。这里有很多评论使用了 math.min 和 math.max。这基本上会使容器平移,直到到达其长度的末端。出色的!那么没有更多的空白了吗? 没那么快...
与这些示例不同的一点是我的容器最初会显示 3 或 4 个 div。所以,当offset为0时,父容器中已经有一定的长度了。
他们通过添加数字 1 来显示图像。因此,他们的轮播会根据数组中图像的索引号向前滑动 1 张图像。例如,如果容器中有 10 个图像,我们向 currentimage 变量添加 1 个图像,则 math.min 计算出的值将为“1”。然后,当我们添加另一个“1”时,当前图像将是 2,并且 math.min 的值将是 2,因为 2 mod 10 是 2。这个特定的示例将改变滑块的游戏我正在努力做。这是引起我注意的代码:
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);在评论中发现 richard kichenama 解决方案的巧妙之处在于使用 math.max 来确保值不会低于 0,并使用 math.min 来计算平移值,直到达到最大长度图像数组。
现在,我该如何解决空白问题?我必须考虑所有子 div 的边距,并将它们加在一起以获得子 div 的整个长度。然后,一旦到达最后一个子项,滑块就应该停止移动。这意味着总宽度是所有子项宽度加上边距的总和。
但是,我遇到了另一个问题:一些 div 已经显示在容器中,这让我再次陷入困境。幸运的是,我的一个朋友救了我。与他们讨论问题后,我的理解如下:
我无法考虑子 div 的整个长度。剩下的空白区域几乎与容器的长度一样多。解决方案是从子容器的总长度(包括边距)中减去父容器的长度。这一调整有助于解决空白问题——唷!
一些代码示例有一个类似于“计数器”的变量。它充当翻译属性的“计数器”。当这个变量增加时,翻译属性增加等等。我将下一个和上一个按钮的 math.min 和 math.max 属性分开。这样更有帮助,也更容易。
在我引用的示例中,代码使用数组的长度来确定滑动距离,但是,根据我之前与朋友的讨论,我需要考虑空白,所以我必须减去容器。这样,我确保了我的 div 只能移动特定的量,避免了末尾的额外空间。
另外,感谢 john smilga 的教程,我学会了如何获取项目的宽度、高度、顶部属性。应用正确的值是一项艰巨的任务,找出某些值是字符串并且需要将其转换为数字也是一项艰巨的任务。我在谷歌上轻松找到了这一点,并被介绍给‘parsefloat’。
我还发现了另一个有用的资源,它教我如何在大屏幕上仅显示三个 div,在小屏幕上显示两个 div。诀窍是将容器宽度的 100% 除以 3(对于小屏幕则为 2)并减去边距。这允许大小相同的 div 完美地适合容器(太聪明了!)。最后,要查看最终的功能,请访问我的github。这是我的存储库的链接。
用于调整大小的窗口事件侦听器对于解决容器中的对齐问题至关重要。它通过重置调整大小时的偏移量解决了“无样式内容的 flash”(fouc) 问题。我必须感谢我的朋友帮助我了解如何计算 maxoffset——这真的改变了游戏规则。
最后,向所有经验丰富的开发人员大声喊叫:您分享的每句话都会对这个领域的新手有所帮助。因此,请继续发布您这边的信息,因为我们正在另一边等待渴望了解。谢谢你!
以上就是API 每小时数据的响应式 JavaScript 轮播的详细内容,更多请关注其它相关文章!