好玩的谷歌浏览器插件-自定义谷歌浏览器光标皮肤插件-Chrome 的自定义光标

周末没有啥事 看到了一个非常有意思的插件 就是 在使用谷歌浏览器的时候,可以把鼠标的默认样式换一个皮肤。就像下面的这种样子。

实际谷歌浏览器插件开发对于有前端编程基础的小伙伴 还是比较容易的,实际也是写 html css js 。
所以这个插件使用的技术:

html css 和 js 实现。

先看一下 最终实现的样子

大概插件就是这样的,使用方式 在下面选择我们喜欢的图标,然后选中后,点击应用选择 。这个时候我们再使用浏览器的时候 发现我们的鼠标光标 就变了一个皮肤。

周末闲着没事,就简单的也写了一个类似的插件,正好也是练习一下自己的前端技术。 插件功能大概实现了 光标皮肤切换。写完后 简单的测试了一下 ,可以使用。

分享一下代码结构

bash 复制代码
<!-- 作者:json -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="自定义光标皮肤,让您的浏览体验更加个性化">
  <title>自定义光标皮肤</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    :root {
      --primary-color: #3498db;
      --primary-dark: #2980b9;
      --danger-color: #e74c3c;
      --danger-dark: #c0392b;
      --text-color: #333;
      --text-light: #7f8c8d;
      --text-dark: #2c3e50;
      --bg-gradient: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
      --card-bg: rgba(255, 255, 255, 0.8);
      --shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
      --shadow-hover: 0 8px 15px rgba(0, 0, 0, 0.1);
      --border-radius: 10px;
      --transition: all 0.3s ease;
    }
    
    body {
      width: 360px;
      min-height: 480px;
      font-family: 'Microsoft YaHei', sans-serif;
      background: var(--bg-gradient);
      color: var(--text-color);
      padding: 20px;
      overflow-x: hidden;
    }
    
    .container {
      display: flex;
      flex-direction: column;
      height: 100%;
    }
    
    header {
      position: sticky;
      top: 0;
      z-index: 100;
      background: var(--bg-gradient);
      padding-bottom: 15px;
      margin-bottom: 20px;
      box-shadow: var(--shadow);
      border-radius: var(--border-radius);
    }
    
    .header-content {
      text-align: center;
      margin-bottom: 15px;
    }
    
    h1 {
      font-size: 24px;
      margin-bottom: 10px;
      color: var(--text-dark);
      text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
    }
    
    .subtitle {
      font-size: 14px;
      color: var(--text-light);
      margin-bottom: 15px;
    }
    
    .actions {
      display: flex;
      justify-content: center;
      margin-bottom: 10px;
    }
    
    .status {
      text-align: center;
      font-size: 14px;
      color: #27ae60;
      height: 20px;
      margin-top: 5px;
      transition: var(--transition);
    }
    
    .cursor-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 15px;
      margin-bottom: 20px;
      padding-top: 5px;
    }
    
    .cursor-item {
      background-color: var(--card-bg);
      border-radius: var(--border-radius);
      padding: 15px;
      cursor: pointer;
      transition: var(--transition);
      display: flex;
      flex-direction: column;
      align-items: center;
      box-shadow: var(--shadow);
      position: relative;
      height: 120px; /* 固定高度,确保所有项目大小一致 */
      justify-content: space-between; /* 确保内容均匀分布 */
      will-change: transform; /* 优化动画性能 */
    }
    
    .cursor-item:hover {
      transform: translateY(-5px);
      box-shadow: var(--shadow-hover);
    }
    
    .cursor-item.active {
      background-color: rgba(52, 152, 219, 0.2);
      border: 2px solid var(--primary-color);
    }
    
    .cursor-item.active::after {
      content: "✓";
      position: absolute;
      top: 5px;
      right: 5px;
      color: var(--primary-color);
      font-weight: bold;
    }
    
    .cursor-preview {
      width: 64px;
      height: 64px;
      margin-bottom: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: rgba(255, 255, 255, 0.5);
      border-radius: 8px;
      padding: 5px;
      position: relative;
    }
    
    .cursor-preview img {
      max-width: 32px; /* 限制最大宽度为32px */
      max-height: 32px; /* 限制最大高度为32px */
      width: auto; /* 保持宽高比 */
      height: auto; /* 保持宽高比 */
      object-fit: contain; /* 确保图片完全显示 */
      display: block; /* 消除底部间隙 */
      image-rendering: pixelated; /* 像素图片更清晰 */
      image-rendering: -moz-crisp-edges;
      image-rendering: crisp-edges;
    }
    
    /* 添加放大效果,方便用户查看小图标 */
    .cursor-preview:hover img {
      transform: scale(1.5);
      transition: transform 0.2s ease;
    }
    
    .cursor-name {
      font-size: 12px;
      text-align: center;
      color: var(--text-dark);
      width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    
    button {
      background-color: var(--primary-color);
      color: white;
      border: none;
      padding: 10px 20px;
      border-radius: 5px;
      cursor: pointer;
      font-size: 16px;
      transition: var(--transition);
      box-shadow: var(--shadow);
    }
    
    button:hover {
      background-color: var(--primary-dark);
      transform: translateY(-2px);
      box-shadow: var(--shadow-hover);
    }
    
    button:disabled {
      background-color: #bdc3c7;
      cursor: not-allowed;
      transform: none;
      box-shadow: none;
    }
    
    .reset-btn {
      background-color: var(--danger-color);
      margin-left: 10px;
    }
    
    .reset-btn:hover {
      background-color: var(--danger-dark);
    }
    
    .loading {
      display: none;
      text-align: center;
      margin: 20px 0;
    }
    
    .loading-spinner {
      border: 4px solid rgba(0, 0, 0, 0.1);
      border-left-color: var(--primary-color);
      border-radius: 50%;
      width: 30px;
      height: 30px;
      animation: spin 1s linear infinite;
      margin: 0 auto;
    }
    
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
    
    .empty-state {
      text-align: center;
      padding: 40px 20px;
      color: var(--text-light);
    }
    
    .empty-state p {
      margin-bottom: 15px;
    }
    
    /* 添加响应式设计 */
    @media (max-width: 320px) {
      .cursor-grid {
        grid-template-columns: repeat(2, 1fr);
      }
    }
    
    /* 添加暗黑模式支持 */
    @media (prefers-color-scheme: dark) {
      :root {
        --card-bg: rgba(30, 39, 46, 0.8);
        --text-color: #f5f6fa;
        --text-light: #dcdde1;
        --text-dark: #f5f6fa;
        --bg-gradient: linear-gradient(135deg, #2f3640 0%, #1e272e 100%);
        --shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
        --shadow-hover: 0 8px 15px rgba(0, 0, 0, 0.4);
      }
      
      .cursor-preview {
        background-color: rgba(0, 0, 0, 0.2);
      }
      
      button:disabled {
        background-color: #4b6584;
      }
    }
    
    /* 添加无障碍支持 */
    .sr-only {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      border-width: 0;
    }
    
    /* 键盘导航焦点样式 */
    .cursor-item:focus-visible {
      outline: 3px solid var(--primary-color);
      outline-offset: 2px;
    }
    
    button:focus-visible {
      outline: 3px solid white;
      outline-offset: 2px;
    }
  </style>
</head>
<body>
  <div class="container">
    <header>
      <div class="header-content">
        <h1>自定义光标皮肤</h1>
        <p class="subtitle">选择您喜欢的光标样式,让浏览体验更加个性化</p>
        <p class="subtitle">更多资源:www.wwwoop.com</p>
      </div>
      
      <div class="actions">
        <button id="apply-btn" disabled>应用选择</button>
        <button id="reset-btn" class="reset-btn">恢复默认</button>
      </div>
      
      <div id="status" class="status" aria-live="polite"></div>
    </header>
    
    <div id="loading" class="loading" aria-hidden="true">
      <div class="loading-spinner"></div>
      <p class="sr-only">正在加载光标...</p>
    </div>
    
    <div id="cursor-grid" class="cursor-grid" role="listbox" aria-label="光标选项列表">
      <!-- 光标选项将通过JavaScript动态加载 -->
    </div>
    
    <div id="empty-state" class="empty-state" style="display: none;">
      <p>没有找到光标皮肤</p>
      <p>请确保images文件夹中有光标图片</p>
    </div>
  </div>
  
  <script src="popup.js"></script>
</body>
</html> 

以上就是 html 代码

插件写完后,也装到了自己的谷歌浏览器上测试了一下,可以正常使用。但是不保证是否还有细节性的bug。如果有小伙伴 对这个插件有兴趣,可以拿去玩一玩。
代码完全开源 ,因为是自己写的插件,所以没有上架到谷歌应用商店,大家拿到插件后,有开发能力的小伙伴可以自由发挥。直接安装使用也是可以的。
https://wwwoop.com/home/Index/projectInfo?goodsId=56&typeParam=1&subKey=0

相关推荐
vvilkim8 分钟前
全面解析React内存泄漏:原因、解决方案与最佳实践
前端·javascript·react.js
vvilkim14 分钟前
React批处理(Batching)更新机制深度解析
前端·javascript·react.js
Bayi·19 分钟前
前端面试场景题
开发语言·前端·javascript
程序猿熊跃晖1 小时前
Vue中如何优雅地处理 `<el-dialog>` 的关闭事件
前端·javascript·vue.js
进取星辰1 小时前
12、高阶组件:魔法增幅器——React 19 HOC模式
前端·javascript·react.js
拉不动的猪1 小时前
前端低代码开发
前端·javascript·面试
程序员张31 小时前
Vue3集成sass
前端·css·sass
夜跑者1 小时前
axios 在请求拦截器中设置Content-Type无效问题
前端
知识分享小能手1 小时前
JavaScript学习教程,从入门到精通,Ajax与Node.js Web服务器开发全面指南(24)
开发语言·前端·javascript·学习·ajax·node.js·html5
烛阴1 小时前
Swizzling--OpenGL的向量的灵活组合
前端·webgl