vue3网页端屏幕截图并可以裁剪,反转,添加批注等
<template>
<!-- 屏幕截图弹出窗 -->
<el-dialog
v-model="dialogShow"
custom-class="customSnapshotDialog"
title="调整截图"
width="1000px"
top="49px"
:close-on-click-modal="false"
:destroy-on-close="true"
@close="handleClose"
>
<div class="boardBox">
<div id="tui-image-editor" />
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="handleCanvas2Img">确认上传</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { reactive, toRefs, watch, nextTick } from 'vue'
import 'tui-image-editor/dist/'
import 'tui-color-picker/dist/'
export default {
name: 'DialogPageSnapshot',
components: { },
props: {
dialogVisiable: {
type: Boolean,
default: false
},
imgUrl: {
type: String,
default: ''
}
},
emits: ['closeDialog'],
setup(props, context) {
// const { proxy } = getCurrentInstance()
const state = reactive({
dialogShow: false,
imgBaseUrl: '',
// 创建的画布对象
instance: null,
ImageEditor: require('tui-image-editor'),
localeCN: {
Crop: '裁剪',
Draw: '涂鸦',
Text: '添加文本',
Undo: '上一步',
Redo: '下一步',
Reset: '重置',
Apply: '确定',
Cancel: '取消',
Custom: '自定义',
Square: '正方形',
Free: '曲线',
Straight: '直线',
Color: '颜色',
Range: '粗细/角度',
Bold: '加粗',
Italic: '斜体',
Underline: '下划线',
Left: '左对齐',
Center: '居中',
Right: '右对齐',
'Flip X': 'X 轴',
'Flip Y': 'Y 轴',
Flip: '镜像',
Rotate: '旋转',
ZoomIn: '放大',
ZoomOut: '缩小',
Hand: '拖动',
'Text size': '字体大小'
},
customTheme: {
// image 坐上角度图片
'': '', // 在这里换上你喜欢的logo图片
'': '0px',
'': '0px',
'': 'none',
'': '#f3f4f6',
'': 'none',
// header
'': 'none',
'': 'transparent',
'': '0px',
// load button
'': '#fff',
'': '1px solid #ddd',
'': '#222',
'': 'NotoSans, sans-serif',
'': '12px',
'': 'none', // 可以直接隐藏掉
// download button
'': '#fdba3b',
'': '1px solid #fdba3b',
'': '#fff',
'': 'NotoSans, sans-serif',
'': '12px',
'': 'none', // 可以直接隐藏掉
// icons default
'': '#8a8a8a',
'': '#555555',
'': '#434343',
'': '#e9e9e9',
'': '#8a8a8a',
'': '#e9e9e9',
'': '18px',
'': '18px',
'': '20px',
'': '20px',
// '': '#ddd',
// submenu primary color
// '': 'currentcolor',
'': '#858585',
// submenu labels
'': '#858585',
'': 'lighter',
'': '#fff',
'': 'lighter',
// checkbox style
'': '1px solid #ccc',
'': '#fff',
// rango style
'': '#fff',
'': '#666',
'': '#d1d1d1',
'': '#414141',
'': '#282828',
'': '#414141',
'': '#fff',
'': 'lighter',
'': '11px',
'': '1px solid #353535',
'': '#151515',
'': '#fff',
'': 'lighter',
// colorpicker style
// '': '1px solid #1e1e1e',
'': '#fff'
}
})
watch(props, (newValue) => {
state.dialogShow = newValue.dialogVisiable
if (state.dialogShow) {
state.refPage = newValue.refPage
state.imgBaseUrl = newValue.imgUrl
if (state.imgBaseUrl) {
nextTick(() => {
// 获取到当前屏幕的宽高,用于判断当前是大屏幕还是小屏幕==》进而确定的那个要渲染哪个init(画布大小不一样)
// 如果不压缩图片大小,太大的图片出现拖动,手机端无法操作,所以要根据不同屏幕大小渲染不同大小的画布
if (document.documentElement.clientWidth <= 500) {
initMini()
} else {
// 页面加载好,就调用这个方法来创建图片编辑器
init()
}
})
}
}
})
const init = () => {
// 创建tui-image-editor组件实例,后续操作需要用到这个对象
state.instance = new state.ImageEditor(document.querySelector('#tui-image-editor'), {
includeUI: {
// 默认加载的图片
loadImage: {
// 图片路径
path: state.imgBaseUrl,
// 图片的名字,可以省略
name: 'image'
},
// 默认开启绘图的功能,小屏幕情况下,直接打开菜单,会占用较大屏幕空间,不美观
initMenu: 'draw',
// 支持的菜单
menu: [
'crop', // 裁切
'draw', // 添加绘画
'text', // 添加文本
'rotate', // 旋转
'flip' // 翻转
// 'shape', // 添加形状
// 'icon', // 添加图标
// 'mask', // 添加覆盖
// 'filter' // 添加滤镜
],
// 菜单位置在下面
menuBarPosition: 'bottom',
// 汉化
locale: state.localeCN,
// 自定义样式(隐藏默认顶部栏目、按钮颜色。。。)
theme: state.customTheme
},
// 设置画布的最大宽高,能自动等比例缩放大图片到指定的宽高内
// TODO:可以监听当前页面的缩放,动态修改画布最大宽高以防止图片过大
cssMaxWidth: 850
// cssMaxHeight: 580
}
)
// 清除自定义样式造成的一条边框线
document.getElementsByClassName('tui-image-editor-main')[0].style.top = 0
// 你也可以指定那个菜单隐藏,留几个有用的菜单
// ('[tooltip-content="Undo"]'). = 'none'// 上一步
// ('[tooltip-content="Redo"]'). = 'none' // 下一步
// ('[tooltip-content="Reset"]'). = 'none' // 完全重新编辑
// ('[tooltip-content="ZoomIn"]'). = 'none' // 放大
// ('[tooltip-content="ZoomOut"]'). = 'none' // 缩小
// ('[tooltip-content="Hand"]'). = 'none' // 拖动界面
document.querySelector('[tooltip-content="History"]').style.display = 'none'
document.querySelector('[tooltip-content="Delete"]').style.display = 'none' // 删除选中编辑内容
document.querySelector('[tooltip-content="DeleteAll"]').style.display = 'none' // 清空
// 隐藏分割线
document.querySelectorAll('.tui-image-editor-icpartition').forEach(item => {
item.style.display = 'none'
})
}
// 创建图片编辑器 ==>小屏幕
const initMini = () => {
// 创建tui-image-editor组件实例,后续操作需要用到这个对象
state.instance = new state.ImageEditor(
document.querySelector('#tui-image-editor'),
{
includeUI: {
// 默认加载的图片
loadImage: {
// 图片路径
path: state.imgBaseUrl,
// 图片的名字,可以省略
name: 'image'
},
// 默认开启绘图的功能,小屏幕情况下,直接打开菜单,会占用较大屏幕空间,不美观
initMenu: 'draw',
// 支持的菜单
menu: [
'crop', // 裁切
'draw', // 添加绘画
'text' // 添加文本
],
// 菜单位置在下面
menuBarPosition: 'bottom',
// 汉化
locale: state.localeCN,
// 自定义样式(隐藏默认顶部栏目、按钮颜色。。。)
theme: state.customTheme
},
// 设置画布的最大宽高,能自动等比例缩放大图片到指定的宽高内
// !设置小图宽高,自动压缩图片,防止过大出现滚动,导致无法操作
cssMaxWidth: 350,
cssMaxHeight: 500
}
)
// 清除自定义样式造成的一条边框线
document.getElementsByClassName('tui-image-editor-main')[0].style.top = 0
// 设置图片编辑其余距离底部90px(就不会被底部展开的工具栏遮挡住了)===>无效
// ('tui-image-editor-wrap')[0]. = 90
//! 修改图片编辑器的顶部导航栏
// ('[tooltip-content="Undo"]'). = 'none'// 上一步
document.querySelector('[tooltip-content="History"]').style.display = 'none'
document.querySelector('[tooltip-content="Delete"]').style.display = 'none' // 删除选中编辑内容
document.querySelector('[tooltip-content="DeleteAll"]').style.display = 'none' // 清空
// 隐藏分割线
document.querySelectorAll('.tui-image-editor-icpartition').forEach(item => {
item.style.display = 'none'
})
}
/** 保存编辑后图片 */
const handleCanvas2Img = () => {
// 要延时调用,否则会被锁死,因为异步方法会在没有这个dom时触发它
setTimeout(() => {
// () 编辑后的base64图片码
// 传给上传组件(父组件)
context.emit('closeDialog', state.instance.toDataURL())
}, 700)
}
// 将base64转换成file类型,用于给tui-image-editor组件的官方方法调用,计算获得当前图片的宽高
// ? 这个官方的方法会返回图片的宽高,但是传入的必须时file类型的文件
const dataURLtoFile = (dataurl) => {
var arr = dataurl.split(',')
var mime = arr[0].match(/:(.*?);/)[1]
var bstr = atob(arr[1])
var n = bstr.length
var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], { type: mime })
}
const handleClose = () => {
state.dialogShow = false
context.emit('closeDialog', false)
}
return { ...toRefs(state), handleClose, handleCanvas2Img, dataURLtoFile, initMini, init }
}
}
</script>
<style lang="scss" scoped>
.boardBox {
width: 100%;
height: 79.5vh;
background: #f9f9f9;
}
// 弹窗的关闭按钮
.closeBigBtn {
position: absolute;
left: 150px;
top: 12px;
}
</style>
<style lang="scss">
.tui-image-editor-container .tui-image-editor-controls {
height: 40px;
background-color: #ddd;
}
.tui-image-editor-container .tui-image-editor-wrap {
padding: 6px 0;
position: initial;
flex: 1;
}
.tui-image-editor-container .tui-image-editor-main {
display: flex;
flex-direction: column-reverse;
}
.tui-image-editor-container .tui-image-editor-main-container {
height: calc(100% - 40px);
}
.tui-image-editor-container .color-picker-value {
width: 22px;
height: 22px;
}
.tui-image-editor {
top: 0 !important;
}
.tui-image-editor-submenu {
border-radius: 10px 10px 0 0 !important;
}
.tui-image-editor-container .tui-image-editor-partition > div {
height: 40px;
}
.tui-image-editor-submenu-item {
padding: 8px 0 8px 0 !important;
}
.tui-image-editor-container {
background-color: transparent;
}
.tui-image-editor-container li {
line-height: initial;
}
.tui-image-editor-container .svg_ic-submenu {
display: inline-block;
}
/* 强制压缩菜单的高度 ,减少占用屏幕的空间*/
.tui-image-editor-container .tui-image-editor-submenu {
height: auto !important;
position: sticky !important;
}
.tui-image-editor-container.bottom .tui-image-editor-submenu>div {
padding: 0 !important;
}
/* 顶部工具栏定位 */
.tui-image-editor-container .tui-image-editor-header {
top: -55px;
}
.tui-image-editor-container .tui-image-editor-help-menu {
border-radius: 10px 10px 0 0;
}
.tui-image-editor-container .tui-image-editor-help-menu.top {
top: -32px;
background-color: #f0f2f5;
height: auto;
}
/* 顶部工具栏定位 */
.tui-image-editor-container {
overflow: visible;
}</style>