赞
踩
实现网页版的屏幕截图添加备注等功能,效果如下:
需要安装插件:tui-image-editor
这个弹出框具体代码:
<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/tui-image-editor.css' import 'tui-color-picker/dist/tui-color-picker.css' 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 坐上角度图片 'common.bi.image': '', // 在这里换上你喜欢的logo图片 'common.bisize.width': '0px', 'common.bisize.height': '0px', 'common.backgroundImage': 'none', 'common.backgroundColor': '#f3f4f6', 'common.border': 'none', // header 'header.backgroundImage': 'none', 'header.backgroundColor': 'transparent', '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': '#434343', 'menu.hoverIcon.color': '#e9e9e9', 'submenu.normalIcon.color': '#8a8a8a', 'submenu.activeIcon.color': '#e9e9e9', 'menu.iconSize.width': '18px', 'menu.iconSize.height': '18px', 'submenu.iconSize.width': '20px', 'submenu.iconSize.height': '20px', // 'submenu.backgroundColor': '#ddd', // submenu primary color // 'submenu.backgroundColor': 'currentcolor', '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' } }) 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组件实例,后续操作需要用到this.instance这个对象 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 // 你也可以指定那个菜单隐藏,留几个有用的菜单 // document.querySelector('[tooltip-content="Undo"]').style.display = 'none'// 上一步 // document.querySelector('[tooltip-content="Redo"]').style.display = 'none' // 下一步 // document.querySelector('[tooltip-content="Reset"]').style.display = 'none' // 完全重新编辑 // document.querySelector('[tooltip-content="ZoomIn"]').style.display = 'none' // 放大 // document.querySelector('[tooltip-content="ZoomOut"]').style.display = 'none' // 缩小 // document.querySelector('[tooltip-content="Hand"]').style.display = '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组件实例,后续操作需要用到this.instance这个对象 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(就不会被底部展开的工具栏遮挡住了)===>无效 // document.getElementsByClassName('tui-image-editor-wrap')[0].style.bottom = 90 //! 修改图片编辑器的顶部导航栏 // document.querySelector('[tooltip-content="Undo"]').style.display = '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(() => { // state.instance.toDataURL() 编辑后的base64图片码 // 传给上传组件(父组件) context.emit('closeDialog', state.instance.toDataURL()) }, 700) } // 将base64转换成file类型,用于给tui-image-editor组件的官方方法调用,计算获得当前图片的宽高 // ? this.instance.loadImageFromFile这个官方的方法会返回图片的宽高,但是传入的必须时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>
父组件
<!-- 调整截图弹出框 -->
<DialogPageSnapshot :dialog-visiable="dialogSnapshot" :img-url="imgBaseUrl" @closeDialog="handleCloseSnapshot" />
import html2canvas from 'html2canvas' // 屏幕快照 async function PageSnapshot(ele) { let url = '' await html2canvas(ele, { dpi: 300, scale: 2, // 处理图片模糊 background: '#fff', useCORS: true // 允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。 }).then((canvas) => { url = canvas.toDataURL('image/jpg') }) return url } // 点击弹出框显示的事件内容 const handleDialogClick = () => { // 需要打印的模块 const elementHtml = document.getElementsByClassName('box-excel')[0] state.imgBaseUrl = await PageSnapshot(elementHtml) nextTick(() => { state.dialogSnapshot = true }) }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。