一直想让WordPress JustNews主题,可以根据时间自动切换夜间模式。比如,白天自动日间模式,晚上自动夜间模式。而且,用户可以点击切换夜间模式。目前JustNews主题后台,只能设置跟随系统自动夜间(每个设备不都是有夜间深色模式吗,就跟随系统设置自动夜间),或者通过按钮切换夜间模式。两个只能二选一。
我寻思问问Open Ai ChatGPT是否可以实现,根据太阳落山时间,自动切换夜间模式。你始终要相信,ChatGPT可以办到,只要你的提问方式有效。下面,我们就来演示下,如何向ChatGPT有效提问,并在文末给出大家最终实现的代码。也就是说,本文最终实现了所需要的功能,而且很完美。
首先,我们要观察下JustNews主题的夜间模式,在前端的变化状态。详情如下图
提问前准备,夜间模式具体变化
我们发现,夜间模式有如下变动:
- body区域class中新增内容:style-for-dark
- 切换按钮部分dark-style-toggle新增:active
- 切换图标本身变成:#wi-moon-fill
有了如上相关内容,我们就可以向ChatGPT提问了。下面,我们以对话的方式,给出部分与ChatGPT的聊天内容
有效的向ChatGPT提问
古哥:
我的网站有一个白天夜间切换按钮,它的class是这样定义的:class=”dark-style-toggle”。白天时,是这样class=”dark-style-toggle”。晚上时:class=”dark-style-toggle active”。此外,晚上时,还会在body的class中添加一个style-for-dark。我现在想实现,每天太阳升起时,自动白天模式。太阳落山,自动夜间模式。
ChatGPT:
要实现这个功能,你需要用到 JavaScript 来检测当前时间,并根据时间来自动切换网站的模式。以下是一个实现的示例代码:
// 获取切换按钮和body元素 const toggleBtn = document.querySelector('.dark-style-toggle'); const body = document.body; // 获取当前时间 const now = new Date(); const sunrise = new Date(); const sunset = new Date(); // 设置日出和日落时间,这里以 6:00 和 18:00 为例 sunrise.setHours(6); sunrise.setMinutes(0); sunset.setHours(18); sunset.setMinutes(0); // 检测当前时间,并根据时间来切换网站的模式 if (now > sunrise && now < sunset) { body.classList.remove('style-for-dark'); toggleBtn.classList.remove('active'); } else { body.classList.add('style-for-dark'); toggleBtn.classList.add('active'); }
你可以将上述代码添加到你的网站 JavaScript 文件中,或直接将其添加到页面的
<script>
标签中。这样,在每次加载网站时,JavaScript 会自动检测当前时间并切换网站的模式。
明白人应该都能看出来,我少提了一个需求,毕竟需求都是一步一步提的,当然不可能有人一次性就提出所有需求,我们继续提需求。
古哥:
我发现还有这个切换图标本身也会变化,白天是这样:<i class=”wpcom-icon wi”><svg aria-hidden=”true”><use xlink:href=”#wi-sun-fill”></use></svg></i>。晚上是这样:<i class=”wpcom-icon wi”><svg aria-hidden=”true”><use xlink:href=”#wi-moon-fill”></use></svg></i>
ChatGPT:
好的,你需要在 JavaScript 中找到切换按钮对应的图标元素,并根据当前模式来更改其内容。以下是更新图标的示例代码:
// 获取切换按钮和对应的图标元素 const toggleBtn = document.querySelector('.dark-style-toggle'); const icon = toggleBtn.querySelector('svg use'); // 获取当前时间 const now = new Date(); const sunrise = new Date(); const sunset = new Date(); // 设置日出和日落时间,这里以 6:00 和 18:00 为例 sunrise.setHours(6); sunrise.setMinutes(0); sunset.setHours(18); sunset.setMinutes(0); // 检测当前时间,并根据时间来切换网站的模式和图标 if (now > sunrise && now < sunset) { body.classList.remove('style-for-dark'); toggleBtn.classList.remove('active'); icon.setAttribute('xlink:href', '#wi-sun-fill'); } else { body.classList.add('style-for-dark'); toggleBtn.classList.add('active'); icon.setAttribute('xlink:href', '#wi-moon-fill'); }
这段代码中,我们首先使用
toggleBtn.querySelector('svg use')
找到了对应的图标元素。然后,根据当前模式来使用icon.setAttribute('xlink:href', '...')
方法来更新该元素对应的xlink:href
属性,从而更改图标的内容。
细心的人,应该发现上述代码漏了个定义,可以跟第一次发我的代码比对下,就能发现漏了如下定义:const body = document.body;
。不过,这不是重点,我们继续。
代码BUG描述
古哥:
我手动设置白天模式后,再次访问是夜间模式没问题的。但是,每次访问它都会闪屏,也就是先白天,然后自动夜间。我不想让它闪屏
此刻开始,我就走上了一条不归路,差点走到死胡同。不过庆幸的是,最终解决了。起因是:我发现ChatGPT给我的答案满足了我的需求,它可以根据时间自动切换夜间模式了。但是,每次访问都会先是日间,然后秒变成夜间。这样就导致一个情况:晚上时,用户访问,总是出现一个闪屏的情况;就算用户二次访问也会有一个闪屏的情况。
ChatGPT:
这个问题是因为你的 JavaScript 代码在页面加载后执行,导致页面一开始是白天模式,然后 JS 代码再根据时间切换为夜间模式。为了解决这个问题,你可以使用 JavaScript 的
DOMContentLoaded
事件,让代码在页面完全加载后再执行。document.addEventListener('DOMContentLoaded', function() { // 获取切换按钮和对应的图标元素 const toggleBtn = document.querySelector('.dark-style-toggle'); const icon = toggleBtn.querySelector('svg use'); // 获取当前时间 const now = new Date(); const sunrise = new Date(); const sunset = new Date(); // 设置日出和日落时间,这里以 6:00 和 18:00 为例 sunrise.setHours(6); sunrise.setMinutes(0); sunset.setHours(18); sunset.setMinutes(0); // 检测当前时间,并根据时间来切换网站的模式和图标 if (now > sunrise && now < sunset) { body.classList.remove('style-for-dark'); toggleBtn.classList.remove('active'); icon.setAttribute('xlink:href', '#wi-sun-fill'); } else { body.classList.add('style-for-dark'); toggleBtn.classList.add('active'); icon.setAttribute('xlink:href', '#wi-moon-fill'); } });
这里使用
document.addEventListener('DOMContentLoaded', function() { ... })
来监听页面的 DOMContentLoaded 事件,然后将原本的代码放在回调函数中。这样,代码会在页面完全加载后才执行,就避免了页面闪屏的问题。
代码BUG源头分析
我又跟ChatGPT聊了很久,这里就不一一列举了,重点说下最终的解决过程吧。我查看JustNews源码,发现JustNews是通过本地存储实现的当前夜间模式记录。所以,它提前保存了当前夜间模式,每次代码又给它强行切换夜间模式,导致出现了闪屏。
所以,我们可以继续提问了。
古哥:
我发现,网站本身是通过window.localStorage实现的白天夜间状态记忆,你可以照着如下代码完善一下吗
<script> if (window.localStorage) { var dark = localStorage.getItem('darkStyle'); var toggle = document.querySelector('.dark-style-toggle'); if (dark == 1 && !toggle.classList.contains('active')) { document.body.classList.add('style-for-dark'); toggle.classList.add('active'); toggle.querySelector('use').setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#wi-moon-fill'); } else if (dark == 0 && toggle.classList.contains('active')) { document.body.classList.remove('style-for-dark'); toggle.classList.remove('active'); toggle.querySelector('use').setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#wi-sun-fill'); } } </script>
ChatGPT:
你可以将 localStorage 的状态记录与自动切换的代码结合起来,这样可以保持记忆并实现自动切换的功能。
以下是结合 localStorage 记录状态的代码示例:
document.addEventListener('DOMContentLoaded', function() { // 隐藏整个页面 document.documentElement.style.visibility = 'hidden'; // 获取切换按钮和对应的图标元素 const toggleBtn = document.querySelector('.dark-style-toggle'); const icon = toggleBtn.querySelector('svg use'); // 获取当前时间 const now = new Date(); const sunrise = new Date(); const sunset = new Date(); // 设置日出和日落时间,这里以 6:00 和 18:00 为例 sunrise.setHours(6); sunrise.setMinutes(0); sunset.setHours(18); sunset.setMinutes(0); // 检测当前时间,并根据时间来切换网站的模式和图标 if (now > sunrise && now < sunset) { body.classList.remove('style-for-dark'); toggleBtn.classList.remove('active'); icon.setAttribute('xlink:href', '#wi-sun-fill'); localStorage.setItem('darkStyle', 0); // 记录为白天模式 } else { body.classList.add('style-for-dark'); toggleBtn.classList.add('active'); icon.setAttribute('xlink:href', '#wi-moon-fill'); localStorage.setItem('darkStyle', 1); // 记录为夜间模式 } // 显示整个页面 document.documentElement.style.visibility = 'visible'; }); // 监听切换按钮的点击事件 const toggleBtn = document.querySelector('.dark-style-toggle'); toggleBtn.addEventListener('click', function() { // 切换页面模式 body.classList.toggle('style-for-dark'); toggleBtn.classList.toggle('active'); if (toggleBtn.classList.contains('active')) { icon.setAttribute('xlink:href', '#wi-moon-fill'); localStorage.setItem('darkStyle', 1); // 记录为夜间模式 } else { icon.setAttribute('xlink:href', '#wi-sun-fill'); localStorage.setItem('darkStyle', 0); // 记录为白天模式 } });
在这个示例中,我们通过
localStorage
记录网站的模式状态。在页面加载时,根据当前时间判断是白天模式还是夜间模式,并记录到localStorage
中。同时在切换按钮的点击事件中,也会根据当前的状态来进行相应的切换并记录到localStorage
中。这样可以实现记忆和自动切换的功能。
接着,我们又聊了很久,因为它又顾及到了我曾经的提问:闪屏问题,所以它一直想给代码中添加显示整个页面的相关js。我想这个ChatGPT大概是走歪了。此外,本文的篇幅也确实太长了,下面直接进入最终答案的版本。
最终实现的完整代码
古哥:
因为我网站本身就有点击判断,我不需要你再加个点击判断。这样两个点击,就相当于没点击了。
不知道你们理不理解这句话,就相当于JustNews主题本身就有点击切换夜间模式的功能,这个ChatGPT再给我加个监听切换按钮的点击事件,就相当于点一次按钮相当于点两次,就是没点的意思。也就是说,加了ChatGPT给的代码,我倒是可以实现夜间模式自动切换不闪屏的问题了,但是JustNews主题自带的切换按钮整个废掉了。
ChatGPT:
明白了,那么你可以尝试以下这个代码,它会在页面加载时根据时间自动设置白天或夜间模式,同时也会根据用户点击的切换按钮来切换模式,而不会与原来的点击判断冲突:
// 获取切换按钮和对应的图标元素 const toggleBtn = document.querySelector('.dark-style-toggle'); const icon = toggleBtn.querySelector('svg use'); const body = document.body; // 获取当前时间 const now = new Date(); const sunrise = new Date(); const sunset = new Date(); // 设置日出和日落时间,这里以 6:00 和 18:00 为例 sunrise.setHours(6); sunrise.setMinutes(0); sunset.setHours(18); sunset.setMinutes(0); // 检测当前时间,并根据时间来切换网站的模式和图标 if (now > sunrise && now < sunset) { body.classList.remove('style-for-dark'); toggleBtn.classList.remove('active'); icon.setAttribute('xlink:href', '#wi-sun-fill'); localStorage.setItem('darkStyle', 0); // 记录为白天模式 } else { body.classList.add('style-for-dark'); toggleBtn.classList.add('active'); icon.setAttribute('xlink:href', '#wi-moon-fill'); localStorage.setItem('darkStyle', 1); // 记录为夜间模式 } // 监听切换按钮的点击事件 toggleBtn.addEventListener('click', function() { // 切换页面模式 body.classList.toggle('style-for-dark'); toggleBtn.classList.toggle('active'); if (toggleBtn.classList.contains('active')) { icon.setAttribute('xlink:href', '#wi-moon-fill'); localStorage.setItem('darkStyle', 1); // 记录为夜间模式 } else { icon.setAttribute('xlink:href', '#wi-sun-fill'); localStorage.setItem('darkStyle', 0); // 记录为白天模式 } });
这段代码会在页面加载时自动根据当前时间设置白天或夜间模式,并在用户点击切换按钮时切换模式,同时还记录了用户的模式偏好,方便下次访问时自动设置模式。
结果,ChatGPT又给我加上了监听切换按钮的点击事件,正准备开骂,我意识到一个问题:这次给的代码写的很规范,判断了当前事件,修改了body、切换图标、切换状态等三个我在开篇提到的关键点,而且,将夜间状态存储到了本地存储中。重点是它不再关注闪屏问题了。那么这段代码只要删掉整个监听切换按钮的点击事件这部分代码就可以了。所以,最终,我们拿到了可用的完整代码如下:
<script>
// 获取切换按钮和对应的图标元素
const toggleBtn = document.querySelector('.dark-style-toggle');
const icon = toggleBtn.querySelector('svg use');
const body = document.body;
// 获取当前时间
const now = new Date();
const sunrise = new Date();
const sunset = new Date();
// 设置日出和日落时间,这里以 6:00 和 18:00 为例
sunrise.setHours(6);
sunrise.setMinutes(0);
sunset.setHours(18);
sunset.setMinutes(0);
// 检测当前时间,并根据时间来切换网站的模式和图标
if (now > sunrise && now < sunset) {
body.classList.remove('style-for-dark');
toggleBtn.classList.remove('active');
icon.setAttribute('xlink:href', '#wi-sun-fill');
localStorage.setItem('darkStyle', 0); // 记录为白天模式
} else {
body.classList.add('style-for-dark');
toggleBtn.classList.add('active');
icon.setAttribute('xlink:href', '#wi-moon-fill');
localStorage.setItem('darkStyle', 1); // 记录为夜间模式
}
</script>
如上,就是实现JustNews主题夜间模式根据时间自动切换的JavaScript代码了,并且主题自带的切换还是有效的。也就是说用户访问时,根据当前时间,自动确定是否开启夜间模式,并且把状态保存到本地存储(解决闪屏问题)中,而且用户还可以通过主题自带的按钮切换夜间模式。
希望各位可以通过本文了解到一定的ChatGPT提问技巧。如果你有相关代码需求,可以向我支付¥30,我来帮你提问。当然,你也可以纯为了支持我,给我打赏,以支持我高昂的服务器费用。
原创文章,作者:古哥,转载需经过作者授权同意,并附上原文链接:https://iymark.com/articles/4294.html