switch img src according to the theme

This commit is contained in:
Lyric
2024-02-21 17:02:43 -08:00
parent f489b7b9b6
commit bcc5e97fd9
6 changed files with 150 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
<template>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
const currentTheme = ref('light');
const props = defineProps({
base: {
type: String,
required: true,
},
res: {
type: String,
required: true,
},
alt: {
type: String,
default: "",
},
});
const imgUrl = computed(() => {
if (isDarkTheme()) {
return `${props.base}/${props.res}.dark.svg`;
}
return `${props.base}/${props.res}.light.svg`;
});
function isDarkTheme() {
// check html element class, if it is dark, return true
let ret = document.documentElement.classList.contains('dark');
if (currentTheme.value === 'dark') {
ret = true
}
return ret;
}
function switchImagesTheme(isDark:boolean) {
const themedImages = document.querySelectorAll('img.themed');
for (let i = 0; i < themedImages.length; i ++) {
const img:any = themedImages[i];
const originalSrc:any = img.getAttribute('src')
const parts = originalSrc.split('.');
const prefix = parts.shift();
const ext = parts.pop();
const mid = isDark ? 'dark' : 'light';
if (prefix && ext && (prefix !== ext)) {
const newSrc = `${prefix}.${mid}.${ext}`
img.onerror = () => {
img.setAttribute('src', originalSrc);
}
img.setAttribute('src', newSrc);
}
}
}
onMounted(() => {
const htmlEle:any = document.querySelector('html');
const observer = new MutationObserver((mutationsList, observer) => {
for(const mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
switchImagesTheme(htmlEle.classList.contains('dark'))
}
}
});
const config = {
attributes: true,
attributeFilter: ['class']
};
observer.observe(htmlEle, config);
// apply html
switchImagesTheme(htmlEle.classList.contains('dark'))
});
</script>
<style lang="scss" scoped>
.image-wrapper {
display: flex;
justify-content: center;
align-items: center;
img {
width: 100%;
height: auto;
}
}
</style>

View File

@@ -16,6 +16,7 @@ export default {
// },
enhanceApp({ app, router, siteData }) {
// ...
app.component('Image', Image)
app.component('SpeakWord', SpeakWord)
}
} satisfies Theme

View File

@@ -1,6 +1,7 @@
<script setup>
import DefaultTheme from 'vitepress/theme'
import SpeakWordInlineConverter from '../components/SpeakWordInlineConverter.vue'
import ThemedImageSwitch from '../components/ThemedImageSwitch.vue'
const { Layout } = DefaultTheme
@@ -11,6 +12,7 @@ const { Layout } = DefaultTheme
<template #doc-after>
<ClientOnly>
<SpeakWordInlineConverter />
<ThemedImageSwitch />
</ClientOnly>
</template>
</Layout>