需要在操作系统中更改暗/亮模式以强制刷新外部 SVG 文件
Posted
技术标签:
【中文标题】需要在操作系统中更改暗/亮模式以强制刷新外部 SVG 文件【英文标题】:Need dark/light mode change in OS to force refresh of external SVG files 【发布时间】:2022-01-10 21:34:19 【问题描述】:我的网站使用了许多外部 SVG 文件,它们在 SVG 文件本身中带有自己的 <style>
元素。我在主网站 CSS 和中有暗模式媒体查询在 SVG 文件自己的样式中:@media (prefers-color-scheme:light)
和 @media (prefers-color-scheme:dark)
在初始加载或硬刷新时,一切都按预期工作,网站 CSS 和 SVG CSS 都会根据系统操作系统设置为暗模式还是亮模式来加载适当的样式。
但是,如果我在操作系统中切换模式,只会更新网站 CSS,而不是外部 SVG 文件的 CSS。
所以,我需要硬重新加载缓存的 SVG 图像,或者只是刷新 SVG CSS。
我在 javascript 中设置了一个事件侦听器,可以正确检测操作系统模式更改,但我不知道如何在操作系统暗/亮模式更改时触发 SVG 刷新。我搜索了高低,但不知道如何做到这一点,希望以最简单、最优雅的方式。
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e =>
// WHAT GOES HERE TO REFRESH SVGs TO CORRECTLY REFLECT OS MODE?
);
window.location.reload(true);
不会硬重新加载缓存文件。我不确定cache.delete
在这里是否合适,或者我将如何使用它来强制重新加载所有 SVG 图像 (<img src="whatever.svg"/>
)。也许我忽略了另一种方法。
感谢您的帮助。
【问题讨论】:
Do any of these suggestions help? 是否可以选择将 SVG 作为背景图像?因为如果是这样,您可以使用@media (prefers-color-scheme:light) svgcontainer background-image: url(light.svg);
和@media (prefers-color-scheme:dark) background-image: url(dark.svg);
@PaulLeBeau:我之前看到过,我想弄清楚如何使用 forEach 循环为多个图像实现它。一旦我这样做并测试它,我就会知道在这种情况下缓存破坏器是否有效。
@mrmonsieur:该网站非常庞大且复杂,将大量图标重建为背景图像将是一项艰巨的任务,而且许多图标是由管理员在 CMS 界面中的文本中手工编码的,并且html 需要对他们尽可能简单和用户友好。我需要一个通过 javascript 的解决方案。谢谢。
也许可以使用 Web 组件加载这些 SVG,以便全局 CSS 可以设置它们的样式:dev.to/dannyengelman/…
【参考方案1】:
这就是诀窍,几行 javascript。首先,在页面加载时,识别所有 SVG 图像并确定当前的prefers-color-scheme
主题。然后,检测该主题何时更改,并将动态缓存中断器附加到这些文件名,这会强制 SVG 重新加载。
// Dark mode changes needs cache refresh for external SVG file CSS.
allImg = document.querySelectorAll('img[src$=".svg"');
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
thisMode = 'dark';
else
thisMode = 'light';
window.matchMedia('(prefers-color-scheme: '+ thisMode + ')').addEventListener('change', e =>
allImg.forEach(img =>
imgTime = Date.now();
newImgSrc = img.src + '?' + imgTime;
img.src = newImgSrc;
);
);
21 年 12 月 13 日更新了原始答案。现在,强制重新加载 SVG 的 cachebuster 仅在模式更改后调用,而不是在每次页面加载时调用。
21 年 12 月 19 日更新:此解决方案不适用于 Safari(a known bug,其中 Safari 不尊重 SVG 文件 CSS 中的 prefers-color-scheme 媒体查询)。对于 Safari,我编写了额外的 JS,用于在页面加载时检测 Safari,使用上面的 prefers-color-scheme 条件,如果操作系统是暗模式,则将所有 SVG 文件名从“image.svg”替换为“image-dark.svg” ,调用每个 SVG 的浅色或深色版本。当操作系统深色/浅色主题更改时,它还会在 Safari 中重新加载页面。如果 Apple 修复了这个错误,我可以使用上面更简单的解决方案。
【讨论】:
这种方法当然有一个缺点。每个 SVG 将在第一个页面加载时下载两次。如果您没有 @david 的约束,最好将查询字符串 ("?" + imgTime
) 烘焙到原始 URL 中。
@PaulLeBeau:是的,由于这里的限制,将缓存破坏程序烘焙到原始 IMG SRC 中是不可行的。该站点依靠 HTML 知识有限的管理员将 SVG 手动插入 CMS 文本区域。幸运的是,SVG 为 1kb 或更小,任何给定页面上最多只有大约 10 个唯一的 SVG。以上是关于需要在操作系统中更改暗/亮模式以强制刷新外部 SVG 文件的主要内容,如果未能解决你的问题,请参考以下文章