Edge 浏览器插件开发:图片切割插件

Edge 浏览器插件开发:图片切割插件

在图片处理领域,按比例切割图片是一个常见需求。本文将带你开发一个 Edge 浏览器插件,用于将用户上传的图片分割成 4 个部分并自动下载到本地。同时,本文介绍如何使用 cursor 辅助工具来更高效地实现和调试插件功能。

先看效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
点击分割图片后:
在这里插入图片描述
在这里插入图片描述

功能概述

插件的主要功能包括:

  1. 用户上传并预览图片。
  2. 将图片平均分割成 4 份。
  3. 自动下载分割的图片到本地默认文件夹。

通过 cursor 辅助工具,我们可以高效地管理代码中的事件和操作流,确保插件在多个步骤中流畅运行,并能够在图片加载、分割和下载的每个关键步骤中实时监控进程状态。


使用 cursor 辅助工具

在插件开发中,cursor 工具可以帮助我们实现多步事件的顺序执行和状态管理。下面的代码将展示如何在 popup.js 中利用 cursor 来管理图片处理流程。


开发步骤

1. 创建项目结构

在项目目录下创建以下文件:

  • manifest.json:插件的配置文件。
  • popup.html:插件的用户界面。
  • popup.js:实现插件的核心逻辑和 cursor 功能。
  • icons 目录:存储插件的图标文件(如 icon16.pngicon48.png 等)。
2. 配置 manifest.json

manifest.json 是插件的核心配置文件,声明了插件的基础信息和权限。该插件需要 downloads 权限来下载图片到本地。代码如下:

{
  "manifest_version": 3,
  "name": "图片分割工具",
  "version": "1.0",
  "description": "将图片平均分割成4份并下载",
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "32": "icons/icon32.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "permissions": ["downloads"]
}
3. 设计用户界面 popup.html

popup.html 中设计用户界面,包括文件选择器、图片预览、分割按钮和状态显示区域:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body { width: 300px; padding: 10px; font-family: Arial, sans-serif; }
    #preview { max-width: 100%; margin: 10px 0; border: 1px solid #ccc; }
    .button { width: 100%; padding: 8px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }
    .button:disabled { background-color: #cccccc; }
    #status { margin-top: 10px; color: #333; background-color: #f0f0f0; border-radius: 4px; padding: 5px; }
  </style>
</head>
<body>
  <input type="file" id="imageInput" accept="image/*">
  <img id="preview" style="display: none;">
  <button id="splitButton" class="button" disabled>分割图片</button>
  <div id="status">请选择一张图片</div>
  <script src="popup.js"></script>
</body>
</html>
4. 实现核心逻辑 popup.js

popup.js 中使用 cursor 工具来管理图片处理步骤,包括加载、分割、和自动下载。

// 使用 cursor 工具在多步流程中跟踪状态和事件
import cursor from 'cursor';

document.addEventListener('DOMContentLoaded', function() {
  const imageInput = document.getElementById('imageInput');
  const preview = document.getElementById('preview');
  const splitButton = document.getElementById('splitButton');
  const status = document.getElementById('status');
  let originalImage = null;
  let originalFileName = '';

  const showStatus = cursor.create({
    defaultStatus: '请选择一张图片',
    updateStatus: function(message) {
      status.textContent = message;
      console.log(message);
    }
  });

  imageInput.addEventListener('change', function(e) {
    const file = e.target.files[0];
    if (file) {
      originalFileName = file.name.replace(/\.[^/.]+$/, '');
      showStatus.updateStatus('正在加载图片...');
      
      const reader = new FileReader();
      reader.onload = function(event) {
        preview.src = event.target.result;
        preview.style.display = 'block';
        originalImage = new Image();
        originalImage.src = event.target.result;
        originalImage.onload = function() {
          splitButton.disabled = false;
          showStatus.updateStatus(`图片已加载,尺寸: ${originalImage.width}x${originalImage.height}`);
        };
      };
      reader.readAsDataURL(file);
    }
  });

  splitButton.addEventListener('click', async function() {
    try {
      if (!originalImage) {
        showStatus.updateStatus('请先选择图片');
        return;
      }

      splitButton.disabled = true;
      showStatus.updateStatus('开始分割图片...');

      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const partWidth = Math.floor(originalImage.width / 2);
      const partHeight = Math.floor(originalImage.height / 2);
      
      canvas.width = partWidth;
      canvas.height = partHeight;

      for (let row = 0; row < 2; row++) {
        for (let col = 0; col < 2; col++) {
          ctx.clearRect(0, 0, canvas.width, canvas.height);
          ctx.drawImage(
            originalImage,
            col * partWidth, row * partHeight,
            partWidth, partHeight,
            0, 0,
            partWidth, partHeight
          );

          const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
          const url = URL.createObjectURL(blob);
          
          try {
            await chrome.downloads.download({
              url: url,
              filename: `${originalFileName}_split_${row+1}x${col+1}.png`,
              saveAs: false
            });
            showStatus.updateStatus(`已完成 ${row * 2 + col + 1}/4 张图片`);
          } catch (error) {
            console.error('下载失败:', error);
            showStatus.updateStatus(`下载失败: ${error.message}`);
          } finally {
            URL.revokeObjectURL(url);
          }
        }
      }

      showStatus.updateStatus('所有图片分割完成!');
    } catch (error) {
      console.error('处理过程出错:', error);
      showStatus.updateStatus(`处理出错: ${error.message}`);
    } finally {
      splitButton.disabled = false;
    }
  });
});

运行与测试

1. 加载插件

在 Edge 浏览器中,访问 edge://extensions/,启用“开发者模式”,选择“加载已解压的扩展程序”并选择项目文件夹。

2. 测试流程
  1. 上传一张图片,确认图片是否成功显示在预览区域。
  2. 点击“分割图片”按钮,观察插件是否顺利完成图片分割和下载。
3. cursor 调试优势
  • 进度实时更新cursor 帮助我们实时跟踪每一步的状态,如“图片加载中”、“开始分割图片”等,让用户直观地了解操作进度。
  • 错误捕捉与提示:利用 cursor 定位和反馈错误信息,确保用户在出现异常时能够清楚知道原因。

总结与扩展思路

通过本插件,我们了解了图片分割处理的基本流程,以及如何借助 cursor 工具在插件开发中高效管理流程。插件在 Edge 和 Chrome 浏览器上均可运行,并支持进一步扩展,例如添加用户自定义切割比例、支持不同的文件格式和 UI 优化。

借助 cursor,你可以让插件的事件流更可控、流程更顺畅。这为进一步优化插件功能和用户体验提供了良好的基础。如果你有其他想法或改进建议,欢迎一起讨论!


参考网址:https://mp.weixin.qq.com/s/KZt5-3OxCtlwuTKhplzGCg
完整代码网址:https://github.com/yyq2024/split_image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/906035.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT QPainter 绘图

QT QPainter 绘图 一、基本绘图类&#xff1a; Qt 中提供了强大的 2D 绘图系统&#xff0c;可以使用相同的 API 在屏幕和绘图设备上进行绘制&#xff0c;它主要基于QPainter、QPaintDevice 和 QPaintEngine 这三个类。 QPainter 用于执行绘图操作&#xff0c;其提供的 API 在…

【C++】位图详解(一文彻底搞懂位图的使用方法与底层原理)

目录 1.位图的概念 2.位图的使用方法 定义与创建 设置和清除 位访问和检查 转换为其他格式 3.位图的使用场景 1.快速的查找某个数据是否在一个集合中 2.排序去重 3.求两个集合的交集和并集 4.位图的底层实现 私有成员定义与初始化 set和reset的实现 前面的博客我们…

在线教育系统源码开发详解:网校培训平台搭建的核心技术

本篇文章&#xff0c;笔者将详细介绍在线教育系统源码的开发过程&#xff0c;重点聚焦网校培训平台搭建的核心技术&#xff0c;以期为有意从事在线教育行业的开发者提供实用的参考。 一、在线教育系统的构成 前端负责用户的交互体验&#xff0c;后端处理业务逻辑&#xff0c;…

qt QPalette详解

1、概述 QPalette是Qt框架中用于管理颜色组和角色的一种机制。它允许开发者为应用程序中的不同组件&#xff08;如窗口、按钮、文本框等&#xff09;定义一套统一的颜色方案。QPalette通过定义颜色角色&#xff08;如背景色、前景色、选择色等&#xff09;和颜色组&#xff08…

Java基本语法和基础数据类型——针对实习面试

目录 Java基本语法和基础数据类型标识符和关键字有什么区别&#xff1f;Java关键字有哪些&#xff1f;Java基本数据类型有哪些&#xff1f;什么是自动装箱和拆箱&#xff1f;自动装箱&#xff08;Autoboxing&#xff09;自动拆箱&#xff08;Unboxing&#xff09; 自动装箱和拆…

逻辑磁盘管理 附实验:逻辑卷的组成与划分

分区类型&#xff1a; 1、系统引导分区 就是存放系统的引导文件和Linux的内核文件 2、swap分区 交换分区&#xff0c;系统的物理内存不足时&#xff0c;从一些长时间未运行的程序当中释放一部分内存释放出来的保存到swap分区&#xff0c;这些未运行的程序一旦运行还要从swap空…

fetch: 取消请求、读取流、获取下载进度...

引言 Fetch API 提供了一个获取资源的接口(包括跨网络通信)。对于任何使用过 XMLHttpRequest 的开发者来说, 对于 Fetch 应该都能轻松上手, 而且新的 API 提供了更强大和灵活的功能集… 本文主要就是记录下, 在使用 Fetch 期间可能会碰到的几个小案例… 一、取消请求 在前端…

【 纷享销客-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

mobaxterm 中文输入问号解决办法

无论是终端&#xff0c;还是session的name&#xff0c;输入中文都是问号&#xff0c;那么使用以下方法可解决问题 语言设置中找到英文键盘删除即可

Hive的数据存储格式

目录 一、前言 二、存储格式 2.1、文本格式&#xff08;TextFile&#xff09; 2.1.1、定义与特点 2.1.2、存储与压缩 2. 1.3、使用场景 2.2、行列式文件&#xff08;ORCFile&#xff09; 2.2.1、ORC的结构 2.2.2、ORC的数据类型 2.2.3、ORC的压缩格式 2.2.3、ORC存储…

Spring Boot的核心优势及其应用详解

目录 前言1. Spring Boot的核心优势1.1 启动依赖的集成1.2 自动化配置 2. 内嵌服务器支持2.1 内嵌Tomcat服务器2.2 独立运行与便捷部署 3. 外部配置管理3.1 多环境支持3.2 配置优先级与外部化配置 4. Spring Boot的应用场景4.1 微服务架构4.2 云原生应用 结语 前言 在现代的Ja…

scala---10.30

val、var package com_1030class Person {var name:String"rose"def sum(n1:Int,n2:Int):Int{n1n2} } object Person{def main(args: Array[String]): Unit {//创建person对象var personnew Person()println(person.sum(10,20))//30println(person.name)person.nam…

ubuntu22.04 docker-compose搭建apisix高可用

首先你得先确保每台主机安装了docker和docker-compose 3台主机 没有安装docker和docker-compose的可以看我前两篇博客 可以先克隆仓库 git clone https://github.com/apache/apisix-docker.git 进入example目录 拷贝dashboard配置文件 将all-in-one中apisix-dashboard文件夹拷…

北大计算机考研难度如何?毕业后就业情况怎么样?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 一、总体情况概述 北京大学计算机 2024 届考研整体呈现 “稳中有升” 的态势。在复试分数线方面&#xff0c;无论是学硕&#xff08;本部&#xff09;还是专硕&#xff08;深圳&#xff09;&#xff0c;较 2023 届均有…

黑马JavaWeb-day04

文章目录 mavenmaven 简介maven 安装IDEA集成maven创建maven项目Maven 坐标依赖管理单元测试 Web入门Springboot 入门HTTP协议三层架构分层解耦 I O C & D I IOC\&DI IOC&DI入门 I O C IOC IOC和 D I DI DI详解 maven maven 简介 maven: M a v e n Maven Maven是…

什么是FUSE用户态文件系统

零. 文件系统 1. 为什么要有文件系统 文件系统是操作系统中管理文件和目录的一种机制。它提供了组织、存储、检索和更新文件的方法&#xff0c;主要如下&#xff1a; 数据组织&#xff1a;文件系统将数据组织成文件和目录&#xff0c;使用户能够更方便地管理和查找文件。每个…

品牌怎么找到用户发的优质内容,进行加热、复制?

在&#xff0c;相对传统媒体来说&#xff0c;社交媒体营销具有更高的成本效益。品牌可以通过相对较低的成本达到大量潜在客户&#xff0c;尤其是通过口碑营销和内容分享&#xff0c;可以实现倍增的传播效果。在社媒营销的过程中&#xff0c;去找到与品牌有关的优质、正向内容&a…

梁山派入门指南3——串口使用详解,包括串口发送数据、重定向、中断接收不定长数据、DMA+串口接收不定长数据,以及对应的bsp文件和使用示例

梁山派入门指南3——串口使用详解&#xff0c;包括串口发送数据、重定向、中断接收不定长数据、DMA串口接收不定长数据&#xff0c;以及对应的bsp文件和使用示例 1. 串口发送数据1.1 串口简介1.2 梁山派上的串口开发1.3 bsp_uart文件&#xff08;只发送不接收&#xff0c;兼容串…

notepad++ compare插件的离线下载和安装

一、离线安装 去改地址找到最新的插件&#xff1a;https://github.com/notepad-plus-plus/nppPluginList/blob/master/doc/plugin_list_x64.md下载之后复制到插件文件夹&#xff0c;插件文件夹的打开方式如下 注意目录&#xff1a; 二、问题汇总 &#xff08;1&#xff09…

你的网站需要防护吗?

你的网站经常被恶意爬虫&#xff0c;重要数据被批量搬运吗&#xff1f; 你想知道你的网站是不是安全的&#xff0c;有没有被 xss攻击、sql注入、命令注入等等这些乱七八糟的攻击手段攻击吗&#xff1f; 2014年我还是学生的时候&#xff0c;负责学院官网的维护&#xff0c;一…