tui-image-editor 强大的图像编辑器

主要介绍了TUI Image Editor图像编辑器的使用及配置,如预览配置汉化处理、自定义主题样式、自定义功能等;也介绍了react和vue中的使用,及使用过程中碰到的问题和解决方案

TUI Image Editor 是一个基于 JavaScript 的独立图像编辑库,它使用 HTML5 的 Canvas 技术,提供了丰富的图片处理功能,适合集成到 Web 应用程序中,让用户在浏览器内就能进行图片编辑操作。主要功能如下:

  1. 照片处理:支持基本的图片裁剪、翻转、旋转功能。
  2. 绘图工具:允许用户在图片上自由绘制线条、形状,支持多种笔触颜色和宽度。
  3. 文本添加:可以在图片上添加自定义文本,调整字体、大小、颜色和位置。
  4. 图标与形状:内置多种图标和形状,方便用户快速添加装饰元素。
  5. 滤镜与效果:提供多种预设的图片滤镜和效果,增强图片视觉效果。
  6. 遮罩功能:可以应用不同的遮罩效果,为图片添加创意风格。
  7. 自定义图标:支持添加自定义图标到工具栏,扩展编辑器功能。
  8. 主题定制:允许开发者自定义编辑器的外观,包括颜色、按钮图标等。

TUI Image Editor官网地址:ui.toast.com/tui-image-e...

TUI Image Editor Github 地址:github.com/nhn/tui.ima...,可以单用,也支持 react 和 vue

1. tui-image-editor

  1. 安装依赖
bash 复制代码
# 安装命令
npm install tui-image-editor
  1. 引入样式及编辑器
js 复制代码
// 导入`tui-color-picker`CSS样式
import "tui-color-picker/dist/tui-color-picker.css";
// 导入`tui-image-editor`的CSS样式
import "tui-image-editor/dist/tui-image-editor.css";
// 导入`tui-image-editor`库
import ImageEditor from "tui-image-editor";
  1. 常用配置
js 复制代码
// tui-image-editor语言配置,汉化文字
export const localeCN = {
  Resize: "调整宽高",
  Crop: "裁剪",
  Flip: "镜像",
  Rotate: "旋转",
  Draw: "画笔",
  Shape: "形状标注",
  Icon: "图标标注",
  Text: "文字标注",
  Mask: "遮罩",
  Filter: "滤镜",

  Download: "下 载",
  Load: "上 传",

  Free: "任意线条",
  Straight: "直线",
  Color: "颜色",
  Range: "粗细",

  ZoomIn: "放大",
  ZoomOut: "缩小",
  Hand: "手掌",
  History: "历史",
  Undo: "撤销",
  Redo: "反撤销",
  Reset: "重置",
  Delete: "删除",
  DeleteAll: "全部删除",

  Bold: "加粗",
  Italic: "斜体",
  Underline: "下划线",
  Left: "左对齐",
  Center: "居中",
  Right: "右对齐",
  "Text size": "字体大小",
  Custom: "自定义",
  Square: "正方形",
  Apply: "应用",
  Cancel: "取消",
  "Flip X": "X 轴",
  "Flip Y": "Y 轴",
  Stroke: "描边",
  Fill: "填充",
  Circle: "圆",
  Triangle: "三角",
  Rectangle: "矩形",
  Arrow: "箭头",
  "Arrow-2": "箭头2",
  "Arrow-3": "箭头3",
  "Star-1": "星星1",
  "Star-2": "星星2",
  Polygon: "多边形",
  Location: "定位",
  Heart: "心形",
  Bubble: "气泡",
  "Custom icon": "自定义图标",
  "Load Mask Image": "加载蒙层图片",
  Grayscale: "灰度",
  Blur: "模糊",
  Sharpen: "锐化",
  Emboss: "浮雕",
  "Remove White": "除去白色",
  Distance: "距离",
  Brightness: "亮度",
  Noise: "噪音",
  "Color Filter": "彩色滤镜",
  Sepia: "棕色",
  Sepia2: "棕色2",
  Invert: "负片",
  Pixelate: "像素化",
  Threshold: "阈值",
  Tint: "色调",
  Multiply: "正片叠底",
  Blend: "混合色",
};

// tui-image-editor自定义主题样式
export const customTheme = {
  // image 坐上角度图片
  "common.bi.image": "", // 替换logo图片 我直接不显示
  "common.bisize.width": "0px",
  "common.bisize.height": "0px",
  // "common.backgroundImage": "none",
  "common.border": "1px solid #d5cfcf",
  "common.backgroundColor": "#fff", // 整体背景颜色

  // header(头部)
  // "header.backgroundImage": "none",
  // "header.border": "0px",
  "header.backgroundColor": "#000", // 头部的背景颜色

  // load button(上传按钮)
  // "loadButton.backgroundColor": "#fff",
  // "loadButton.border": "1px solid #ddd",
  // "loadButton.color": "#222",
  // "loadButton.fontFamily": "NotoSans, sans-serif",
  // "loadButton.fontSize": "12px",
  "loadButton.display": "none", // 可以直接隐藏掉"上传"按钮

  // download button(下载按钮)
  // "downloadButton.backgroundColor": "#fdba3b", // 下载按钮背景颜色
  // "downloadButton.border": "1px solid #fdba3b", // 下载按钮边框样式
  // "downloadButton.color": "#fff", // 下载按钮文字颜色
  // "downloadButton.fontFamily": "NotoSans, sans-serif",
  // "downloadButton.fontSize": "12px",
  "downloadButton.display": "none", // 可以直接隐藏掉"下载"按钮

  // rango style
  // "range.pointer.color": "#fff",
  // "range.bar.color": "#666",
  // "range.subbar.color": "#d1d1d1",

  // "range.disabledPointer.color": "#414141",
  // "range.disabledBar.color": "#282828",
  // "range.disabledSubbar.color": "#414141",

  // "range.value.color": "#fff",
  // "range.value.fontWeight": "lighter",
  // "range.value.fontSize": "11px",
  // "range.value.border": "1px solid #353535",
  // "range.value.backgroundColor": "#151515",
  // "range.title.color": "#fff",
  // "range.title.fontWeight": "lighter",

  // colorpicker style
  // "colorpicker.button.border": "1px solid #1e1e1e",
  // "colorpicker.title.color": "#fff",

  // // 菜单-普通状态 - 绿色
  "menu.normalIcon.color": "#2d8cf0",
  // // 菜单-选中状态 - 蓝色
  "menu.activeIcon.color": "blue",
  // // 菜单-禁用状态 - 灰色
  "menu.disabledIcon.color": "grey",
  // // 菜单-鼠标悬浮状态 - 黄色
  "menu.hoverIcon.color": "yellow",
};
  1. 创建编辑器实例
js 复制代码
// 定义编辑器的配置选项
const options = {
  // 编辑器的配置,如UI、尺寸、样式等
  includeUI: {
    // menu: ["draw", "text"], // 支持的菜单
    // initMenu: "draw", // 默认开启绘图的功能,初始化时显示的菜单
    menuBarPosition: "bottom", // 菜单栏位置
    loadImage: { path: "", name: "预览图片" }, // 默认加载的图片
    locale: localeCN, // 文字汉化
    theme: customTheme, // 样式修改
  },
  cssMaxWidth: 700,
  cssMaxHeight: 500,
  selectionStyle: {
    cornerSize: 20,
    rotatingPointOffset: 70,
  },
};
js 复制代码
// 定义渲染元素
<div id="tui-image-editor" ref={editorRef}></div>;

// 定义一个用于存储编辑器DOM元素的引用
const editorRef = useRef < HTMLDivElement > null;

useEffect(() => {
  if (!editorRef.current) return; // 确保DOM元素存在

  // 创建ImageEditor实例
  const editor = new ImageEditor(editorRef.current, options);
  // 加载图片 图片路径public/img/example.png
  editor
    .loadImageFromURL("/img/example.png", "预览图片")
    .then(() => {
      console.log("图片加载成功");
    })
    .catch((error) => console.error("加载图片失败:", error));
}, []);

初始化效果如下所示:

1.1 底部操作按钮无效

问题描述:通过上述方法加载图片,可以正常渲染出来,但是点击底部操作按钮,发现没反应;重新上传一张图片后,可以正常操作了。

问题解决:改了一下操作逻辑(先赋值,再初始化),就可以了

js 复制代码
useEffect(() => {
  if (!editorRef.current) return; // 确保DOM元素存在

  // 先赋值
  options.includeUI.loadImage.path = "/img/example.png";

  // 初始化编辑器
  const editor = new ImageEditor(editorRef.current, options);
}, []);

自定义样式后整体效果:

1.2 自定义菜单配置

  1. 自定义工具栏配置:提供配置参数,可以单独配置
js 复制代码
// 自定义工具栏的全部菜单
menu: [
  "resize",
  "crop",
  "flip",
  "rotate",
  "draw",
  "shape",
  "icon",
  "text",
  "mask",
  "filter",
];

// 我只保留画笔和文字标注
menu: ["draw", "text"],
  1. 固定工具栏配置:没有提供配置项,直接通过 css 样式隐藏

顶部工具栏菜单:没有单独配置的地方,针对每个按钮调整

css 复制代码
/* // 修改样式 */
.tui-image-editor-header {
  display: none;
}
.tui-image-editor-container .tui-image-editor-help-menu.top {
  display: none;
}
.tui-image-editor-container .tui-image-editor-main {
  top: 0;
}

1.3 自定义按钮事件

不想用默认的点击事件,通过自定义按钮触发事件。以画笔按钮为例

js 复制代码
const handleDraw = () => {
  const ele = document.getElementsByClassName("tie-btn-draw"); // 获取画笔元素
  if (ele.length > 0 && ele[0] instanceof HTMLElement) {
    // 确保至少有一个匹配的元素
    ele[0].click(); // 通过索引 [0] 访问第一个元素并触发 click 事件
  }
};

最终效果如下所示:

2. react-image-editor

bash 复制代码
# 安装命令
npm install --save @toast-ui/react-image-editor

# 强制安装命令
npm install --save @toast-ui/react-image-editor --force
# 或者
npm install --save @toast-ui/react-image-editor --legacy-peer-deps

我安装时报错了,如下 tui-2 所示:

遇到 npm ERR! ERESOLVE unable to resolve dependency tree 错误,通常是因为项目中存在依赖版本冲突

我的项目中 react 版本为 18.3.1,但是 @toast-ui/react-image-editor@3.15.2 要求的 react 版本是 ^17.0.2,这导致了冲突。

解决方法,报错信息中也提供了,使用 --force--legacy-peer-deps参数强制 npm 忽略依赖冲突并继续安装。

但是这样做可能会引入不兼容的依赖,导致运行时错误。

还有一种解决方法,就是降级 react 版本

bash 复制代码
npm uninstall react react-dom
npm install react@17.0.2 react-dom@17.0.2
相关推荐
前端李易安2 小时前
Web常见的攻击方式及防御方法
前端
PythonFun2 小时前
Python技巧:如何避免数据输入类型错误
前端·python
hakesashou2 小时前
python交互式命令时如何清除
java·前端·python
天涯学馆2 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF2 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi2 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi3 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript
凌云行者3 小时前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
华农第一蒟蒻3 小时前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
积水成江3 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js