Мощный плагин для редактирования изображений, у которого нет друзей, мне он нравится!

внешний интерфейс Vue.js
Мощный плагин для редактирования изображений, у которого нет друзей, мне он нравится!

предисловие

Недавно предложенные новые потребности пользователей, учителя могут просматривать студенческие работы, изображения должны быть повернуты, масштабированы, обрезанные, граффити, мечь, добавить текст и так далее. На первый взгляд, но также потерял много волос. Там нет более мощных функций реализации плагинов, поэтому у меня больше времени остановить два одиннадцать женских голосовать рук? Ответ конечно это да.

Показать результаты

граффити

涂鸦2.jpg

обрезать

裁剪.jpg

вызывать

标注2.jpg

вращать

旋转2.jpg

фильтр

1636088844(1).jpg

Это очень мощно! Есть также много функций, которые я покажу. Так жду чего, используй его со мной ~

Установить

npm i tui-image-editor
// or
yarn add tui-image-editor

использовать

Быстрый опыт

Скопируйте следующий код, чтобы импортировать плагин в свой проект.

<template>
  <div class="drawing-container">
    <div id="tui-image-editor"></div>
  </div>
</template>
<script>
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
import ImageEditor from "tui-image-editor";
export default {
  data() {
    return {
      instance: null,
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      this.instance = new ImageEditor(
        document.querySelector("#tui-image-editor"),
        {
          includeUI: {
            loadImage: {
              path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image",
              name: "image",
            },
            initMenu: "draw", // 默认打开的菜单项
            menuBarPosition: "bottom", // 菜单所在的位置
          },
          cssMaxWidth: 1000, // canvas 最大宽度
          cssMaxHeight: 600, // canvas 最大高度
        }
      );
      document.getElementsByClassName("tui-image-editor-main")[0].style.top = "45px"; // 图片距顶部工具栏的距离
    },
  },
};
</script>

<style lang="scss" scoped>
.drawing-container {
  height: 900px;
}
</style>

Вы можете видеть, что появляются инструменты для редактирования изображений в реальном времени, не правда ли, это очень просто:

初始效果.jpg

глобализация

Поскольку он был разработан иностранцем, текстовые описания по умолчанию все на английском языке, поэтому давайте сначала переведем их на китайский язык:

const locale_zh = {
  ZoomIn: "放大",
  ZoomOut: "缩小",
  Hand: "手掌",
  History: '历史',
  Resize: '调整宽高',
  Crop: "裁剪",
  DeleteAll: "全部删除",
  Delete: "删除",
  Undo: "撤销",
  Redo: "反撤销",
  Reset: "重置",
  Flip: "镜像",
  Rotate: "旋转",
  Draw: "画",
  Shape: "形状标注",
  Icon: "图标标注",
  Text: "文字标注",
  Mask: "遮罩",
  Filter: "滤镜",
  Bold: "加粗",
  Italic: "斜体",
  Underline: "下划线",
  Left: "左对齐",
  Center: "居中",
  Right: "右对齐",
  Color: "颜色",
  "Text size": "字体大小",
  Custom: "自定义",
  Square: "正方形",
  Apply: "应用",
  Cancel: "取消",
  "Flip X": "X 轴",
  "Flip Y": "Y 轴",
  Range: "区间",
  Stroke: "描边",
  Fill: "填充",
  Circle: "圆",
  Triangle: "三角",
  Rectangle: "矩形",
  Free: "曲线",
  Straight: "直线",
  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: "混合色",
  Width: "宽度",
  Height: "高度",
  "Lock Aspect Ratio": "锁定宽高比例",
};

this.instance = new ImageEditor(
  document.querySelector("#tui-image-editor"),
  {
    includeUI: {
      loadImage: {
        path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image",
        name: "image",
      },
      initMenu: "draw", // 默认打开的菜单项
      menuBarPosition: "bottom", // 菜单所在的位置
      locale: locale_zh, // 本地化语言为中文
    },
    cssMaxWidth: 1000, // canvas 最大宽度
    cssMaxHeight: 600, // canvas 最大高度
  }
);

Эффект следующий:

汉化.jpg

нестандартный стиль

Стиль по умолчанию темный, если вы хотите изменить его на белый фон или хотите изменить размер, цвет и другие стили кнопок, вы можете использовать собственный стиль.

const customTheme = {
  "common.bi.image": "", // 左上角logo图片
  "common.bisize.width": "0px",
  "common.bisize.height": "0px",
  "common.backgroundImage": "none",
  "common.backgroundColor": "#f3f4f6",
  "common.border": "1px solid #333",

  // header
  "header.backgroundImage": "none",
  "header.backgroundColor": "#f3f4f6",
  "header.border": "0px",
  
  // 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", // 隐藏

  // icons default
  "menu.normalIcon.color": "#8a8a8a",
  "menu.activeIcon.color": "#555555",
  "menu.disabledIcon.color": "#ccc",
  "menu.hoverIcon.color": "#e9e9e9",
  "submenu.normalIcon.color": "#8a8a8a",
  "submenu.activeIcon.color": "#e9e9e9",

  "menu.iconSize.width": "24px",
  "menu.iconSize.height": "24px",
  "submenu.iconSize.width": "32px",
  "submenu.iconSize.height": "32px",

  // submenu primary color
  "submenu.backgroundColor": "#1e1e1e",
  "submenu.partition.color": "#858585",

  // submenu labels
  "submenu.normalLabel.color": "#858585",
  "submenu.normalLabel.fontWeight": "lighter",
  "submenu.activeLabel.color": "#fff",
  "submenu.activeLabel.fontWeight": "lighter",

  // checkbox style
  "checkbox.border": "1px solid #ccc",
  "checkbox.backgroundColor": "#fff",

  // 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",
};

this.instance = new ImageEditor(
  document.querySelector("#tui-image-editor"),
  {
    includeUI: {
      loadImage: {
        path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image",
        name: "image",
      },
      initMenu: "draw", // 默认打开的菜单项
      menuBarPosition: "bottom", // 菜单所在的位置
      locale: locale_zh, // 本地化语言为中文
      theme: customTheme, // 自定义样式
    },
    cssMaxWidth: 1000, // canvas 最大宽度
    cssMaxHeight: 600, // canvas 最大高度
  }
);

Эффект следующий:

自定义样式.jpg

Оптимизация кнопок

Через пользовательский стиль мы видим, что кнопки «Загрузить» и «Скачать» в правом верхнем углу были скрыты, далее мы скроем другие кнопки, которые не нужны (согласно бизнес-потребностям), и добавим кнопку для сохранения изображения.

<template>
  <div class="drawing-container">
    <div id="tui-image-editor"></div>
    <el-button class="save" type="primary" size="small" @click="save">保存</el-button>
  </div>
</template>

// ...
methods: {
  init() {
    this.instance = new ImageEditor(
      document.querySelector("#tui-image-editor"),
      {
        includeUI: {
          loadImage: {
            path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image",
            name: "image",
          },
          menu: ["resize", "crop", "rotate", "draw", "shape", "icon", "text", "filter"], // 底部菜单按钮列表 隐藏镜像flip和遮罩mask
          initMenu: "draw", // 默认打开的菜单项
          menuBarPosition: "bottom", // 菜单所在的位置
          locale: locale_zh, // 本地化语言为中文
          theme: customTheme, // 自定义样式
        },
        cssMaxWidth: 1000, // canvas 最大宽度
        cssMaxHeight: 600, // canvas 最大高度
      }
    );
    document.getElementsByClassName("tui-image-editor-main")[0].style.top ="45px"; // 调整图片显示位置
    document.getElementsByClassName("tie-btn-reset tui-image-editor-item help") [0].style.display = "none";  // 隐藏顶部重置按钮
  },
  // 保存图片,并上传
  save() {
    const base64String = this.instance.toDataURL(); // base64 文件
    const data = window.atob(base64String.split(",")[1]);
    const ia = new Uint8Array(data.length);
    for (let i = 0; i < data.length; i++) {
      ia[i] = data.charCodeAt(i);
    }
    const blob = new Blob([ia], { type: "image/png" }); // blob 文件
    const form = new FormData();
    form.append("image", blob);
    // upload file
  },
}

<style lang="scss" scoped>
.drawing-container {
  height: 900px;
  position: relative;
  .save {
    position: absolute;
    right: 50px;
    top: 15px;
  }
}
</style>

Эффект следующий:

按钮优化.jpg

Вы можете увидеть кнопку сброса вверху, а кнопки зеркала и маски внизу исчезли. В правом верхнем углу есть собственная кнопка сохранения.Нажмите кнопку, чтобы получить файл base64 и файл blob.

полный код

<template>
  <div class="drawing-container">
    <div id="tui-image-editor"></div>
    <el-button class="save" type="primary" size="small" @click="save">保存</el-button>
  </div>
</template>
<script>
import 'tui-image-editor/dist/tui-image-editor.css'
import 'tui-color-picker/dist/tui-color-picker.css'
import ImageEditor from 'tui-image-editor'
const locale_zh = {
  ZoomIn: '放大',
  ZoomOut: '缩小',
  Hand: '手掌',
  History: '历史',
  Resize: '调整宽高',
  Crop: '裁剪',
  DeleteAll: '全部删除',
  Delete: '删除',
  Undo: '撤销',
  Redo: '反撤销',
  Reset: '重置',
  Flip: '镜像',
  Rotate: '旋转',
  Draw: '画',
  Shape: '形状标注',
  Icon: '图标标注',
  Text: '文字标注',
  Mask: '遮罩',
  Filter: '滤镜',
  Bold: '加粗',
  Italic: '斜体',
  Underline: '下划线',
  Left: '左对齐',
  Center: '居中',
  Right: '右对齐',
  Color: '颜色',
  'Text size': '字体大小',
  Custom: '自定义',
  Square: '正方形',
  Apply: '应用',
  Cancel: '取消',
  'Flip X': 'X 轴',
  'Flip Y': 'Y 轴',
  Range: '区间',
  Stroke: '描边',
  Fill: '填充',
  Circle: '圆',
  Triangle: '三角',
  Rectangle: '矩形',
  Free: '曲线',
  Straight: '直线',
  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: '混合色',
  Width: '宽度',
  Height: '高度',
  'Lock Aspect Ratio': '锁定宽高比例'
}

const customTheme = {
  "common.bi.image": "", // 左上角logo图片
  "common.bisize.width": "0px",
  "common.bisize.height": "0px",
  "common.backgroundImage": "none",
  "common.backgroundColor": "#f3f4f6",
  "common.border": "1px solid #333",

  // header
  "header.backgroundImage": "none",
  "header.backgroundColor": "#f3f4f6",
  "header.border": "0px",
  
  // 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", // 隐藏

  // icons default
  "menu.normalIcon.color": "#8a8a8a",
  "menu.activeIcon.color": "#555555",
  "menu.disabledIcon.color": "#ccc",
  "menu.hoverIcon.color": "#e9e9e9",
  "submenu.normalIcon.color": "#8a8a8a",
  "submenu.activeIcon.color": "#e9e9e9",

  "menu.iconSize.width": "24px",
  "menu.iconSize.height": "24px",
  "submenu.iconSize.width": "32px",
  "submenu.iconSize.height": "32px",

  // submenu primary color
  "submenu.backgroundColor": "#1e1e1e",
  "submenu.partition.color": "#858585",

  // submenu labels
  "submenu.normalLabel.color": "#858585",
  "submenu.normalLabel.fontWeight": "lighter",
  "submenu.activeLabel.color": "#fff",
  "submenu.activeLabel.fontWeight": "lighter",

  // checkbox style
  "checkbox.border": "1px solid #ccc",
  "checkbox.backgroundColor": "#fff",

  // 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",
};
export default {
  data() {
    return {
      instance: null
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      this.instance = new ImageEditor(document.querySelector('#tui-image-editor'), {
        includeUI: {
          loadImage: {
            path: 'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image',
            name: 'image'
          },
          menu: ['resize', 'crop', 'rotate', 'draw', 'shape', 'icon', 'text', 'filter'], // 底部菜单按钮列表 隐藏镜像flip和遮罩mask
          initMenu: 'draw', // 默认打开的菜单项
          menuBarPosition: 'bottom', // 菜单所在的位置
          locale: locale_zh, // 本地化语言为中文
          theme: customTheme // 自定义样式
        },
        cssMaxWidth: 1000, // canvas 最大宽度
        cssMaxHeight: 600 // canvas 最大高度
      })
      document.getElementsByClassName('tui-image-editor-main')[0].style.top = '45px' // 调整图片显示位置
      document.getElementsByClassName(
        'tie-btn-reset tui-image-editor-item help'
      )[0].style.display = 'none' // 隐藏顶部重置按钮
    },
    // 保存图片,并上传
    save() {
      const base64String = this.instance.toDataURL() // base64 文件
      const data = window.atob(base64String.split(',')[1])
      const ia = new Uint8Array(data.length)
      for (let i = 0; i < data.length; i++) {
        ia[i] = data.charCodeAt(i)
      }
      const blob = new Blob([ia], { type: 'image/png' }) // blob 文件
      const form = new FormData()
      form.append('image', blob)
      // upload file
    }
  }
}
</script>

<style lang="scss" scoped>
.drawing-container {
  height: 900px;
  position: relative;
  .save {
    position: absolute;
    right: 50px;
    top: 15px;
  }
}
</style>

Суммировать

Выше приведено основное использование tui.image-editor По сравнению с другими плагинами tui.image-editor имеет преимущество в том, что он мощный и простой в использовании.

Плагин прост в использовании, но я также нашел небольшой баг, когда вы увеличиваете изображение, перетаскиваете положение отображения ладонью, а затем нажимаете кнопку сброса, изображение, скорее всего, исчезает. Есть два решения: одно — изменить исходный код, перед сбросом вызвать метод resetZoom для восстановления масштаба, второе — сделать кнопку сброса самостоятельно, а затем вызвать метод this.init для повторного рендеринга после Щелчок.

Подарки из роз, вручите аромат. Если вы найдете это полезным, пожалуйста, переместите маленькую ручку, чтобы заработать состояние, и поставьте лайк~😜

Дополнительные API и демонстрации см. по адресу:

адрес гитхаба:Github.com/ Вы можете включить / отключить .ima ...

Адрес API и примеров:Вы все еще можете .GitHub.IO/retire.image-oh…

другие плагины

Каждая лично проверена мной, тщательно отобрана, одна из ста. Пусть у вас будет больше времени на прикосновения🐟

Vue реализует контекстное меню за 1 минуту, Евангелие для ленивых

Как Vue быстро реализует кадрирование аватара? Метод проще, чем вы думаете

Как вставлять смайлики, текстовые документы и математические формулы в форматированный текст?

Перетащите за 1 минуту, чтобы вы могли грести более свободно