Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow images to be zoomed in on click #854

Open
4 tasks done
noClaps opened this issue Jun 25, 2022 · 26 comments
Open
4 tasks done

Allow images to be zoomed in on click #854

noClaps opened this issue Jun 25, 2022 · 26 comments
Assignees
Labels
enhancement New feature or request theme Related to the theme

Comments

@noClaps
Copy link

noClaps commented Jun 25, 2022

Is your feature request related to a problem? Please describe.

Usually when someone is reading a blog or documentation, there will be images to help explain the content better to the reader, such as screenshots. Sometimes if the screenshot itself is too small, users can click on the image to zoom in, and click on it again to zoom out.

Describe the solution you'd like

I'd like a way for images to be zoomed in on click, and on clicking the image again, zooming back out to the content.

Describe alternatives you've considered

There is medium-zoom, which was integrated into VuePress v2. There is also Lightbox.

I would have used these libraries, but I am not that good at JavaScript and using NPM, so I wouldn't know how to integrate them into my VitePress site, or if they even can be integrated.

Additional context

No response

Validations

@brc-dd brc-dd added enhancement New feature or request theme Related to the theme labels Jun 25, 2022
@brc-dd
Copy link
Member

brc-dd commented Jun 26, 2022

if they even can be integrated

Yeah sure it can be, and its quite easy too. Just run npm i medium-zoom and then you can do stuff like this:

# Hey There

![](https://images.pexels.com/photos/106118/pexels-photo-106118.jpeg){data-zoomable}

<script setup>
import { onMounted } from 'vue';
import mediumZoom from 'medium-zoom';

onMounted(() => {
  mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' });
});
</script>

<style>
.medium-zoom-overlay {
  z-index: 20;
}

.medium-zoom-image {
  z-index: 21;
}
</style>

Here is a demo: https://stackblitz.com/edit/vite-qdzzmm?file=docs%2Findex.md

@noClaps
Copy link
Author

noClaps commented Jun 26, 2022

Hmm, alright, I'll try it out. Is there a way to apply this globally? One way I can think of is using the index.js file, but I don't know how to implement it that way.

Also, will this feature be added to VitePress? If not, you can close the issue.

@brc-dd
Copy link
Member

brc-dd commented Jun 26, 2022

Is there a way to apply this globally?

In next version you'll be able to add a setup function in theme (added this in #856 itself). I'll update the demo once it is available.

@hooray
Copy link
Contributor

hooray commented Jul 5, 2022

Need this feature too, looking forward to the next version

@hooray
Copy link
Contributor

hooray commented Jul 5, 2022

@noClaps At this time, you can use globally like this:

// index.js
import Theme from 'vitepress/theme'
import ZoomImg from './components/ZoomImg.vue'

export default {
    ...Theme,
    enhanceApp({ app }) {
        app.component('ZoomImg', ZoomImg)
    }
}
<!-- ZoomImg.vue -->

<script setup>
import { withBase } from 'vitepress'
import { onMounted, ref } from 'vue'
import mediumZoom from 'medium-zoom'

defineProps({
    src: String
})

const imgRef = ref(null)

onMounted(() => {
    mediumZoom(imgRef.value, { background: 'var(--vp-c-bg)' });
})
</script>

<template>
    <img ref="imgRef" :src="withBase(src)">
</template>

<style>
.medium-zoom-overlay {
    z-index: 20;
}
.medium-zoom-image {
    z-index: 21;
}
</style>

now you can use <ZoomImg src="/some-img.png" /> to replace ![](/some-img.png)

@ywmail
Copy link

ywmail commented Aug 19, 2022

@hooray I updated my theme/index.ts to import ZoomImg, it works fine in dev mode but breaks in build mode. Vitepress cannot handle the img assets in build mode, the image file doesn't be copied to the dist folder and the src of img tag doesn't be transformed.

@brc-dd
Copy link
Member

brc-dd commented Aug 31, 2022

I've updated the example, you now can simply do:

// .vitepress/theme/index.js

import DefaultTheme from 'vitepress/theme';
import { onMounted } from 'vue';
import mediumZoom from 'medium-zoom';

import './index.css';

export default {
  ...DefaultTheme,
  setup() {
    onMounted(() => {
      mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' });
    });
  },
};
/* .vitepress/theme/index.css */

.medium-zoom-overlay {
  z-index: 20;
}

.medium-zoom-image {
  z-index: 21;
}

Then in markdown:

![](path/to/file.jpg){data-zoomable}

If you want to enable this for all images without explicitly adding {data-zoomable}, you can change that mediumZoom call to this:

mediumZoom('.main img', { background: 'var(--vp-c-bg)' });

@ekil1100
Copy link

ekil1100 commented Sep 1, 2022

@brc-dd I tried this method, it is not working when comes from another route. Need to refresh page to make it work.

@brc-dd
Copy link
Member

brc-dd commented Sep 1, 2022

Ah, I'll look into that. Might need to initialise medium-zoom inside a watcher.

@Zhengqbbb
Copy link
Contributor

Ah, I'll look into that. Might need to initialise medium-zoom inside a watcher.

My website's medium-zoom use wacher.

watch(
    () => router.route.path,
    () => nextTick(() => zoom.refresh()),
  )

About medium-zoom usage. Can see:
https://github.com/Zhengqbbb/cz-git/blob/5637a6006beaa7124d96a90177bb75fb33d6a764/docs/.vitepress/theme/index.ts#L26

@arcqiufeng
Copy link

Here is a demo: https://stackblitz.com/edit/vite-qdzzmm?file=docs%2Findex.md

I followed the demo and got it works. But only a little problem:

When I open my page first it doesn't work. Then I press F5 to refresh the page, then I will get the zoom function.

Why it can't work when first open the page?

@Graysonnwu
Copy link

Here is a demo: https://stackblitz.com/edit/vite-qdzzmm?file=docs%2Findex.md

I followed the demo and got it works. But only a little problem:

When I open my page first it doesn't work. Then I press F5 to refresh the page, then I will get the zoom function.

Why it can't work when first open the page?

Does this help you? --> https://stackblitz.com/edit/vite-oph6sp?file=docs/.vitepress/theme/index.js

// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme';
import { onMounted, watch, nextTick } from 'vue';
import { useRoute } from 'vitepress';
import mediumZoom from 'medium-zoom';

import './index.css';

export default {
  ...DefaultTheme,

  setup() {
    const route = useRoute();
    const initZoom = () => {
      new mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' }); // Should there be a new?
      // new mediumZoom('.main img', { background: 'var(--vp-c-bg)' });
    };
    onMounted(() => {
      initZoom();
    });
    watch(
      () => route.path,
      () => nextTick(() => initZoom())
    );
  },
};

I don't know much about coding, so please correct me if I'm wrong.

It works for me though.

@arcqiufeng
Copy link

I don't know much about coding, so please correct me if I'm wrong.

It works for me though.

Does this help you? --> https://stackblitz.com/edit/vite-oph6sp?file=docs/.vitepress/theme/index.js

It really helps. I know very little about JavaScript.

Thank you very much for your help.
Now it worked like a charm.

Much appreciated!

@cedeber
Copy link

cedeber commented Mar 7, 2023

@Graysonnwu

      new mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' }); // Should there be a new?

Thanks, first. The new here is indeed wrong, as mediumZoom is not a Class but just a function that returns an object with some functions in it. So that you can chain them or use them later.

@arcqiufeng
Copy link

arcqiufeng commented Mar 8, 2023

@Graysonnwu

      new mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' }); // Should there be a new?

Thanks, first. The new here is indeed wrong, as mediumZoom is not a Class but just a function that returns an object with some functions in it. So that you can chain them or use them later.

Can you tell me how to correct the code? I know little about javascript? Just remove the word "new"?

@cedeber
Copy link

cedeber commented Mar 8, 2023

Yes, just remove the new keyword.

@jackloves111
Copy link

jackloves111 commented Sep 23, 2023

Cool. It indeed work normally, and the summary is as follows:

vitepress 实现,单击时图片放大,再次单击图像时图片缩小的功能

npm i medium-zoom

you now can simply do:

// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme';
import { onMounted, watch, nextTick } from 'vue';
import { useRoute } from 'vitepress';
import mediumZoom from 'medium-zoom';

import './index.css';

export default {
  ...DefaultTheme,

  setup() {
    const route = useRoute();
    const initZoom = () => {
      mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' }); 
      // mediumZoom('.main img', { background: 'var(--vp-c-bg)' });
    };
    onMounted(() => {
      initZoom();
    });
    watch(
      () => route.path,
      () => nextTick(() => initZoom())
    );
  },
};
/* .vitepress/theme/index.css */

.medium-zoom-overlay {
  z-index: 20;
}

.medium-zoom-image {
  z-index: 21;
}

Then in markdown:

// docs/index.md

![](path/to/file.jpg){data-zoomable}

If you want to enable this for all images without explicitly adding , you can change that call to this:{data-zoomable}``mediumZoom

// .vitepress/theme/index.js

...
mediumZoom('.main img', { background: 'var(--vp-c-bg)' });
...

@github-actions github-actions bot removed the stale label Sep 25, 2023
@cruvie
Copy link

cruvie commented Nov 16, 2023

wait this feature added to VitePress

@github-actions github-actions bot removed the stale label Nov 25, 2023
@github-actions github-actions bot added the stale label Dec 26, 2023
@miyuesc
Copy link

miyuesc commented Mar 7, 2024

This is a very useful feature, we can hardly wait.😄

@RaniAgus
Copy link

RaniAgus commented Mar 18, 2024

Quick update: with the latest versions the z-index values have increased 😄

.medium-zoom-overlay {
  z-index: 30;
}

.medium-zoom-image--opened {
  z-index: 31;
}

@QC2168
Copy link

QC2168 commented Apr 6, 2024

solved my problem! thanks you

@github-actions github-actions bot added the stale label May 23, 2024
@wangxiang4
Copy link

vitepress setup() is not supported in. vitepress/theme/index.js files that are too old
In vitepress version 0.22.4, it can be written in the custom theme portal vue component
For example, you can write a custom theme in the vp-app.vue component

@AdamBD
Copy link

AdamBD commented Aug 12, 2024

how can you control the actual zoom? This solution is providing z-index to get the image to float above the rest of the content and provide a white background but it doesnt really 'zoom' in on the image.

@brc-dd
Copy link
Member

brc-dd commented Aug 12, 2024

Something like this maybe - https://www.npmjs.com/package/vitepress-plugin-image-viewer

@BadgerHobbs
Copy link

As relevant to this discussion, I ended up creating a simple plugin for handling light boxes. Could easily be modified for other base libraries.

https://github.com/BadgerHobbs/vitepress-plugin-lightbox

@github-actions github-actions bot added the stale label Oct 26, 2024
@expand-platform
Copy link

It perfectly works, my hat down! Thanks for a setup!

@github-actions github-actions bot removed the stale label Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request theme Related to the theme
Projects
None yet
Development

No branches or pull requests