Genshin Impact Map Toggle Chest Pin Style

Toggle chest pin style between type and obtain way on the fly in the Teyvat Interactive Map

作者のサイトでサポートを受ける。または、このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name               Genshin Impact Map Toggle Chest Pin Style
// @name:en            Genshin Impact Map Toggle Chest Pin Style
// @name:zh            原神米游社大地图更换宝箱标点样式
// @name:zh-CN         原神米游社大地图更换宝箱标点样式
// @namespace          WEGFan
// @version            1.1.0
// @author             WEGFan
// @description        Toggle chest pin style between type and obtain way on the fly in the Teyvat Interactive Map
// @description:en     Toggle chest pin style between type and obtain way on the fly in the Teyvat Interactive Map
// @description:zh     原神米游社大地图实时切换解谜宝箱的标点样式,可选择显示品质或获取方式
// @description:zh-CN  原神米游社大地图实时切换解谜宝箱的标点样式,可选择显示品质或获取方式
// @license            MIT
// @icon               https://webstatic.mihoyo.com/ys/app/interactive-map/mapicon.png
// @homepage           https://github.com/WEGFan/Genshin-Impact-Map-Toggle-Chest-Pin-Style
// @supportURL         https://github.com/WEGFan/Genshin-Impact-Map-Toggle-Chest-Pin-Style/issues
// @match              https://webstatic.mihoyo.com/ys/app/interactive-map/*
// @match              https://act.hoyolab.com/ys/app/interactive-map/*
// @require            https://cdn.jsdelivr.net/npm/@violentmonkey/dom@2.1.3/dist/index.js
// @require            https://cdn.jsdelivr.net/npm/i18next@22.4.14/i18next.min.js
// @grant              GM_getValue
// @grant              GM_setValue
// ==/UserScript==

(t=>{const e=document.createElement("style");e.dataset.source="vite-plugin-monkey",e.textContent=t,document.head.append(e)})(' .wegfan__chest-marker-style-toggle .chest-marker-style-option{display:flex;justify-content:space-between;align-items:center;margin-top:.04rem;color:#ece6d9bf;font-size:.12rem}.wegfan__chest-marker-style-toggle .button-container{display:flex;gap:.1rem}.wegfan__chest-marker-style-toggle .button-container .button{height:.24rem;width:.57rem;border-radius:.06rem;background-color:#323947;background-position:50%;background-repeat:no-repeat;background-size:100%;overflow:hidden;line-height:.24rem;text-align:center;display:inline-block;white-space:nowrap;text-overflow:ellipsis;cursor:pointer;position:relative}.wegfan__chest-marker-style-toggle .button.selected{color:#d3bc8e}.wegfan__chest-marker-style-toggle .button.selected:after{position:absolute;display:block;content:"";top:0;left:0;width:100%;height:100%;border:.5px solid #d3bc8e;border-radius:.06rem;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:2} ');

(function (i18next, VM) {
  'use strict';

  function _interopNamespaceDefault(e) {
    const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
    if (e) {
      for (const k in e) {
        if (k !== 'default') {
          const d = Object.getOwnPropertyDescriptor(e, k);
          Object.defineProperty(n, k, d.get ? d : {
            enumerable: true,
            get: () => e[k]
          });
        }
      }
    }
    n.default = e;
    return Object.freeze(n);
  }

  const VM__namespace = /*#__PURE__*/_interopNamespaceDefault(VM);

  var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  const languageDetector = {
    type: "languageDetector",
    async: false,
    detect() {
      const url = new URL(location.href);
      const lang = url.searchParams.get("lang");
      if (lang) {
        return lang;
      }
      if (url.host.includes("webstatic.mihoyo.com")) {
        return "zh-cn";
      }
      if (url.host.includes("act.hoyolab.com")) {
        return "en-us";
      }
      return "en-us";
    }
  };
  const translation$1 = {
    "解谜宝箱显示样式": '"Puzzle Chest" pin style',
    "品质": "Type",
    "获取方式": "Obtain way"
  };
  const enUs = {
    translation: translation$1
  };
  const translation = {
    "解谜宝箱显示样式": "解谜宝箱显示样式",
    "品质": "品质",
    "获取方式": "获取方式"
  };
  const zhCn = {
    translation
  };
  const i18n = i18next.createInstance({
    debug: false,
    initImmediate: false,
    lowerCaseLng: true,
    fallbackLng: "en-us",
    resources: {
      "en-us": enUs,
      "zh-cn": zhCn
    }
  }).use(languageDetector);
  let i18nInited = false;
  const init = () => {
    var _a, _b;
    const map = (_b = (_a = document.querySelector(".mhy-game-gis")) == null ? void 0 : _a.__vue__) == null ? void 0 : _b.map;
    const markerLayers = Object.values((map == null ? void 0 : map._layers) ?? {}).filter((layer) => layer._drawMarker);
    if (!map || !markerLayers) {
      return;
    }
    if (!i18nInited) {
      i18n.init();
      i18nInited = true;
    }
    const insertMarkerStyleTogglePanel = () => {
      const className = "wegfan__chest-marker-style-toggle";
      if (document.querySelector(`.${className}`)) {
        return;
      }
      const chestFilterPanelContentElement = document.querySelector('[id="13"]>div.filter-panel__labels-content');
      if (!chestFilterPanelContentElement) {
        return;
      }
      const panelElement = VM__namespace.m(
        /* @__PURE__ */ VM__namespace.h("div", { className: "wegfan__chest-marker-style-toggle" }, /* @__PURE__ */ VM__namespace.h("div", { className: "chest-marker-style-option" }, /* @__PURE__ */ VM__namespace.h("span", null, i18n.t("解谜宝箱显示样式")), /* @__PURE__ */ VM__namespace.h("div", { className: "button-container" }, /* @__PURE__ */ VM__namespace.h("div", { className: "button", "data-chest-marker-style-index": "1", title: i18n.t("品质") }, i18n.t("品质")), /* @__PURE__ */ VM__namespace.h("div", { className: "button", "data-chest-marker-style-index": "2", title: i18n.t("获取方式") }, i18n.t("获取方式")))))
      );
      chestFilterPanelContentElement.parentElement.insertBefore(panelElement, chestFilterPanelContentElement);
      const buttons = panelElement.querySelectorAll(".chest-marker-style-option .button");
      const toggleMarkerStyle = (event) => {
        event.preventDefault();
        buttons.forEach((button) => button.classList.remove("selected"));
        event.target.classList.add("selected");
        _GM_setValue("markerStyle", event.target.getAttribute("data-chest-marker-style-index"));
        markerLayers.forEach((layer) => {
          layer._latlngMarkers.dirty = 1;
          layer._latlngMarkers.total = 1;
          layer.redraw();
        });
      };
      buttons.forEach((button) => {
        if (button.getAttribute("data-chest-marker-style-index") === _GM_getValue("markerStyle", "1")) {
          button.classList.add("selected");
        }
        button.addEventListener("click", toggleMarkerStyle);
        button.addEventListener("touchend", toggleMarkerStyle);
      });
    };
    const hookMapDrawMarker = (layer) => {
      if (layer._wegfan_toggleChestMarkerStyleHooked) {
        return;
      }
      layer._drawMarker = function(t, e) {
        var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j;
        let n = this;
        this._imageLookup || (this._imageLookup = {}), e || (e = n._map.latLngToContainerPoint(t.getLatLng()));
        let iconUrl = t.options.icon.options.iconUrl;
        const markerStyle = _GM_getValue("markerStyle", "1");
        if (markerStyle === "2") {
          let extAttrs = (_b2 = (_a2 = t == null ? void 0 : t.attrs) == null ? void 0 : _a2.marker) == null ? void 0 : _b2.ext_attrs;
          if (extAttrs) {
            let chestSource = (_c = JSON.parse(extAttrs)) == null ? void 0 : _c["3"];
            let sourceIconUrl = (_j = (_i = (_h = (_g = (_f = (_e = (_d = t == null ? void 0 : t.attrs) == null ? void 0 : _d.config) == null ? void 0 : _e.group) == null ? void 0 : _f.ext_attr_list) == null ? void 0 : _g[0]) == null ? void 0 : _h.children) == null ? void 0 : _i[chestSource]) == null ? void 0 : _j.icon;
            if (sourceIconUrl) {
              iconUrl = sourceIconUrl;
            }
          }
        }
        if (t.canvas_img && t.previousChestMarkerStyle !== markerStyle) {
          t.canvas_img = null;
        }
        t.previousChestMarkerStyle = markerStyle;
        if (t.canvas_img) {
          n._drawImage(t, e);
        } else if (n._imageLookup[iconUrl]) {
          t.canvas_img = n._imageLookup[iconUrl][0], false === n._imageLookup[iconUrl][1] ? n._imageLookup[iconUrl][2].push([
            t,
            e
          ]) : n._drawImage(t, e);
        } else {
          let r = new Image();
          r.crossOrigin = "Anonymous", r.src = iconUrl, t.canvas_img = r, n._imageLookup[iconUrl] = [
            r,
            false,
            [
              [
                t,
                e
              ]
            ]
          ], r.onload = function() {
            n._imageLookup[iconUrl][1] = true, n._imageLookup[iconUrl][2].forEach(function(t2) {
              n._drawImage(t2[0], t2[1]);
            });
          };
        }
      };
      layer._wegfan_toggleChestMarkerStyleHooked = true;
    };
    insertMarkerStyleTogglePanel();
    markerLayers.forEach((layer) => {
      hookMapDrawMarker(layer);
    });
  };
  init();
  setInterval(init, 500);

})(i18next, VM);