您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A JavaScript utility for measuring the spacing between elements on webpage.
- // ==UserScript==
- // @name Spacing.js
- // @namespace https://github.com/stevenlei
- // @version 1.0.5
- // @description A JavaScript utility for measuring the spacing between elements on webpage.
- // @author Steven Lei <contact@stevenlei.com>
- // @run-at document-start
- // @include *
- // @license MIT
- // ==/UserScript==
- 'use strict';
- /*!
- * Spacing.js v1.0.5
- * Copyright (c) 2021 Steven Lei
- * Released under the MIT License.
- */
- /******/ (() => { // webpackBootstrap
- /******/ "use strict";
- /******/ // The require scope
- /******/ var __webpack_require__ = {};
- /******/
- /************************************************************************/
- /******/ /* webpack/runtime/make namespace object */
- /******/ (() => {
- /******/ // define __esModule on exports
- /******/ __webpack_require__.r = (exports) => {
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
- /******/ }
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
- /******/ };
- /******/ })();
- /******/
- /************************************************************************/
- var __webpack_exports__ = {};
- // ESM COMPAT FLAG
- __webpack_require__.r(__webpack_exports__);
- ;// CONCATENATED MODULE: ./src/rect.ts
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
- var Rect = /*#__PURE__*/function () {
- function Rect(rect) {
- _classCallCheck(this, Rect);
- this.top = rect.top;
- this.left = rect.left;
- this.width = rect.width;
- this.height = rect.height;
- this.right = rect.right;
- this.bottom = rect.bottom;
- }
- _createClass(Rect, [{
- key: "colliding",
- value: function colliding(other) {
- return !(this.top > other.bottom || this.right < other.left || this.bottom < other.top || this.left > other.right);
- }
- }, {
- key: "containing",
- value: function containing(other) {
- return this.left <= other.left && other.left < this.width && this.top <= other.top && other.top < this.height;
- }
- }, {
- key: "inside",
- value: function inside(other) {
- return other.top <= this.top && this.top <= other.bottom && other.top <= this.bottom && this.bottom <= other.bottom && other.left <= this.left && this.left <= other.right && other.left <= this.right && this.right <= other.right;
- }
- }]);
- return Rect;
- }();
- ;// CONCATENATED MODULE: ./src/placeholder.ts
- function createPlaceholderElement(type, width, height, top, left, color) {
- var placeholder = document.createElement('div');
- placeholder.classList.add("spacing-js-".concat(type, "-placeholder"));
- placeholder.style.border = "2px solid ".concat(color);
- placeholder.style.position = 'fixed';
- placeholder.style.background = 'none';
- placeholder.style.borderRadius = '2px';
- placeholder.style.padding = '0';
- placeholder.style.margin = '0';
- placeholder.style.width = "".concat(width - 2, "px");
- placeholder.style.height = "".concat(height - 2, "px");
- placeholder.style.top = "".concat(top - 1, "px");
- placeholder.style.left = "".concat(left - 1, "px");
- placeholder.style.pointerEvents = 'none';
- placeholder.style.zIndex = '9999';
- placeholder.style.boxSizing = 'content-box';
- document.body.appendChild(placeholder);
- }
- function clearPlaceholderElement(type) {
- var _document$querySelect;
- (_document$querySelect = document.querySelector(".spacing-js-".concat(type, "-placeholder"))) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.remove();
- }
- ;// CONCATENATED MODULE: ./src/marker.ts
- function createLine(width, height, top, left, text) {
- var border = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'none';
- var marker = document.createElement('span');
- marker.style.backgroundColor = 'red';
- marker.style.position = 'fixed';
- marker.classList.add("spacing-js-marker");
- marker.style.width = "".concat(width, "px");
- marker.style.height = "".concat(height, "px");
- if (border === 'x') {
- marker.style.borderLeft = '1px solid rgba(255, 255, 255, .8)';
- marker.style.borderRight = '1px solid rgba(255, 255, 255, .8)';
- }
- if (border === 'y') {
- marker.style.borderTop = '1px solid rgba(255, 255, 255, .8)';
- marker.style.borderBottom = '1px solid rgba(255, 255, 255, .8)';
- }
- marker.style.pointerEvents = 'none';
- marker.style.top = "".concat(top, "px");
- marker.style.left = "".concat(left, "px");
- marker.style.zIndex = '9998';
- marker.style.boxSizing = 'content-box';
- var value = document.createElement('span');
- value.classList.add("spacing-js-value");
- value.style.backgroundColor = 'red';
- value.style.color = 'white';
- value.style.fontSize = '10px';
- value.style.display = 'inline-block';
- value.style.fontFamily = 'Helvetica, sans-serif';
- value.style.fontWeight = 'bold';
- value.style.borderRadius = '20px';
- value.style.position = 'fixed';
- value.style.width = '42px';
- value.style.lineHeight = '15px';
- value.style.height = '16px';
- value.style.textAlign = 'center';
- value.style.zIndex = '10000';
- value.style.pointerEvents = 'none';
- value.innerText = text;
- value.style.boxSizing = 'content-box';
- if (border === 'x') {
- // Prevent the badge moved outside the screen
- var topOffset = top + height / 2 - 7;
- if (topOffset > document.documentElement.clientHeight - 20) {
- topOffset = document.documentElement.clientHeight - 20;
- }
- if (topOffset < 0) {
- topOffset = 6;
- }
- value.style.top = "".concat(topOffset, "px");
- value.style.left = "".concat(left + 6, "px");
- } else if (border === 'y') {
- // Prevent the badge moved outside the screen
- var leftOffset = left + width / 2 - 20;
- if (leftOffset > document.documentElement.clientWidth - 48) {
- leftOffset = document.documentElement.clientWidth - 48;
- }
- if (leftOffset < 0) {
- leftOffset = 6;
- }
- value.style.top = "".concat(top + 6, "px");
- value.style.left = "".concat(leftOffset, "px");
- }
- document.body.appendChild(marker);
- document.body.appendChild(value);
- }
- function placeMark(rect1, rect2, direction, value) {
- var edgeToEdge = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
- if (direction === 'top') {
- var width = 1;
- var height = Math.abs(rect1.top - rect2.top);
- var left = Math.floor((Math.min(rect1.right, rect2.right) + Math.max(rect1.left, rect2.left)) / 2);
- var top = Math.min(rect1.top, rect2.top);
- if (edgeToEdge) {
- if (rect1.top < rect2.top) {
- return;
- } // If not colliding
- if (rect1.right < rect2.left || rect1.left > rect2.right) {
- return;
- }
- height = Math.abs(rect2.bottom - rect1.top);
- top = Math.min(rect2.bottom, rect1.top);
- }
- createLine(width, height, top, left, value, 'x');
- } else if (direction === 'left') {
- var _width = Math.abs(rect1.left - rect2.left);
- var _height = 1;
- var _top = Math.floor((Math.min(rect1.bottom, rect2.bottom) + Math.max(rect1.top, rect2.top)) / 2);
- var _left = Math.min(rect1.left, rect2.left);
- if (edgeToEdge) {
- if (rect1.left < rect2.left) {
- return;
- } // If not overlapping
- if (rect1.bottom < rect2.top || rect1.top > rect2.bottom) {
- return;
- }
- _width = Math.abs(rect1.left - rect2.right);
- _left = Math.min(rect2.right, rect1.left);
- }
- createLine(_width, _height, _top, _left, value, 'y');
- } else if (direction === 'right') {
- var _width2 = Math.abs(rect1.right - rect2.right);
- var _height2 = 1;
- var _top2 = Math.floor((Math.min(rect1.bottom, rect2.bottom) + Math.max(rect1.top, rect2.top)) / 2);
- var _left2 = Math.min(rect1.right, rect2.right);
- if (edgeToEdge) {
- if (rect1.left > rect2.right) {
- return;
- } // If not overlapping
- if (rect1.bottom < rect2.top || rect1.top > rect2.bottom) {
- return;
- }
- _width2 = Math.abs(rect1.right - rect2.left);
- }
- createLine(_width2, _height2, _top2, _left2, value, 'y');
- } else if (direction === 'bottom') {
- var _width3 = 1;
- var _height3 = Math.abs(rect1.bottom - rect2.bottom);
- var _top3 = Math.min(rect1.bottom, rect2.bottom);
- var _left3 = Math.floor((Math.min(rect1.right, rect2.right) + Math.max(rect1.left, rect2.left)) / 2);
- if (edgeToEdge) {
- if (rect2.bottom < rect1.top) {
- return;
- } // If not overlapping
- if (rect1.right < rect2.left || rect1.left > rect2.right) {
- return;
- }
- _height3 = Math.abs(rect1.bottom - rect2.top);
- }
- createLine(_width3, _height3, _top3, _left3, value, 'x');
- }
- }
- function removeMarks() {
- document.querySelectorAll('.spacing-js-marker').forEach(function (element) {
- element.remove();
- });
- document.querySelectorAll('.spacing-js-value').forEach(function (element) {
- element.remove();
- });
- }
- ;// CONCATENATED MODULE: ./src/spacing.ts
- var active = false;
- var selectedElement;
- var targetElement;
- var originalBodyOverflow;
- var Spacing = {
- start: function start() {
- if (!document.body) {
- console.warn("Unable to initialise, document.body does not exist.");
- return;
- }
- window.addEventListener('keydown', function (e) {
- if (e.key === 'Alt' && !active) {
- e.preventDefault();
- active = true;
- setSelectedElement();
- preventPageScroll(true);
- }
- });
- window.addEventListener('keyup', function (e) {
- active = false;
- clearPlaceholderElement('selected');
- clearPlaceholderElement('target');
- selectedElement = null;
- targetElement = null;
- removeMarks();
- preventPageScroll(false);
- });
- window.addEventListener('mousemove', function (e) {
- setTargetElement().then(function () {
- if (selectedElement != null && targetElement != null) {
- // Do the calculation
- var selectedElementRect = selectedElement.getBoundingClientRect();
- var targetElementRect = targetElement.getBoundingClientRect();
- var selected = new Rect(selectedElementRect);
- var target = new Rect(targetElementRect);
- removeMarks();
- var top, bottom, left, right, outside;
- if (selected.containing(target) || selected.inside(target) || selected.colliding(target)) {
- console.log("containing || inside || colliding");
- top = Math.round(Math.abs(selectedElementRect.top - targetElementRect.top));
- bottom = Math.round(Math.abs(selectedElementRect.bottom - targetElementRect.bottom));
- left = Math.round(Math.abs(selectedElementRect.left - targetElementRect.left));
- right = Math.round(Math.abs(selectedElementRect.right - targetElementRect.right));
- outside = false;
- } else {
- console.log("outside");
- top = Math.round(Math.abs(selectedElementRect.top - targetElementRect.bottom));
- bottom = Math.round(Math.abs(selectedElementRect.bottom - targetElementRect.top));
- left = Math.round(Math.abs(selectedElementRect.left - targetElementRect.right));
- right = Math.round(Math.abs(selectedElementRect.right - targetElementRect.left));
- outside = true;
- }
- placeMark(selected, target, 'top', "".concat(top, "px"), outside);
- placeMark(selected, target, 'bottom', "".concat(bottom, "px"), outside);
- placeMark(selected, target, 'left', "".concat(left, "px"), outside);
- placeMark(selected, target, 'right', "".concat(right, "px"), outside);
- }
- });
- });
- }
- };
- function setSelectedElement() {
- var elements = document.querySelectorAll(':hover');
- var el = elements[elements.length - 1];
- if (el !== selectedElement) {
- selectedElement = el;
- clearPlaceholderElement('selected');
- var rect = selectedElement.getBoundingClientRect();
- createPlaceholderElement('selected', rect.width, rect.height, rect.top, rect.left, "red");
- }
- }
- function setTargetElement() {
- return new Promise(function (resolve, reject) {
- var elements = document.querySelectorAll(':hover');
- var el = elements[elements.length - 1];
- if (active && el !== selectedElement && el !== targetElement) {
- targetElement = el;
- clearPlaceholderElement('target');
- var rect = targetElement.getBoundingClientRect();
- createPlaceholderElement('target', rect.width, rect.height, rect.top, rect.left, 'blue');
- resolve();
- }
- });
- }
- function preventPageScroll(active) {
- if (active) {
- window.addEventListener('DOMMouseScroll', scrollingPreventDefault, false);
- window.addEventListener('wheel', scrollingPreventDefault, {
- passive: false
- });
- window.addEventListener('mousewheel', scrollingPreventDefault, {
- passive: false
- });
- } else {
- window.removeEventListener('DOMMouseScroll', scrollingPreventDefault);
- window.removeEventListener('wheel', scrollingPreventDefault);
- window.removeEventListener('mousewheel', scrollingPreventDefault);
- }
- }
- function scrollingPreventDefault(e) {
- e.preventDefault();
- }
- /* harmony default export */ const spacing = (Spacing);
- ;// CONCATENATED MODULE: ./src/index.ts
- // Simple, Start.
- spacing.start();
- window.Spacing = __webpack_exports__;
- /******/ })()
- ;