rust-lang / mdBook

Create book from markdown files. Like Gitbook but implemented in Rust
https://rust-lang.github.io/mdBook/
Mozilla Public License 2.0
17.64k stars 1.61k forks source link

Zoomable Images #2075

Open cr0mll opened 1 year ago

cr0mll commented 1 year ago

Problem

Currently, images in HTML rendered through mdbook are static and cannot be zoomed into which can make them difficult to see (such as here).

Proposed Solution

The images should appear as enlarged pop-ups when clicked on (similarly to how Discord or Obsidian do it).

It should also be possible to configure this as an option in book.toml for the HTML renderer. For example

[output.html]
zoomable-images = true
expikr commented 1 year ago

Alternatively it can just make the image clickable links by default like GitHub does.

So the following

![](smilie.png)

Should output

<a href="smilie.png"><img src="smilie.png"/></a>

image

Whereas with vanilla Markdown you'd need to type

[![](smilie.png)](smilie.png)

I see no reason why this shouldn't be the default behaviour considering that this is what GitHub does.

AlessandroMattiazzi commented 1 year ago

You can implement a custom javascript to do this job, here there is my solution:

function zoomIMG(id) {
  var img = document.getElementById(id);
  var imgSrc = img.src;
  var overlay = createOverlay(imgSrc);
  document.body.appendChild(overlay);
  overlay.addEventListener("click", function() {
    document.body.removeChild(overlay);
  });
  overlay.addEventListener("wheel", function(evt) {
    evt.preventDefault();
    var delta = evt.deltaY * 10 || evt.detail * 10;
    zoomImg(overlay, delta);
  });
}

function createOverlay(imgSrc) {
  var overlay = document.createElement("div");
  overlay.style.position = "fixed";
  overlay.style.zIndex = "9999";
  overlay.style.top = "0";
  overlay.style.left = "0";
  overlay.style.width = "100%";
  overlay.style.height = "100%";
  overlay.style.background = "rgba(0, 0, 0, 0.8)";
  overlay.style.display= "flex";
  overlay.style.justifyContent = "center";
  overlay.style.alignItems = "center";
  var zoomedImg = document.createElement("img");
  zoomedImg.src = imgSrc;
  zoomedImg.style.maxWidth = "95%";
  zoomedImg.style.maxHeight = "95%";
  overlay.appendChild(zoomedImg);
  return overlay;
}

function zoomImg(overlay, delta) {
  var zoomedImg = overlay.querySelector("img");
  var scaleDelta = 1.1;
  var newWidth = zoomedImg.offsetWidth;
  var newHeight = zoomedImg.offsetHeight;

  if (delta > 0) {
    newWidth = Math.max(zoomedImg.naturalWidth * 0.2, newWidth / scaleDelta);
    newHeight = Math.max(zoomedImg.naturalHeight * 0.2, newHeight / scaleDelta);
  }
  else {
    newWidth = Math.min(zoomedImg.naturalWidth * 5, newWidth * scaleDelta);
    newHeight = Math.min(zoomedImg.naturalHeight * 5, newHeight * scaleDelta);
    if (newHeight >= window.innerHeight *95/100) {
      newWidth = newWidth + "px";
      newHeight = window.innerHeight;
    }
  }
  zoomedImg.style.width = newWidth + "px";
  overlay.style.justifyContent = "flex-start";
  overlay.scrollTop -= delta * 2;
}