您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
use shortcut to help you mapping on map-making app
- // ==UserScript==
- // @name Map-Making Shortcuts
- // @namespace https://greasyfork.org/users/1179204
- // @description use shortcut to help you mapping on map-making app
- // @version 1.3.6
- // @license BSD
- // @author KaKa
- // @match *://map-making.app/maps/*
- // @grant GM_addStyle
- // @icon https://www.svgrepo.com/show/521871/switch.svg
- // ==/UserScript==
- (function(){
- /* ------------------------------------------------------------------------------- */
- /* ----- KEYBOARD SHORTCUTS (MUST Refresh PAGE FOR CHANGES TO TAKE EFFECT) -------- */
- /* ------------------------------------------------------------------------------- */
- const KEYBOARD_SHORTCUTS = {
- // Single key
- switchLoc: 'Q',
- rewindLoc: 'E',
- deleteLoc: 'C',
- closeLoc: 'V',
- copyLoc:'G',
- hideElement:'H',
- deSelectAll:'Z',
- pruneDuplicates:'P',
- // SHIFT key is need
- deleteTags:'B',
- resetGulf:'M',
- classicMap:'N',
- findLinkPanos:'K',
- exportAsCsv: 'D',
- fullScreenMap:'F',
- };
- /* ############################################################################### */
- /* ##### DON'T MODIFY ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING ##### */
- /* ############################################################################### */
- let selections,currentIndex
- let mapListener
- let isDrawing, isShift,isApplied,isASV,isYSV,isHidden
- let startX, startY, endX, endY
- let selectionBox
- let style
- let actionIndex=-1
- function exportAsCsv(locs){
- const csvContent = jsonToCSV(locs);
- downloadCSV(csvContent);
- }
- function downloadCSV(csvContent, fileName = "output.csv") {
- const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
- const link = document.createElement('a');
- if (link.download !== undefined) {
- const url = URL.createObjectURL(blob);
- link.setAttribute('href', url);
- link.setAttribute('download', fileName);
- link.style.visibility = 'hidden';
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
- }
- }
- function getTagsForRow(item, maxTags) {
- const tags = item.tags || [];
- return Array.from({ length: maxTags }, (_, index) => tags[index] || '');
- }
- function getFormattedDate(dateStr) {
- if (!dateStr) return '';
- const date = new Date(dateStr);
- if (isNaN(date.getTime())) return '';
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, '0');
- return `${year}-${month}`;
- }
- function getMaxTagCount(jsonData) {
- let maxTags = 0;
- jsonData.forEach(item => {
- if (item.tags && item.tags.length > maxTags) {
- maxTags = item.tags.length;
- }
- });
- return maxTags;
- }
- function jsonToCSV(jsonData) {
- const maxTags = getMaxTagCount(jsonData);
- const tagHeaders = Array.from({ length: maxTags }, (_, i) => `tag${i + 1}`);
- const headers = ["lat", "lng", "panoId", "heading", "pitch", "zoom", "date", ...tagHeaders];
- const rows = jsonData.map(item => {
- const lat = item.location.lat|| '';
- const lng = item.location.lng|| '';
- const panoId = item.panoId|| '';
- const heading = item.heading|| '';
- const pitch = item.pitch|| '';
- const zoom = item.zoom || '';
- const date = getFormattedDate(item.panoDate)||'';
- const tags = getTagsForRow(item, maxTags);
- return [
- lat,
- lng,
- panoId,
- heading,
- pitch,
- zoom,
- date,
- ...tags
- ];
- });
- const csvContent = [headers, ...rows].map(row => row.join(",")).join("\n");
- return csvContent;
- }
- function switchLoc(locs) {
- if(editor.currentLocation) editor.closeLocation(editor.currentLocation.updatedProps)
- if (!currentIndex) {
- currentIndex =1;
- } else {
- currentIndex +=1
- if (currentIndex>locs.length){
- currentIndex=1
- }
- }
- editor.openLocation(locs[currentIndex-1]);
- focusOnLoc(locs[currentIndex-1])
- }
- function rewindLoc(locs) {
- const activeSelections=editor.selections.length > 0 ? editor.selections.flatMap(selection => selection.locations) : locations
- if(editor.currentLocation) editor.closeLocation(editor.currentLocation.updatedProps)
- if (!currentIndex) {
- currentIndex =1;
- }
- else {
- currentIndex -=1
- if (currentIndex<1) currentIndex=activeSelections.length
- }
- editor.openLocation(locs[currentIndex-1]);
- focusOnLoc(locs[currentIndex-1])
- }
- function focusOnLoc(loc){
- map.setCenter(loc.location)
- map.setZoom(17)
- }
- function deleteLoc(loc){
- editor.closeAndDeleteLocation(loc)
- }
- function copyLoc(){
- editor.addLocation(editor.currentLocation.updatedProps)
- }
- function setZoom(z){
- if(z<0)z=0
- if(z>4)z=4
- const svControl=unsafeWindow.streetView
- svControl.setZoom(z)
- }
- function getTag(index){
- const sortedTags = Object.keys(editor.tags).sort((a, b) => {
- return editor.tags[a].order - editor.tags[b].order;
- });
- const currentTags= editor.currentLocation.updatedProps.tags
- while(currentTags.includes(sortedTags[index-1])){
- index++
- }
- return sortedTags[index-1]
- }
- async function tagLoc(index){
- if(editor.currentLocation){
- const tag=getTag(index)
- if(tag) await addTag(tag)
- }
- }
- async function addTag(tag){
- const isReview= document.querySelector('.review-header')
- const prevBtn = document.querySelector('[data-qa="review-prev"]');
- const nextBtn = document.querySelector('[data-qa="review-next"]');
- const currentLoc=editor.currentLocation.location
- const editLoc=editor.currentLocation.updatedProps
- if (isReview) {
- await editor.currentLocation.updatedProps.tags.push(tag)
- setTimeout(() => {
- if (nextBtn) nextBtn.click();
- }, 100);
- setTimeout(() => {
- if (prevBtn)prevBtn.click()
- }, 200);
- }
- else{
- await editor.closeAndDeleteLocation(editor.currentLocation.location)
- editLoc.tags.push(tag)
- await editor.addAndOpenLocation(editLoc)
- }
- }
- function deleteTags() {
- let selections = editor.selections;
- while (selections.length > 0) {
- const item = selections[0];
- const tag = JSON.parse(item.key);
- const tagName = tag.tagName;
- const locations = item.locations;
- editor.deleteTag(tagName, locations);
- selections = editor.selections;
- }
- }
- function customLayer(name,tileUrl,maxZoom,minZoom){
- return new google.maps.ImageMapType({
- getTileUrl: function(coord, zoom) {
- return tileUrl
- .replace('{z}', zoom)
- .replace('{x}', coord.x)
- .replace('{y}', coord.y);
- },
- tileSize: new google.maps.Size(256, 256),
- name: name,
- maxZoom:maxZoom,
- minZoom:minZoom||1
- });
- }
- function classicMap(){
- var tileUrl = `https://mapsresources-pa.googleapis.com/v1/tiles?map_id=61449c20e7fc278b&version=15797339025669136861&pb=!1m7!8m6!1m3!1i{z}!2i{x}!3i{y}!2i9!3x1!2m2!1e0!2sm!3m7!2sen!3sus!5e1105!12m1!1e3!12m1!1e2!4e0!5m5!1e0!8m2!1e1!1e1!8i47083502!6m6!1e12!2i2!11e0!39b0!44e0!50e0`
- const tileLayer=customLayer('google_labels_reest',tileUrl,20)
- map.mapTypes.stack.layers[0]=tileLayer
- map.setMapTypeId('stack')
- }
- function resetGulf(){
- var tileUrl = `https://maps.googleapis.com/maps/vt?pb=%211m5%211m4%211i{z}%212i{x}%213i{y}%214i256%212m2%211e0%212sm%213m17%212sen%213smx%215e18%2112m4%211e68%212m2%211sset%212sRoadmap%2112m3%211e37%212m1%211ssmartmaps%2112m4%211e26%212m2%211sstyles%212ss.e%3Ag%7Cp.v%3Aoff%2Cs.t%3A1%7Cs.e%3Ag.s%7Cp.v%3Aon%2Cs.e%3Al%7Cp.v%3Aon%215m1%215f1.350000023841858`
- if(JSON.parse(localStorage.getItem('mapBoldCountryBorders')))tileUrl=`https://maps.googleapis.com/maps/vt?pb=%211m5%211m4%211i{z}%212i{x}%213i{y}%214i256%212m2%211e0%212sm%213m17%212sen%213smx%215e18%2112m4%211e68%212m2%211sset%212sRoadmap%2112m3%211e37%212m1%211ssmartmaps%2112m4%211e26%212m2%211sstyles%212ss.t%3A17%7Cs.e%3Ag.s%7Cp.w%3A2%7Cp.c%3A%23000000%2Cs.e%3Ag%7Cp.v%3Aoff%2Cs.t%3A1%7Cs.e%3Ag.s%7Cp.v%3Aon%2Cs.e%3Al%7Cp.v%3Aon%215m1%215f1.350000023841858`
- if(JSON.parse(localStorage.getItem('mapBoldSubdivisionBorders')))tileUrl=`https://maps.googleapis.com/maps/vt?pb=%211m5%211m4%211i{z}%212i{x}%213i{y}%214i256%212m2%211e0%212sm%213m17%212sen%213smx%215e18%2112m4%211e68%212m2%211sset%212sRoadmap%2112m3%211e37%212m1%211ssmartmaps%2112m4%211e26%212m2%211sstyles%212ss.t%3A18%7Cs.e%3Ag.s%7Cp.w%3A3%2Cs.e%3Al%7Cp.v%3Aoff%2Cs.t%3A1%7Cs.e%3Ag.s%7Cp.v%3Aoff%215m1%215f1.350000023841858`
- if(JSON.parse(localStorage.getItem('mapBoldSubdivisionBorders'))&&JSON.parse(localStorage.getItem('mapBoldCountryBorders')))tileUrl=`https://maps.googleapis.com/maps/vt?pb=%211m5%211m4%211i{z}%212i{x}%213i{y}%214i256%212m2%211e0%212sm%213m17%212sen%213smx%215e18%2112m4%211e68%212m2%211sset%212sRoadmap%2112m3%211e37%212m1%211ssmartmaps%2112m4%211e26%212m2%211sstyles%212ss.t%3A17%7Cs.e%3Ag.s%7Cp.w%3A2%7Cp.c%3A%23000000%2Cs.t%3A18%7Cs.e%3Ag.s%7Cp.w%3A3%2Cs.e%3Ag%7Cp.v%3Aoff%2Cs.t%3A1%7Cs.e%3Ag.s%7Cp.v%3Aon%2Cs.e%3Al%7Cp.v%3Aon%215m1%215f1.350000023841858`
- const tileLayer=customLayer('google_labels_reest',tileUrl,20)
- map.mapTypes.stack.layers[2]=tileLayer
- map.setMapTypeId('stack')
- }
- function setHW(){
- map.mapTypes.stack.layers.splice(2, 1)
- const tileUrl = `https://maprastertile-drcn.dbankcdn.cn/display-service/v1/online-render/getTile/24.12.10.10/{z}/{x}/{y}/?language=zh&p=46&scale=2&mapType=ROADMAP&presetStyleId=standard&pattern=JPG&key=DAEDANitav6P7Q0lWzCzKkLErbrJG4kS1u%2FCpEe5ZyxW5u0nSkb40bJ%2BYAugRN03fhf0BszLS1rCrzAogRHDZkxaMrloaHPQGO6LNg==`
- const tileLayer=customLayer('Petal_Maps',tileUrl,20)
- map.mapTypes.stack.layers[0]=tileLayer
- map.setMapTypeId('stack')
- }
- function setGD(){
- const tileUrl = `https://t2.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=75f0434f240669f4a2df6359275146d2`
- const tileLayer=customLayer('GaoDe_Terrain',tileUrl,20)
- //map.mapTypes.stack.layers[0]=tileLayer
- const tileUrl_ = `https://t2.tianditu.gov.cn/tbo_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=tbo&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=75f0434f240669f4a2df6359275146d2`
- const tileLayer_=customLayer('GaoDe_Border',tileUrl_,20)
- map.mapTypes.stack.layers[1]=tileLayer_
- const _tileUrl = `https://t2.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=75f0434f240669f4a2df6359275146d2`
- const _tileLayer=customLayer('GaoDe_Labels',_tileUrl,20)
- //map.mapTypes.stack.layers[2]=_tileLayer
- map.setMapTypeId('stack')
- }
- function setYandex(){
- const svUrl=`https://core-stv-renderer.maps.yandex.net/2.x/tiles?l=stv&x={x}&y={y}&z={z}&scale=1&v=2025.04.04.20.13-1_25.03.31-4-24330`
- const baseUrl=`https://core-renderer-tiles.maps.yandex.net/tiles?l=map&v=5.04.07-2~b:250311142430~ib:250404100358-24371&x={x}&y={y}&z={z}&scale=1&lang=en_US`
- const svLayer=customLayer('Yandex_StreetView',svUrl,20,5)
- const baseLayer=customLayer('Yandex_Maps',baseUrl,20,1)
- map.mapTypes.stack.layers.splice(2, 0,svLayer)
- map.mapTypes.stack.layers.splice(2, 0,baseLayer)
- map.mapTypes.set("stack",map.mapTypes.stack.layers)
- map.setMapTypeId('stack')
- }
- function setApple(){
- const svUrl=`https://lookmap.eu.pythonanywhere.com/bluelines_raster_2x/{z}/{x}/{y}.png`
- const svLayer=customLayer('Apple_StreetView',svUrl,16)
- map.mapTypes.stack.layers.splice(2, 0,svLayer)
- map.setMapTypeId('stack')
- }
- async function downloadTile(id,g) {
- try {
- const response = await fetch(`https://streetviewpixels-pa.googleapis.com/v1/tile?cb_client=apiv3&panoid=${id}&output=tile&x=${g==='Gen4'?18:16}&y=${g==='Gen4'?13:11}&zoom=5&nbt=1&fover=2`);
- const imageBlob = await response.blob();
- const img = new Image();
- img.onload = function() {
- const canvas = document.createElement('canvas');
- const ctx = canvas.getContext('2d');
- canvas.width = img.width;
- canvas.height = img.height;
- ctx.drawImage(img, 0, 0);
- const dataUrl = canvas.toDataURL('image/jpeg');
- const link = document.createElement('a');
- link.href = dataUrl;
- link.download = id+'.jpg';
- link.click();
- };
- img.src = URL.createObjectURL(imageBlob);
- } catch (error) {
- console.error('Error:', error);
- }
- }
- function lon2tile(lng,zoom) {
- return (lng+180)/360*Math.pow(2,zoom);
- }
- function lat2tile(lat,zoom){
- return (1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,zoom);
- }
- function lonLatToEpsg3395Tile(lng, lat, zoom) {
- return [lon2tile(lng,zoom), lat2tile(lat,zoom)];
- }
- function getMap(){
- let element = document.getElementsByClassName("map-embed")[0]
- try{
- const keys = Object.keys(element)
- const key = keys.find(key => key.startsWith("__reactFiber$"))
- const props = element[key]
- if(!map)window.map=props.pendingProps.children[1].props.children[1].props.map
- }
- catch(e){
- console.error('Failed to get map: '+e)
- }
- }
- function delay(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
- }
- async function fetchPanorama(service,panoId) {
- await delay(100);
- return await service.getPanorama({ pano: panoId });
- }
- async function findLinkPanos() {
- const startLoc = editor.currentLocation.updatedProps;
- let prevHeading = startLoc.heading;
- let service = new google.maps.StreetViewService();
- let metadata = await fetchPanorama(service,startLoc.panoId);
- while (metadata.data.links.length == 2) {
- let nextLoc = metadata.data.links.find(loc => Math.abs(loc.heading - prevHeading) <= 90);
- if (nextLoc) {
- metadata = await fetchPanorama(service,nextLoc.pano);
- editor.addLocation({
- location: {
- lat: metadata.data.location.latLng.lat(),
- lng: metadata.data.location.latLng.lng()
- },
- panoId: metadata.data.location.pano,
- heading: nextLoc.heading,
- pitch: 0,
- zoom: 0,
- tags: [],
- flags: 1
- });
- prevHeading = nextLoc.heading;
- }
- else break
- }
- }
- function toggleElementHidden() {
- if(!isHidden){
- style = GM_addStyle(`
- .embed-controls {display: none !important}
- .SLHIdE-sv-links-control {display: none !important}
- [class$="gmnoprint"], [class$="gm-style-cc"] {display: none !important}
- `);
- isHidden = true;
- }
- else{
- style.remove()
- isHidden=false;
- }
- }
- let onKeyDown =async (e) => {
- if (e.target.tagName === 'INPUT' || e.target.isContentEditable||!isApplied) {
- return;
- }
- const activeSelections=editor.selections.length > 0 ? editor.selections.flatMap(selection => selection.locations) : locations
- if (e.key >= '1' && e.key <= '9'){
- e.stopImmediatePropagation();
- const tagIndex=parseInt(e.key)
- await tagLoc(tagIndex)
- }
- if (!e.shiftKey&&!e.ctrlKey&&(e.key === KEYBOARD_SHORTCUTS.hideElement || e.key === KEYBOARD_SHORTCUTS.hideElement.toLowerCase())) {
- e.stopImmediatePropagation();
- toggleElementHidden()
- }
- else if (!e.shiftKey&&!e.ctrlKey&&(e.key === KEYBOARD_SHORTCUTS.deSelectAll || e.key === KEYBOARD_SHORTCUTS.deSelectAll.toLowerCase())) {
- e.stopImmediatePropagation();
- editor.resetSelections()
- }
- else if (!e.shiftKey&&!e.ctrlKey&&(e.key === KEYBOARD_SHORTCUTS.copyLoc || e.key === KEYBOARD_SHORTCUTS.copyLoc.toLowerCase())) {
- e.stopImmediatePropagation();
- copyLoc()
- }
- else if (e.key === KEYBOARD_SHORTCUTS.switchLoc || e.key === KEYBOARD_SHORTCUTS.switchLoc.toLowerCase()) {
- e.stopImmediatePropagation();
- switchLoc(activeSelections)
- }
- else if (e.key === KEYBOARD_SHORTCUTS.rewindLoc || e.key === KEYBOARD_SHORTCUTS.rewindLoc.toLowerCase()) {
- e.stopImmediatePropagation();
- rewindLoc(activeSelections)
- }
- else if (!e.shiftKey&&!e.ctrlKey&&(e.key === KEYBOARD_SHORTCUTS.deleteLoc || e.key === KEYBOARD_SHORTCUTS.deleteLoc.toLowerCase())) {
- e.stopImmediatePropagation();
- deleteLoc(activeSelections[currentIndex-1])
- }
- else if (!e.shiftKey&&!e.ctrlKey&&(e.key === KEYBOARD_SHORTCUTS.closeLoc || e.key === KEYBOARD_SHORTCUTS.closeLoc.toLowerCase())) {
- e.stopImmediatePropagation();
- editor.closeLocation(editor.currentLocation.updatedProps)
- }
- else if (e.key === KEYBOARD_SHORTCUTS.pruneDuplicates || e.key === KEYBOARD_SHORTCUTS.pruneDuplicates.toLowerCase()){
- const duplicates=editor.selections.flatMap(selection=>{if (selection.key.includes('dup') ) return selection})
- if (duplicates.length>0){
- duplicates.forEach((dup)=>{
- editor.pruneDuplicates(dup)
- })
- }
- }
- if ((e.shiftKey)&&(e.key === KEYBOARD_SHORTCUTS.exportAsCsv || e.key === KEYBOARD_SHORTCUTS.exportAsCsv.toLowerCase())) {
- e.stopImmediatePropagation();
- exportAsCsv(activeSelections)
- }
- if ((e.shiftKey)&&(e.key === KEYBOARD_SHORTCUTS.resetGulf || e.key === KEYBOARD_SHORTCUTS.resetGulf.toLowerCase())) {
- e.stopImmediatePropagation();
- resetGulf()
- }
- if ((e.shiftKey)&&(e.key === KEYBOARD_SHORTCUTS.classicMap || e.key === KEYBOARD_SHORTCUTS.classicMap.toLowerCase())) {
- e.stopImmediatePropagation();
- classicMap()
- }
- if ((e.shiftKey)&&(e.key === KEYBOARD_SHORTCUTS.deleteTags || e.key === KEYBOARD_SHORTCUTS.deleteTags.toLowerCase())) {
- e.stopImmediatePropagation();
- deleteTags()
- }
- if (e.shiftKey&&(e.key === KEYBOARD_SHORTCUTS.findLinkPanos || e.key === KEYBOARD_SHORTCUTS.findLinkPanos.toLowerCase())) {
- e.stopImmediatePropagation();
- findLinkPanos();
- }
- if ((e.shiftKey)&&(e.key === KEYBOARD_SHORTCUTS.fullScreenMap || e.key === KEYBOARD_SHORTCUTS.fullScreenMap.toLowerCase())) {
- e.stopImmediatePropagation();
- document.getElementsByClassName("gm-fullscreen-control")[0].click()
- }
- if ((e.shiftKey)&&(e.key === 'h' || e.key === 'H')) {
- e.stopImmediatePropagation();
- setHW()
- }
- /*if (e.key === 't' || e.key === 'T') {
- e.stopImmediatePropagation();
- getEditor()
- const panos=[]
- for (const loc of selections) {
- const panoId=loc.panoId
- var gen
- if (loc.tags.includes('Gen4')) gen='Gen4'
- if(panoId) panos.push({id:panoId,g:gen})
- }
- const downloadPromises = panos.map(pano => downloadTile(pano.id, pano.g));
- await Promise.all(downloadPromises);
- };*/
- }
- document.addEventListener("keydown", onKeyDown);
- var shortCutButton = document.createElement('button');
- shortCutButton.textContent = 'Shortcut Off';
- shortCutButton.style.position = 'absolute';
- shortCutButton.style.top = '8px';
- shortCutButton.style.right = '700px';
- shortCutButton.style.zIndex = '9999';
- shortCutButton.style.borderRadius = "18px";
- shortCutButton.style.padding = "5px 10px";
- shortCutButton.style.border = "none";
- shortCutButton.style.backgroundColor = "#4CAF50";
- shortCutButton.style.color = "white";
- shortCutButton.style.cursor = "pointer";
- shortCutButton.addEventListener('click', function(){
- if(isApplied){
- isApplied=false
- shortCutButton.style.border='none'
- shortCutButton.textContent = 'Shortcut Off';
- }
- else {isApplied=true
- shortCutButton.textContent = 'ShortCut On';
- shortCutButton.style.border='2px solid #fff'}
- });
- document.body.appendChild(shortCutButton)
- document.addEventListener('keydown', function(e) {
- if (e.shiftKey ) {
- isShift = true;
- }
- });
- document.addEventListener('keyup', function(e) {
- if (!e.shiftKey ) {
- isShift = false;
- }
- });
- document.addEventListener('mousedown', function(e) {
- if (e.button === 0&&isShift) {
- isDrawing = true;
- startX = e.clientX;
- startY = e.clientY;
- document.body.style.userSelect = 'none'
- selectionBox = document.createElement('div');
- selectionBox.style.position = 'absolute';
- selectionBox.style.border = '2px solid rgba(0, 128, 255, 0.7)';
- selectionBox.style.backgroundColor = 'rgba(0, 128, 255, 0.2)';
- document.body.appendChild(selectionBox);
- }
- });
- document.addEventListener('mousemove', function(e) {
- if (isDrawing) {
- endX = e.clientX;
- endY = e.clientY;
- const width = Math.abs(endX - startX);
- const height = Math.abs(endY - startY);
- selectionBox.style.left = `${Math.min(startX, endX)}px`;
- selectionBox.style.top = `${Math.min(startY, endY)}px`;
- selectionBox.style.width = `${width}px`;
- selectionBox.style.height = `${height}px`;
- selectionBox.style.zIndex = '999999';
- }
- });
- document.addEventListener('mouseup', function(e) {
- if (isDrawing) {
- isDrawing = false;
- const rect = selectionBox.getBoundingClientRect();
- document.body.removeChild(selectionBox);
- const elements = document.querySelectorAll('ul.tag-list');
- elements.forEach(element => {
- const childrens = element.querySelectorAll('li.tag.has-button');
- childrens.forEach(child => {
- const childRect = child.getBoundingClientRect();
- if (
- childRect.top >= rect.top &&
- childRect.left >= rect.left &&
- childRect.bottom <= rect.bottom &&
- childRect.right <= rect.right
- ) {
- child.click();
- document.body.style.userSelect = 'text';
- }
- });
- });
- }
- });
- })();