Greasy Fork is available in English.
Add a counter badge on the favicon
此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.org/scripts/453212/1105873/FaviconBadger.js
// ==UserScript== // @name FaviconBadger // @description Add a counter badge on the favicon // @version 1.0 // @author ?? // ==/UserScript== /** * Create new FaviconBadger instance * @param {Object} [Options] * @param {Object} [Options.size=0.6] - Badge's size * @param {Object} [Options.position='ne'] - Badge's position ['n' 's' 'e' 'w' 'nw' 'ne' 'sw' 'se'] * @param {Object} [Options.radius=8] - Badge's border radius * @param {Object} [Options.backgroundColor='#f00'] - Badge's background color * @param {Object} [Options.color='#fff'] - Badge's text color * @return {Object} FaviconBadger object * @example * const faviconBadger = new FaviconBadger({ * size : 0.6, * position : 'ne', * radius : 8, * backgroundColor : '#f00', * color : '#fff' * }); * faviconBadger.value = 1; * faviconBadger.update(); */ const FaviconBadger = (function () { function FaviconBadger(options) { const _this = this; this.backgroundColor = options.backgroundColor || '#f00'; this.color = options.color || '#fff'; this.size = options.size || 0.6; this.position = options.position || 'ne'; this.radius = options.radius || 8; // this.src = options.src || ''; this.canvas = document.createElement('canvas'); var _a; this.src = (_a = document.querySelector('link[rel$=icon]')) === null || _a === void 0 ? void 0 : _a.href; this.ctx = this.canvas.getContext('2d'); this.faviconSize = 0; this.offset = { x: 0, y: 0 }; this.badgeSize = 0; this.value = 0; this.img = new Image(); this.img.addEventListener('load', function () { _this.faviconSize = _this.img.naturalWidth; _this.badgeSize = _this.faviconSize * _this.size; _this.canvas.width = _this.faviconSize; _this.canvas.height = _this.faviconSize; const sd = _this.faviconSize - _this.badgeSize; const sd2 = sd / 2; _this.offset = { n: { x: sd2, y: 0 }, e: { x: sd, y: sd2 }, s: { x: sd2, y: sd }, w: { x: 0, y: sd2 }, nw: { x: 0, y: 0 }, ne: { x: sd, y: 0 }, sw: { x: 0, y: sd }, se: { x: sd, y: sd } }[_this.position] || { x: 0, y: 0 }; _this._draw(); }); this.img.crossOrigin = 'Anonymous'; this.img.src = this.src; } FaviconBadger.prototype._drawIcon = function () { this.ctx.clearRect(0, 0, this.faviconSize, this.faviconSize); if (this.value) this.ctx.drawImage(this.img, 0, 0 + this.faviconSize * 0.2, this.faviconSize * 0.8, this.faviconSize * 0.8); else this.ctx.drawImage(this.img, 0, 0, this.faviconSize, this.faviconSize); }; FaviconBadger.prototype._drawShape = function () { const r = this.radius; const xa = this.offset.x; const ya = this.offset.y; const xb = this.offset.x + this.badgeSize; const yb = this.offset.y + this.badgeSize; this.ctx.beginPath(); this.ctx.moveTo(xb - r, ya); this.ctx.quadraticCurveTo(xb, ya, xb, ya + r); this.ctx.lineTo(xb, yb - r); this.ctx.quadraticCurveTo(xb, yb, xb - r, yb); this.ctx.lineTo(xa + r, yb); this.ctx.quadraticCurveTo(xa, yb, xa, yb - r); this.ctx.lineTo(xa, ya + r); this.ctx.quadraticCurveTo(xa, ya, xa + r, ya); this.ctx.fillStyle = this.backgroundColor; this.ctx.fill(); this.ctx.closePath(); const margin = (this.badgeSize * 0.18) / 2; this.ctx.beginPath(); this.ctx.textBaseline = 'middle'; this.ctx.textAlign = 'center'; this.ctx.font = 'bold '.concat(this.badgeSize * 0.9, 'px Arial'); this.ctx.fillStyle = this.color; this.ctx.fillText(this.value.toString(), this.badgeSize / 2 + this.offset.x, this.badgeSize / 2 + this.offset.y + margin); this.ctx.closePath(); }; FaviconBadger.prototype._drawFavicon = function () { document.querySelectorAll('link[rel*=\'icon\']').forEach(elm => { elm.parentElement.removeChild(elm); }); const link = document.createElement('link'); link.type = 'image/x-icon'; link.rel = 'shortcut icon'; link.href = this.canvas.toDataURL(); document.querySelector('head').appendChild(link); }; FaviconBadger.prototype._draw = function () { this._drawIcon(); if (this.value) this._drawShape(); this._drawFavicon(); }; FaviconBadger.prototype.update = function () { this.value = Math.min(99, parseInt(this.value.toString(), 10)); this._draw(); }; return FaviconBadger; }());