【油猴脚本】整了个更实在的防沉迷

这论坛是不是掺了点什么,论文都没写整天尽逛论坛了 :rofl:

23 天,纯手动 36.4k 帖子 :crazy_face:
image

在论坛有看到有大佬做过论坛防沉迷脚本了

但是并不太满足我的需求,于是自己整了个

视频预览:point_down:不知道能不能加载出来,能加载出来也有点糊,凑合看吧 :smiling_face_with_tear:

可以自行调整时间大小、防沉迷时长等,默认每隔半小时防沉迷一分钟
用的 canvas 动画,默认为约 90 帧,对电脑性能还是有点要求的,可以自行更改帧率
当然有大佬能帮忙优化下就更好了 :yum:

睡了睡了,快六点,感觉要寄了 :crazy_face:

脚本在这
// ==UserScript==
// @name         背景时间弹弹弹
// @namespace    http://tampermonkey.net/
// @version      2024-04-30
// @description  背景时间弹弹弹
// @author       You
// @match        https://linux.do/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=linux.do
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

  // 防沉迷基本参数
  const antiAddictionConfig = {
    enabled: true, //是否启用防沉迷
    time: [0, 30], //启用时间
    duration: 60, //持续时间
    background: "rgba(0,0,0,0.3)", // 防沉迷背景颜色
    backdropFilter: "blur(20px)", // 防沉迷背景模糊
    zIndex: "100000", // 防沉迷背景层级(默认置于顶层,设为负则置于底层)
  };

  // 时间基本参数
  const timeConfig = {
    showSize: 10, // 时间数字大小(整数)
    speed: 1, // 移动速度(可为小数)
    zIndex: 100000, // 时间数字层级(默认置于顶层,设为负则置于底层)
    frameRate: 90, // 动画帧率
    colorList: [
      "#c12c1f",
      "#e18a3b",
      "#ffee6f",
      "#4f6f46",
      "#108b96",
      "#3271ae",
      "#a6559d",
      "#d4dde1",
      "#b2b6b6",
      "#151d29",
    ], // 随机颜色池
  };
  const digit = [
    // 每个数字的5x7点阵表示,1表示亮点,0表示灭点
    // 0
    [
      [0, 1, 1, 1, 0],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
    ],
    // 1
    [
      [0, 0, 1, 0, 0],
      [0, 1, 1, 0, 0],
      [0, 0, 1, 0, 0],
      [0, 0, 1, 0, 0],
      [0, 0, 1, 0, 0],
      [0, 0, 1, 0, 0],
      [0, 1, 1, 1, 0],
    ],
    // 2
    [
      [0, 1, 1, 1, 0],
      [1, 0, 0, 0, 1],
      [0, 0, 0, 0, 1],
      [0, 0, 0, 1, 0],
      [0, 0, 1, 0, 0],
      [0, 1, 0, 0, 0],
      [1, 1, 1, 1, 1],
    ],
    // 3
    [
      [0, 1, 1, 1, 0],
      [1, 0, 0, 0, 1],
      [0, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
      [0, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
    ],
    // 4
    [
      [1, 0, 0, 1, 0],
      [1, 0, 0, 1, 0],
      [1, 0, 0, 1, 0],
      [1, 1, 1, 1, 1],
      [0, 0, 0, 1, 0],
      [0, 0, 0, 1, 0],
      [0, 0, 0, 1, 0],
    ],
    // 5
    [
      [1, 1, 1, 1, 1],
      [1, 0, 0, 0, 0],
      [1, 0, 0, 0, 0],
      [0, 1, 1, 1, 0],
      [0, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
    ],
    // 6
    [
      [0, 1, 1, 1, 0],
      [1, 0, 0, 0, 0],
      [1, 0, 0, 0, 0],
      [0, 1, 1, 1, 1],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
    ],
    // 7
    [
      [1, 1, 1, 1, 1],
      [0, 0, 0, 0, 1],
      [0, 0, 0, 1, 0],
      [0, 0, 1, 0, 0],
      [0, 0, 1, 0, 0],
      [0, 1, 0, 0, 0],
      [0, 1, 0, 0, 0],
    ],
    // 8
    [
      [0, 1, 1, 1, 0],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
    ],
    // 9
    [
      [0, 1, 1, 1, 0],
      [1, 0, 0, 0, 1],
      [1, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
      [0, 0, 0, 0, 1],
      [0, 0, 0, 0, 1],
      [0, 1, 1, 1, 0],
    ],
  ];

  // 初始化遮罩和canvas
  const mask = document.createElement("div");
  Object.assign(mask.style, {
    position: "fixed",
    top: 0,
    left: 0,
    width: "100vw",
    height: "100vh",
    background: antiAddictionConfig.background,
    backdropFilter: antiAddictionConfig.backdropFilter,
    zIndex: antiAddictionConfig.zIndex,
    pointerEvents: "auto",
    display: "none",
  });
  document.body.appendChild(mask);

  const canvas = document.createElement("canvas");
  if (!canvas.getContext) {
    alert("您的浏览器不支持canvas,无法显示时间背景!");
  }
  document.body.appendChild(canvas);
  Object.assign(canvas, {
    width: window.innerWidth,
    height: window.innerHeight,
  });
  Object.assign(canvas.style, {
    position: "fixed",
    left: "0",
    top: "0",
    pointerEvents: "none",
    zIndex: timeConfig.zIndex,
  });
  const ctx = canvas.getContext("2d");

  // 初始化动画参数
  function initAnimationParams(config, canvas) {
    const width = 40 * config.showSize; // 时间数字宽度
    const height = 8 * config.showSize; // 时间数字高度
    const radius = config.showSize / 2 - 1; // 半径
    // 随机初始位置
    let mx = Math.floor(Math.random() * (canvas.width - width));
    let my = Math.floor(Math.random() * (canvas.height - height));
    // 随机方向
    let dx = config.speed * (Math.random() < 0.5 ? -1 : 1);
    let dy = config.speed * (Math.random() < 0.5 ? -1 : 1);

    return { width, height, radius, mx, my, dx, dy };
  }
  const params = initAnimationParams(timeConfig, canvas);

  // 绘制单个数字点阵
  function renderDigit(x, y, num, ctx) {
    for (let i = 0; i < digit[num].length; i++) {
      for (let j = 0; j < digit[num][i].length; j++) {
        if (digit[num][i][j] == 1) {
          ctx.beginPath();
          ctx.arc(
            x + j * timeConfig.showSize,
            y + i * timeConfig.showSize,
            params.radius,
            0,
            (params.radius / 2) * Math.PI
          );
          ctx.fill();
        }
      }
    }
  }

  // 绘制冒号点阵
  function renderColon(x, y, ctx) {
    ctx.beginPath();
    ctx.arc(
      x,
      y + 2 * timeConfig.showSize,
      params.radius,
      0,
      (params.radius / 2) * Math.PI
    );
    ctx.fill();
    ctx.beginPath();
    ctx.arc(
      x,
      y + 4 * timeConfig.showSize,
      params.radius,
      0,
      (params.radius / 2) * Math.PI
    );
    ctx.fill();
  }

  function updateAnimation(lastTime) {
    // ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
    const currentTime = new Date();
    const hours = currentTime.getHours();
    const minutes = currentTime.getMinutes();
    const seconds = currentTime.getSeconds();

    // 检查是否需要更新遮罩显示状态
    if (antiAddictionConfig.enabled) {
      mask.style.display =
        antiAddictionConfig.time.includes(minutes) &&
        seconds < antiAddictionConfig.duration
          ? ""
          : "none";
    }

    // 获取当前时间的时间戳
    const now = performance.now();
    // 检查是否已经过了足够的时间来更新动画
    if (now - lastTime > Math.floor(1000 / timeConfig.frameRate)) {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
      // 动画更新逻辑
      renderDigit(
        params.mx + timeConfig.showSize,
        params.my + timeConfig.showSize,
        parseInt(hours / 10),
        ctx
      );
      renderDigit(
        params.mx + 7 * timeConfig.showSize,
        params.my + timeConfig.showSize,
        hours % 10,
        ctx
      );
      // 如果秒数是偶数,则显示冒号
      if (seconds % 2 == 0) {
        renderColon(
          params.mx + 13 * timeConfig.showSize,
          params.my + timeConfig.showSize,
          ctx
        );
      }
      renderDigit(
        params.mx + 15 * timeConfig.showSize,
        params.my + timeConfig.showSize,
        parseInt(minutes / 10),
        ctx
      );
      renderDigit(
        params.mx + 21 * timeConfig.showSize,
        params.my + timeConfig.showSize,
        minutes % 10,
        ctx
      );
      // 如果秒数是偶数,则显示冒号
      if (seconds % 2 == 0) {
        renderColon(
          params.mx + 27 * timeConfig.showSize,
          params.my + timeConfig.showSize,
          ctx
        );
      }
      renderDigit(
        params.mx + 29 * timeConfig.showSize,
        params.my + timeConfig.showSize,
        parseInt(seconds / 10),
        ctx
      );
      renderDigit(
        params.mx + 35 * timeConfig.showSize,
        params.my + timeConfig.showSize,
        seconds % 10,
        ctx
      );

      // 更新上一次更新的时间戳
      lastTime = now;
    }
    // 检测边界碰撞并反转方向
    if (
      params.mx + params.dx > ctx.canvas.width - params.width ||
      params.mx + params.dx < 0
    ) {
      params.dx = -params.dx;
      // 随机更换颜色
      ctx.fillStyle =
        timeConfig.colorList[
          Math.floor(Math.random() * timeConfig.colorList.length)
        ];
    }
    if (
      params.my + params.dy > ctx.canvas.height - params.height ||
      params.my + params.dy < 0
    ) {
      params.dy = -params.dy;
      // 随机更换颜色
      ctx.fillStyle =
        timeConfig.colorList[
          Math.floor(Math.random() * timeConfig.colorList.length)
        ];
    }

    // 更新位置
    params.mx += params.dx;
    params.my += params.dy;

    // 请求下一帧动画
    requestAnimationFrame(() => updateAnimation(lastTime));
  }

  // 启动动画循环
  requestAnimationFrame(() => updateAnimation(performance.now()));
})();
7 个赞

好家伙

说吧,你是哪个部门派来的…… :face_with_peeking_eye:

我的建议是反向思考,每半个小时提示你才水这么点时间

不要阻止我水经验 :rofl:

这是谁的部下:thinking:

真正的放下,是诱惑在你眼前你可以视而不见

+2

From #dev to 开发调优