您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Visual indicator of page progress while scrolling
当前为
- // ==UserScript==
- // @license MIT
- // @name Scroll Page Progress
- // @namespace http://tampermonkey.net/
- // @version 1.6.2
- // @description Visual indicator of page progress while scrolling
- // @author You
- // @match *://*/*
- // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- if (window.trustedTypes && window.trustedTypes.createPolicy) {
- window.trustedTypes.createPolicy('default', {
- createHTML: (string, sink) => string
- });
- }
- let globalShadow
- function once(fn, context) {
- var result;
- return function() {
- if(fn) {
- result = fn.apply(context || this, arguments);
- fn = null;
- }
- return result;
- };
- }
- function insertCirculaProgressBarEl() {
- const shadowHost = document.createElement('div')
- const shadow = shadowHost.attachShadow({ mode: "closed" });
- const circularProgressBar = document.createElement('div')
- const contentWrapper = document.createElement('div')
- const closeOverlay = document.createElement('div')
- const title = document.createElement('div')
- const overlay = document.createElement('div')
- const leftSide = document.createElement('div')
- const rightSide = document.createElement('div')
- globalShadow = shadow
- circularProgressBar.classList.add('circular-progress-bar')
- title.classList.add('title');
- closeOverlay.classList.add('close-overlay');
- contentWrapper.classList.add('content-wrapper')
- overlay.classList.add('overlay');
- leftSide.classList.add('left-side');
- rightSide.classList.add('right-side');
- shadowHost.id = 'host-shwadow-circular-progress'
- title.innerText = '-%'
- if (window.trustedTypes) {
- closeOverlay.innerHTML = window.trustedTypes.defaultPolicy.createHTML('×')
- } else {
- closeOverlay.innerHTML = '×'
- }
- closeOverlay.addEventListener('click', function() {
- circularProgressBar.style.display = 'none'
- const path = window.location.pathname;
- let savedPaths = JSON.parse(localStorage.getItem('not-allowed-paths')) || [];
- console.log(path, savedPaths)
- if (!savedPaths.includes(path)) {
- savedPaths.push(path);
- localStorage.setItem('not-allowed-paths', JSON.stringify(savedPaths));
- }
- });
- ;[title, overlay, leftSide, rightSide].forEach(childEl => contentWrapper.appendChild(childEl))
- circularProgressBar.appendChild(closeOverlay)
- circularProgressBar.appendChild(contentWrapper)
- shadow.appendChild(circularProgressBar)
- document.body.appendChild(shadowHost)
- }
- function addCSS() {
- const styleSheet = document.createElement('style');
- styleSheet.textContent = `
- * {
- box-sizing: border-box;
- padding: 0;
- margin: 0;
- }
- .circular-progress-bar {
- --backgroundColor: #424242;
- --left-side-angle: 180deg;
- --barColor:orangered;
- width: 60px;
- height: 60px;
- color: #fff;
- border-radius: 50%;
- position: fixed;
- z-index: 2147483646;
- background: var(--backgroundColor);
- border: 5px solid white;
- box-shadow:
- 0 1px 1px hsl(0deg 0% 0% / 0.075),
- 0 2px 2px hsl(0deg 0% 0% / 0.075),
- 0 4px 4px hsl(0deg 0% 0% / 0.075),
- 0 8px 8px hsl(0deg 0% 0% / 0.075),
- 0 16px 16px hsl(0deg 0% 0% / 0.075);
- text-align: center;
- cursor: pointer;
- transition: opacity 0.2s ease;
- }
- .circular-progress-bar .overlay {
- width: 50%;
- height: 100%;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1;
- background-color: var(--backgroundColor);
- }
- .close-overlay {
- width: 20px;
- height: 20px;
- position: absolute;
- left: 100%;
- top: -30%;
- z-index: 2147483647;
- display: flex;
- justify-content: center;
- align-items: center;
- border-radius: 50%;
- background: orangered;
- font-size: 19px;
- text-align: center;
- opacity: 0;
- }
- .close-overlay:hover {
- font-weight: bold;
- }
- .content-wrapper {
- overflow: hidden;
- height: 100%;
- width: 100%;
- border-radius: 50%;
- position: relative;
- }
- .circular-progress-bar:hover .close-overlay {
- opacity:1;
- }
- .circular-progress-bar .title {
- font-size: 15px;
- font-weight: bold;
- position:relative;
- height: 100%;
- display:flex;
- justify-content:center;
- align-items: center;
- z-index: 100;
- }
- .circular-progress-bar .left-side,
- .circular-progress-bar .right-side {
- width: 50%;
- height: 100%;
- position: absolute;
- top: 0;
- left: 0;
- border: 5px solid var(--barColor);
- border-radius: 100px 0px 0px 100px;
- border-right: 0;
- transform-origin: right;
- }
- .circular-progress-bar .left-side {
- transform: rotate(var(--left-side-angle));
- z-index: var(--zindex);
- }
- .circular-progress-bar .right-side {
- transform: rotate(var(--right-side-angle));
- }
- `
- globalShadow.appendChild(styleSheet)
- }
- insertCirculaProgressBarEl()
- addCSS()
- const currentState = {
- deg: 0,
- progress: 0,
- zIndex: 0
- }
- function setAngle(deg) {
- const progressBar = globalShadow.querySelector('.circular-progress-bar')
- const leftSide = globalShadow.querySelector('.left-side')
- const rightSide = globalShadow.querySelector('.right-side')
- leftSide.style.opacity = "0"
- const zIndex = deg > 180 ? 100 : 0
- const rightSideAngle = deg < 180 ? deg : 180
- const leftSideAngle = deg
- const zIndexChangedToPositive = currentState.zIndex === 0 && zIndex === 100
- if (deg > 180) {
- leftSide.style.opacity = "1"
- progressBar.style.setProperty('--left-side-angle', `${leftSideAngle}deg`);
- progressBar.style.setProperty('--zindex', zIndex);
- }
- progressBar.style.setProperty('--right-side-angle', `${rightSideAngle}deg`);
- currentState.deg = deg
- /*if (zIndex === 100 && zIndexChangedToPositive) {
- setUnsetOpacity()
- }*/
- }
- function percentageToAngle (percentageNumber) {
- if (percentageNumber > 100) {
- return 360
- }
- if (percentageNumber < 0) {
- return 0
- }
- return (360 * percentageNumber)/100
- }
- function setPercentage(percentageNumber) {
- const angle = percentageToAngle(percentageNumber)
- setAngle(angle)
- }
- function debounce(callback, wait) {
- let timerId;
- return (...args) => {
- clearTimeout(timerId);
- timerId = setTimeout(() => {
- callback(...args);
- }, wait);
- };
- }
- const progressBar = globalShadow.querySelector('.circular-progress-bar')
- const body = document.body;
- let offsetX = 0, offsetY = 0, isDragging = false;
- progressBar.addEventListener("mousedown", (e) => {
- e.preventDefault()
- offsetX = e.clientX - progressBar.offsetLeft;
- offsetY = e.clientY - progressBar.offsetTop;
- isDragging = true;
- progressBar.style.cursor = "grabbing";
- progressBar.style.opacity = "0.3";
- });
- document.addEventListener("mousemove", (e) => {
- if (isDragging) {
- e.preventDefault();
- const left = e.clientX - offsetX;
- const top = e.clientY - offsetY;
- progressBar.style.left = `${left}px`;
- progressBar.style.top = `${top}px`;
- savePosition(left, top); // Guardar la posición cada vez que se mueve
- }
- });
- document.addEventListener("mouseup", () => {
- isDragging = false;
- progressBar.style.cursor = "grab";
- progressBar.style.opacity = "1";
- });
- function savePosition(left, top) {
- const position = { left, top };
- localStorage.setItem("elementPosition", JSON.stringify(position));
- }
- function loadPosition() {
- const savedPosition = localStorage.getItem("elementPosition");
- if (savedPosition) {
- const { left, top } = JSON.parse(savedPosition);
- progressBar.style.left = `${left}px`;
- progressBar.style.top = `${top}px`;
- } else {
- progressBar.style.right = `10px`;
- progressBar.style.top = `10px`;
- }
- }
- function getCurrentScrollProgress() {
- const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
- const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
- const progress = (winScroll / height) * 100;
- return Math.trunc(progress);
- }
- const progressBarTitle = globalShadow.querySelector('.title')
- document.onreadystatechange = function () {
- if (document.readyState == "complete") {
- if (window.trustedTypes && window.trustedTypes.createPolicy && !window.trustedTypes.defaultPolicy) {
- window.trustedTypes.createPolicy('default', {
- createHTML: (string, sink) => string
- });
- }
- const currentPath = window.location.pathname;
- const savedPaths = JSON.parse(localStorage.getItem('not-allowed-paths')) || [];
- if (savedPaths.includes(currentPath)) {
- progressBar.style.display = 'none';
- return;
- }
- loadPosition()
- document.addEventListener('scroll', debounce(() => {
- setPercentage(getCurrentScrollProgress())
- progressBarTitle.innerText = getCurrentScrollProgress() + '%'
- console.log(progressBarTitle, getCurrentScrollProgress())
- currentState.progress = getCurrentScrollProgress()
- currentState.deg = percentageToAngle(getCurrentScrollProgress())
- }, 50))
- }
- }
- })();