图片编辑器tui-image-editor

提示:图片编辑器tui-image-editor

文章目录


前言

需求:图片编辑器tui-image-editor

一、安装tui-image-editor

c 复制代码
npm install tui-image-editor --save

二、新建components/ImageEditor.vue

ImageEditor.vue

c 复制代码
<template>
    <div class="image_editor_box" ref="dcRef">
      <div id="tui_image_editor"></div>
      <el-button class="image_save_btn" type="primary" size="small" @click="saveImage">保存</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 = {
    //菜单
    ZoomIn: '放大',
    ZoomOut: '缩小',
    Hand: '抓手工具',
    History: '历史',
    Undo: '撤销',
    Redo: '恢复',
    Reset: '重置',
    Delete: '删除',
    DeleteAll: '全部删除',
    //工具栏
    //尺寸调整
    Resize: '尺寸',
    Width: '宽度',
    Height: '高度',
    'Lock Aspect Ratio': '锁定宽高比例',
    Apply: '应用',
    Cancel: '取消',
    //镜像
    Flip: '镜像',
    'Flip X': 'X 轴',
    'Flip Y': 'Y 轴',
    //蒙版
    Mask: '蒙版',
    'Load Mask Image': '上传蒙版图片',
    //裁剪
    Crop: '裁剪',
    Square: '正方形',
    // 旋转
    Rotate: '旋转',
    Range: '区间',
    //画笔
    Draw: '画笔',
    Free: '曲线',
    Straight: '直线',
    Color: '颜色',
    //图形
    Shape: '图形',
    Rectangle: '矩形',
    Circle: '圆形',
    Triangle: '三角形',
    Fill: '填充',
    Stroke: '描边',
    //图标
    Icon: '图标',
    Arrow: '箭头',
    'Arrow-2': '箭头2',
    'Arrow-3': '箭头3',
    'Star-1': '五角星',
    'Star-2': '多角形',
    Polygon: '多边形',
    Location: '定位',
    Heart: '心形',
    Bubble: '气泡',
    'Custom icon': '自定义图标',
    //文字
    Text: '文字',
    Bold: '加粗',
    Italic: '斜体',
    Underline: '下划线',
    Left: '左对齐',
    Center: '居中',
    Right: '右对齐',
    'Text size': '字体大小',
    //滤镜
    Filter: '滤镜',
    Grayscale: '灰度',
    Sepia: '棕色',
    Blur: '模糊',
    Emboss: '浮雕',
    Invert: '底片',
    Sepia2: '棕色2',
    Sharpen: '锐化',
    'Remove White': '除去白色',
    Distance: '距离',
    Brightness: '亮度',
    Noise: '铜板雕刻',
    Pixelate: '马赛克',
    'Color Filter': '彩色滤镜',
    Threshold: '阈值',
    Tint: '色调',
    Multiply: '正片叠底',
    Blend: '混合色',
    Custom: '自定义',
    load: '上传',
    download:'下载',
  }  
  const IThemeConfig = {
  //图标
  'common.bi.image': 'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF',
  'common.bisize.width': '30px',
  'common.bisize.height': '30px',
  //编辑器背景
  // 'common.backgroundImage': 'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF',
  'common.backgroundColor': '#fff',
  'common.border': '1px solid #eee',

  // 菜单栏样式
  // 'header.backgroundImage': 'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF',
  'header.backgroundColor': 'transparent',
  'header.border': '0 solid #000',

  // 上传按钮
  'loadButton.backgroundColor': '#ecf5ff',
  'loadButton.border': '1px solid #409EFF',
  'loadButton.color': '#409EFF',
  'loadButton.fontFamily': "'Noto Sans', sans-serif",
  'loadButton.fontSize': '12px',

  // 下载按钮
  'downloadButton.backgroundColor': '#409EFF',
  'downloadButton.border': '1px solid #409EFF',
  'downloadButton.color': '#fff',
  'downloadButton.fontFamily': "'Noto Sans', sans-serif",
  'downloadButton.fontSize': '12px',

  // 工具栏icon
  'menu.normalIcon.color': '#7A8799',
  'menu.activeIcon.color': '#409EFF',
  'menu.disabledIcon.color': '#A2AEBF',
  'menu.hoverIcon.color': '#323D4D',
  'menu.iconSize.width': '24px',
  'menu.iconSize.height': '24px',

  // 工具栏子菜单
  'submenu.normalIcon.color': '#7A8799',
  'submenu.activeIcon.color': '#323D4D',
  // 工具栏子菜单icon
  'submenu.iconSize.width': '24px',
  'submenu.iconSize.height': '24px',
  // 工具栏子菜单bg
  'submenu.backgroundColor': '#eee',
  // 工具栏子菜单分割线
  'submenu.partition.color': '#7A8799',
  //工具栏子菜单文字
  'submenu.normalLabel.color': '#7A8799',
  'submenu.normalLabel.fontWeight': '400',
  'submenu.activeLabel.color': '#323D4D',
  'submenu.activeLabel.fontWeight': '400',

  // 工具栏子菜单多选框
  'checkbox.border': '1px solid #7A8799',
  'checkbox.backgroundColor': '#fff',

  // 工具栏子菜单进度条--滑块
  'range.pointer.color': '#409EFF',
  // 工具栏子菜单进度条--底色
  'range.bar.color': '#A2AEBF',
  // 工具栏子菜单进度条--进度
  'range.subbar.color': '#409EFF',
  // 工具栏子菜单进度条--禁用
  'range.disabledPointer.color': '#A2AEBF',
  'range.disabledBar.color': '#A2AEBF',
  'range.disabledSubbar.color': '#7A8799',
  // 工具栏子菜单进度条--值
  'range.color': '#7A8799',
  'range.value.color': '#323D4D',
  'range.value.fontWeight': '400',
  'range.value.fontSize': '11px',
  'range.value.border': '1px solid #A2AEBF',
  'range.value.backgroundColor': '#fff',
  'range.title.fontWeight': '400',

  // 颜色选择器
  'colorpicker.button.border': '1px solid #A2AEBF',
  'colorpicker.title.color': '#7A8799',
};
  export default {
    props:{
        defaultImg:{
            type:Object,
            default:()=>{return {}},
        },
        defaultColorArr:{
            type:Array,
            default:()=>{return []},
        }
    },
    data() {
      return {
        imgEditor: null
      }
    },
    watch:{
        defaultImg(){
            this.imgEditor&&this.imgEditor.loadImageFromURL(this.defaultImg.path,this.defaultImg.name);
        }
    },
    mounted() {
        this.init(this.defaultImg);
    },
    methods: {
      //初始化ImageEditor
      init(defaultImg) {
        this.imgEditor = new ImageEditor(document.getElementById('tui_image_editor'), {
          includeUI: {
            //加载图片
            loadImage: { path:defaultImg.path, name: defaultImg.name },
            //尺寸  裁剪  旋转  画笔  图形  图标  文字  镜像  滤镜  蒙版
            menu: ['resize', 'crop', 'rotate', 'draw', 'shape', 'icon', 'text', 'flip', 'filter', 'mask'], //不初始化 filter mask
            // 默认工具
            initMenu: '',
            // 工具栏位置              
            menuBarPosition: 'bottom', 
            // 语言
            locale: locale,
            // 主题            
            theme: IThemeConfig        
          },
          // 最大宽度
          cssMaxWidth: (this.$refs.dcRef.clientWidth||1000)-80,
           // 最大高度
          cssMaxHeight: (this.$refs.dcRef.clientHeight||600)-64-48-80,
          uiSize: {
            width: '1000px',
            height: '700px'
          },
          selectionStyle: {
            cornerSize: 20,
            rotatingPointOffset: 70
          },
          picker:{}
        });
        //Load按钮文案改成上传
        const load = document.querySelector('.tui-image-editor-header-buttons>div');
        load.innerHTML = load.innerHTML.replace('Load','上传');
        //Download按钮文案改成下载
        const download = document.querySelector('.tui-image-editor-header-buttons .tui-image-editor-download-btn');
        download.innerHTML = "下载";
      },
      // 保存批注的图片
      saveImage() {
        let base64Str = this.imgEditor.toDataURL();
        let blob = this.base64ToBlob(base64Str);
        console.log(base64Str,blob);
        this.$emit('saveEditImgSrc',base64Str);
      },
      //base64转换成blob
      base64ToBlob(base64Str) {
        let arr = base64Str.split(",");
        let type = arr[0].match(/:(.*?);/)[1];
        let bstr = atob(arr[1]);
        let n = bstr.length;
        let u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], { type });
      }
    }
  }
  </script>
  
  <style lang="scss" scoped>
  .image_editor_box {
    height: 100%;
    width: 100%;
    position: relative;
    .image_save_btn {
      position: absolute;
      width: 120px;
      height: 40px;
      right: 260px;
      top: 9px;
      background-color: #409EFF;
      border: 1px solid #409EFF;
      color: #fff;
      font-family: 'Noto Sans', sans-serif;
      font-size: 12px;
      border-radius: 40px;
    }
  }
  </style>
  <style>
    /** 隐藏图标和上传下载按钮 **/
    .image_editor_box .tui-image-editor-header-logo,.image_editor_box .tui-image-editor-header-buttons{
        /* display: none!important; */
    }
    /* 调整图片显示位置 */
    .image_editor_box .tui-image-editor-main{
        top:48px!important;
        height:auto!important;
    }
    .image_editor_box .tui-image-editor-container .tui-image-editor-range-wrap label{
      color: #7A8799;
    }
    .image_editor_box .tui-image-editor-container .tui-image-editor-checkbox label > span {
      color: #7A8799;
    }
    .image_editor_box .tui-image-editor-container .tui-image-editor-controls{
      background-color: #fcfcfc;
      border:1px solid #eee;
      border-top:0;
    }
    .image_editor_box .tui-image-editor-help-menu.top{
      border:1px solid #eee;
      background: #fcfcfc;
    }
  </style>
  

三、修改App.vue

App.vue

c 复制代码
<template>
  <div id="app">
    <div class="img_mark_box">
      <div class="img_mark_l">
        <div class="img_mark_img" v-for="item,index in imgArr" :key="index" @click="changeImg(item)"><img :src="item.path" alt=""></div>
      </div>
      <div class="img_mark_m"><ImageEditor :defaultImg="activeImg" @saveEditImgSrc="saveEditImgSrc"></ImageEditor></div>
      <div class="img_mark_r"><img :src="editImgSrc" alt=""></div>
  </div>
  </div>
</template>

<script>
import ImageEditor from "./components/ImageEditor";
export default {
  name: 'App',
  components:{ImageEditor},
  data(){
    return {
      activeImg:'',
      editImgSrc:'',
      imgArr:[
        {
          path:require('@/assets/test.jpg'),
          name:'图片1'
        },
        {
          path:`data:image/jpeg;base64,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`,
          name:'图片2'
        },
        {
          path:'https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF',
          name:'图片3'
        },
        {
          path:'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF',
          name:'图片4'
        },
        {
          path:'https://t7.baidu.com/it/u=825057118,3516313570&fm=193&f=GIF',
          name:'图片5'
        },
        {
          path:'https://t7.baidu.com/it/u=602106375,407124525&fm=193&f=GIF',
          name:'图片6'
        },
        {
          path:'https://t7.baidu.com/it/u=55748064,2074988836&fm=193&f=GIF',
          name:'图片7'
        },
      ],
    }
  },
  created(){
    this.activeImg = this.imgArr[0];
  },
  methods:{
    changeImg(item){
      this.activeImg = item;
    },
    saveEditImgSrc(src){
      this.editImgSrc = src;
    },
  }
};
</script>

<style scoped >
.img_mark_box {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  padding: 0 200px 0 300px;
  box-sizing: border-box;
}
.img_mark_l,.img_mark_r{
  position: absolute;
  top: 0;
  bottom: 0;
}
.img_mark_l{
  left: 0;
  width: 300px;
  box-sizing: border-box;
  padding: 20px 10px;
}
.img_mark_img{
    height: 80px;
    box-sizing: border-box;
    vertical-align: middle;
    margin-bottom: 10px;
    overflow: hidden;
    border: 1px solid #eee;
    border-radius: 8px;
    cursor: pointer;
}
.img_mark_img>img{
    width: 100%;
    height: 100%;
}
.img_mark_r{
  right: 0;
  width: 200px;
  box-sizing: border-box;
  padding: 20px 10px;
}
.img_mark_r>img{
  width: 100%;
}
.img_mark_m{
  width: 100%;
  height: 100%;
}
</style>

四、效果

五、遇到问题 this.getResolve is not a function

问题:

sass-loader 版本过高,导致tui-image-editor的css无法解析

解决方案:

c 复制代码
npm install sass-loader@7.3.1 --save-dev

报错内容:

c 复制代码
Module build failed: TypeError: this.getResolve is not a function
    at Object.loader (D:\node_modules\sass-loader\dist\index.js:52:26)

 @ ./node_modules/vue-style-loader!./node_modules/css-loader?{"sourceMap":true}!./node_modules/vue-loader/lib/style-compiler?{"vue":true,"id":"data-v-4913b0a8","scoped":true,"hasInlineConfig":false}!D:/node_modules/sass-loader/dist/cjs.js?{"sourceMap":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/ImageEditor.vue 4:14-385 13:3-17:5 14:22-393
 @ ./src/components/ImageEditor.vue
 @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue
 @ ./src/App.vue
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js

总结

踩坑路漫漫长@~@

相关推荐
yqcoder9 分钟前
Vue3 + Vite + Electron + TS 项目构建
前端·javascript·vue.js
ggdpzhk3 小时前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
活宝小娜7 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点7 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow7 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
刚刚好ā8 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
为什么每天的风都这么大9 小时前
Vscode/Code-server无网环境安装通义灵码
ide·vscode·阿里云·编辑器·ai编程·code-server
会发光的猪。10 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客11 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
周全全11 小时前
Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
java·vue.js·spring boot·安全·php