DeepWiki 增强

对文档的 svg 元素功能增强

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         DeepWiki 增强
// @namespace    http://tampermonkey.net/
// @version      2025-05-08
// @description  对文档的 svg 元素功能增强
// @author       MUTTERTOOLS
// @match        https://deepwiki.com/*
// @icon         https://deepwiki.com/favicon.ico
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

function bindSvgEvent(dom) {
  const selector = "div[role=dialog] svg[id|=mermaid]";
  dom.matches(selector) && bindEvent(dom);

  const svgs = dom.querySelectorAll(selector);
  svgs.forEach((svg) => bindEvent(svg));

  function bindEvent(svg) {
    if (svg.binded) return;
    svg.binded = true;

    clearStyle(svg);

    // 初始化缩放和位移参数
    let scale = 1;
    let translateX = 0;
    let translateY = 0;
    let isDragging = false;
    let startX, startY;

    const dialog = svg.closest("div[role=dialog]");

    // 滚轮缩放功能
    dialog.addEventListener("wheel", (e) => {
      e.preventDefault(); // 阻止页面滚动
      const { deltaY } = e;
      const { clientWidth, clientHeight } = document.documentElement;

      // 根据滚轮方向增加或减少缩放比例
      const delta = deltaY > 0 ? -0.2 : 0.2;
      scale = Math.max(0.1, scale + delta); // 确保缩放不会小于0.1

      // 应用变换
      applyTransform();
    });

    // 鼠标按下事件 - 开始拖拽
    dialog.addEventListener("mousedown", (e) => {
      e.preventDefault();
      isDragging = true;

      // 记录起始位置
      startX = e.clientX - translateX;
      startY = e.clientY - translateY;

      // 设置鼠标样式
      svg.style.cursor = "grabbing";
    });

    // 鼠标移动事件 - 拖拽过程
    dialog.addEventListener("mousemove", (e) => {
      if (!isDragging) return;

      // 计算新的偏移量
      translateX = e.clientX - startX;
      translateY = e.clientY - startY;

      // 应用变换
      applyTransform();
    });

    // 鼠标释放事件 - 结束拖拽
    dialog.addEventListener("mouseup", () => {
      isDragging = false;
      svg.style.cursor = "grab";
    });

    // 鼠标离开事件 - 结束拖拽
    dialog.addEventListener("mouseleave", () => {
      isDragging = false;
      svg.style.cursor = "grab";
    });

    // 应用变换的辅助函数
    function applyTransform() {
      svg.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
      svg.style.transformOrigin = "center";
    }

    // 初始化样式
    svg.style.cursor = "grab";
    svg.style.transition = "transform 0.1s";
  }

  function clearStyle(dom) {
    const observer = new MutationObserver((mutationsList) => {
      for (let mutation of mutationsList) {
        if (mutation.type === "attributes" && mutation.attributeName === "style") {
          mutation.target.style.transition = '';
        }
      }
    });

    observer.observe(dom, {
      attributes: true,
      childList: false,
      subtree: false,
    });
  }
}

function setDialogStyle(dom) {
  const selector = "div[role=dialog]";
  dom.matches(selector) && setStyle(dom);

  const dialogs = dom.querySelectorAll(selector);
  dialogs.forEach((dialog) => setStyle(dialog));

  function setStyle(dialog) {
    dialog.style.width = "90vw";
    dialog.style.height = "70vh";
  }
}

const observer = new MutationObserver((mutationsList) => {
  for (let mutation of mutationsList) {
    if (mutation.type === "childList") {
      const dom = mutation.target;
      bindSvgEvent(dom);
      setDialogStyle(dom);
    }
  }
});

observer.observe(document.body, {
  childList: true,
  attributes: false,
  subtree: true,
});


})();