vue3中使用 tui-image-editor进行图片处理,并上传

效果图

在这里插入图片描述

下载包

pnpm i tui-image-editor
pnpm i tui-color-picker

调用组件

//html部分
<el-dialog v-model="imgshow" destroy-on-close width="40%" draggable align-center :show-close="true"
				:close-on-click-modal="false">
				<template #header>
					<div style="display: flex; justify-content: space-between">
						<div style="display: flex">
							<h3>图片</h3>
						</div>
					</div>
				</template>
				<div class="newBox">
					<!-- 图片处理框 -->
					<SignImage v-if="cropperObj.cVisible" :dialogVisible="cropperObj.cVisible" :title="cropperObj.ctitle"
						:imgUrl="cropperObj.previewsImgUrl" @getNewImg="cropperObj.getNewImg"
						@closeCropperDialog="cropperObj.closeCropperView"></SignImage>

				</div>
			</el-dialog>

//js部分
import {
    SignImage } from './index';//调用组件
let imgshow = ref<boolean>(false);
const cropperObj = reactive({
   
	cVisible: true, // 显示切图弹框
	ctitle: "", // 弹框标题
	previewsImgUrl: "https://img0.baidu.com/it/u=2759734465,3558448225&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1708621200&t=acc59373dca9b8658e33e14a974f6c47", //图片地址
	// 开启剪切弹框
	openCropperView: () => {
   
		cropperObj.ctitle = "图片处理"
		cropperObj.cVisible = true
	},
	// 关闭弹框所触发的事件
	closeCropperView: (data) => {
   
		cropperObj.cVisible = false
	},
	// 获取处理完的图片数据
	getNewImg: (val: any) => {
   
		console.log("val", val);
		pictureAnnotationFun(val)
	}
})
//图片上传函数,并加其他参数
async function pictureAnnotationFun(file: any) {
   
	const formData = new FormData()
	formData.append("file", file);
	formData.append('id', xx);
	formData.append('bid', xxx);
	try {
   
		const {
    code, msg, data } = await uploadimg(formData);
		if (code > 0) {
   
			cropperObj.cVisible = false;
			ElMessage({
   
				showClose: true,
				message: '上传成功',
				type: 'success',
			});
		} else {
   
			ElMessage({
   
				showClose: true,
				message: '上传失败' + msg,
				type: 'error',
				duration: 0,
			});
		}
	} catch (e) {
   

		ElMessage({
   
			showClose: true,
			message: '错误: ' + e.message,
			type: 'error',
			duration: 0,
		});
	}
}


封装组件代码

<template>
	<div class="drawing-container">
		<!-- 绘图组件容器DOM -->
		<div id="tui-image-editor"></div>
		<el-button class="save" type="primary" @click="save">保存</el-button>
	</div>
</template>
<script setup lang="ts">
import 'tui-image-editor/dist/tui-image-editor.css';
import 'tui-color-picker/dist/tui-color-picker.css';
import ImageEditor from 'tui-image-editor';
import {
    nextTick, onMounted, ref } from 'vue';

// 中文菜单
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',
};

// props
const props = defineProps({
   
	dialogVisible: {
   
		type: Boolean,
		default: () => {
   
			return false;
		},
	},
	title: {
   
		type: String,
		default: '',
	},
	imgUrl: {
   
		type: String,
		default: '',
	},
});
const emit = defineEmits(['closeCropperDialog', 'getNewImg']);
const instance = ref<any>(null);

onMounted(() => {
   

	nextTick(() => {
   
		init(); // 页面创建完成后调用
	});
});

// 关闭弹框
const closeDialog = () => {
   
	emit('closeCropperDialog');
	// options.img = ''
};

const init = () => {
   
	instance.value = new ImageEditor(document.querySelector('#tui-image-editor'), {
   
		includeUI: {
   
			loadImage: {
   
				path: props.imgUrl,
				name: 'image',
			},
			menu: ['resize', 'crop', 'rotate', 'draw', 'shape', 'icon', 'text', 'filter'], // 底部菜单按钮列表 隐藏镜像flip和遮罩mask
			initMenu: 'draw', // 默认打开的菜单项
			menuBarPosition: 'bottom', // 菜单所在的位置
			locale: locale_zh, // 本地化语言为中文
			theme: customTheme, // 自定义样式
		},
		cssMaxWidth: 400, // canvas 最大宽度
		cssMaxHeight: 500, // 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'; // 隐藏顶部重置按钮
};

// 保存图片,并上传
const save = async () => {
   
	const base64String = instance.value.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 file = new File([ia], "打标.png", {
    type: "image/png" });
	emit('getNewImg', file);

};
</script>

<style lang="scss" scoped>
.drawing-container {
   
	width: 100%;
	height: 80vh;
	position: relative;

	.save {
   
		position: absolute;
		right: 50px;
		top: 15px;
	}
}
</style>

相关推荐

  1. vue3图片进行图片压缩(image-compressor.js)

    2024-02-22 18:20:04       26 阅读
  2. vue-quill-editor图片base64转化为img标签

    2024-02-22 18:20:04       61 阅读
  3. vue+element ui实现图片拖拽进行图片排序

    2024-02-22 18:20:04       67 阅读
  4. vue2图片image-conversion压缩

    2024-02-22 18:20:04       51 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-22 18:20:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-22 18:20:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-22 18:20:04       82 阅读
  4. Python语言-面向对象

    2024-02-22 18:20:04       91 阅读

热门阅读

  1. vue+element下日期组件momentjs转换赋值问题

    2024-02-22 18:20:04       44 阅读
  2. 内存泄漏与内存溢出

    2024-02-22 18:20:04       46 阅读
  3. centos安装扩展

    2024-02-22 18:20:04       38 阅读
  4. 2023年10月CCAA认证通用基础真题

    2024-02-22 18:20:04       100 阅读
  5. python中websockets与主线程传递参数

    2024-02-22 18:20:04       45 阅读
  6. flask请求时间记录和日志处理

    2024-02-22 18:20:04       47 阅读
  7. 字节飞书面试算法题

    2024-02-22 18:20:04       42 阅读