import { defineComponent } from 'vue'; import 'vue-cropper/dist/index.css'; import { VueCropper } from 'vue-cropper'; import styles from './index.module.less'; export default defineComponent({ name: 'col-cropper', components: { VueCropper }, props: { hideInput: { type: Boolean, default: false }, option: { type: Object }, onCancelTailor: { type: Function, default: () => {} }, // 取消 getBase64Data: { type: Function, default: () => {} }, getBlob: { type: Function, default: () => {} }, getFile: { type: Function, default: () => {} }, imgOriginF: { type: Function, default: () => {} } }, data() { return { img: '', config: { ceilbutton: false, //顶部按钮,默认底部 outputSize: 1, //裁剪生成图片的质量 outputType: 'png', //裁剪生成图片的格式,默认png info: false, //裁剪框的大小信息 canScale: true, //图片是否允许滚轮缩放 autoCrop: false, //是否默认生成截图框 autoCropWidth: 0, //默认生成截图框宽度 autoCropHeight: 0, //默认生成截图框高度 fixed: true, //是否开启截图框宽高固定比例 fixedNumber: [1, 1], //截图框的宽高比例 full: false, //是否输出原图比例的截图 fixedBox: true, //固定截图框大小 不允许改变 canMove: true, //上传图片是否可以移动 canMoveBox: false, //截图框能否拖动 original: false, //上传图片按照原始比例渲染 centerBox: true, //截图框是否被限制在图片里面 high: true, //是否按照设备的dpr 输出等比例图片 infoTrue: false, //true 为展示真实输出图片宽高 false 展示看到的截图框宽高 maxImgSize: 2000, //限制图片最大宽度和高度 enlarge: 1, //图片根据截图框输出比例倍数 mode: '100%', //图片默认渲染方式 cancelButtonText: '取消', //取消按钮文本 confirmButtonText: '确定', //确定按钮文本 cancelButtonBackgroundColor: '#606266', //取消按钮背景色 confirmButtonBackgroundColor: '#ed594c', //确定按钮背景色 cancelButtonTextColor: '#ffffff', //取消按钮字体色 confirmButtonTextColor: '#ffffff' //确定按钮字体色 } }; }, mounted() { this.config = Object.assign(this.config, this.option); }, methods: { //添加网格线 addSlide() { if (document.getElementById('vertical') == null) { let box = document.getElementsByClassName('cropper-crop-box')[0]; //左网格线 let verticalLeft = document.createElement('div'); verticalLeft.id = 'vertical'; verticalLeft.style.width = '1px'; verticalLeft.style.height = '100%'; verticalLeft.style.top = '0px'; verticalLeft.style.left = '33%'; verticalLeft.style.position = 'absolute'; verticalLeft.style.backgroundColor = '#fff'; verticalLeft.style.zIndex = '522'; verticalLeft.style.opacity = '0.5'; //右网格线 let verticalRight = document.createElement('div'); verticalRight.style.width = '1px'; verticalRight.style.height = '100%'; verticalRight.style.top = '0px'; verticalRight.style.right = '33%'; verticalRight.style.position = 'absolute'; verticalRight.style.backgroundColor = '#fff'; verticalRight.style.zIndex = '522'; verticalRight.style.opacity = '0.5'; //上网格线 let verticalTop = document.createElement('div'); verticalTop.style.width = '100%'; verticalTop.style.height = '1px'; verticalTop.style.top = '33%'; verticalTop.style.left = '0px'; verticalTop.style.position = 'absolute'; verticalTop.style.backgroundColor = '#fff'; verticalTop.style.zIndex = '522'; verticalTop.style.opacity = '0.5'; //下网格线 let verticalBottom = document.createElement('div'); verticalBottom.style.width = '100%'; verticalBottom.style.height = '1px'; verticalBottom.style.bottom = '33%'; verticalBottom.style.left = '0px'; verticalBottom.style.position = 'absolute'; verticalBottom.style.backgroundColor = '#fff'; verticalBottom.style.zIndex = '522'; verticalBottom.style.opacity = '0.5'; //左上边线 let LeftTopSide = document.createElement('div'); LeftTopSide.style.width = '30px'; LeftTopSide.style.height = '4px'; LeftTopSide.style.top = '-4px'; LeftTopSide.style.left = '-4px'; LeftTopSide.style.position = 'absolute'; LeftTopSide.style.backgroundColor = '#fff'; LeftTopSide.style.zIndex = '522'; LeftTopSide.style.opacity = '1'; //上左边线 let TopListSide = document.createElement('div'); TopListSide.style.width = '4px'; TopListSide.style.height = '30px'; TopListSide.style.top = '-4px'; TopListSide.style.left = '-4px'; TopListSide.style.position = 'absolute'; TopListSide.style.backgroundColor = '#fff'; TopListSide.style.zIndex = '522'; TopListSide.style.opacity = '1'; //右上边线 let RightTopSide = document.createElement('div'); RightTopSide.style.width = '30px'; RightTopSide.style.height = '4px'; RightTopSide.style.top = '-4px'; RightTopSide.style.right = '-4px'; RightTopSide.style.position = 'absolute'; RightTopSide.style.backgroundColor = '#fff'; RightTopSide.style.zIndex = '522'; RightTopSide.style.opacity = '1'; //上右边线 let TopRightSide = document.createElement('div'); TopRightSide.style.width = '4px'; TopRightSide.style.height = '30px'; TopRightSide.style.top = '-4px'; TopRightSide.style.right = '-4px'; TopRightSide.style.position = 'absolute'; TopRightSide.style.backgroundColor = '#fff'; TopRightSide.style.zIndex = '522'; TopRightSide.style.opacity = '1'; //左下边线 let LeftBottomSide = document.createElement('div'); LeftBottomSide.style.width = '30px'; LeftBottomSide.style.height = '4px'; LeftBottomSide.style.bottom = '-4px'; LeftBottomSide.style.left = '-4px'; LeftBottomSide.style.position = 'absolute'; LeftBottomSide.style.backgroundColor = '#fff'; LeftBottomSide.style.zIndex = '522'; LeftBottomSide.style.opacity = '1'; //下左边线 let BottomListSide = document.createElement('div'); BottomListSide.style.width = '4px'; BottomListSide.style.height = '30px'; BottomListSide.style.bottom = '-4px'; BottomListSide.style.left = '-4px'; BottomListSide.style.position = 'absolute'; BottomListSide.style.backgroundColor = '#fff'; BottomListSide.style.zIndex = '522'; BottomListSide.style.opacity = '1'; //右下边线 let RightBottomSide = document.createElement('div'); RightBottomSide.style.width = '30px'; RightBottomSide.style.height = '4px'; RightBottomSide.style.bottom = '-4px'; RightBottomSide.style.right = '-4px'; RightBottomSide.style.position = 'absolute'; RightBottomSide.style.backgroundColor = '#fff'; RightBottomSide.style.zIndex = '522'; RightBottomSide.style.opacity = '1'; //下右边线 let BottomRightSide = document.createElement('div'); BottomRightSide.style.width = '4px'; BottomRightSide.style.height = '30px'; BottomRightSide.style.bottom = '-4px'; BottomRightSide.style.right = '-4px'; BottomRightSide.style.position = 'absolute'; BottomRightSide.style.backgroundColor = '#fff'; BottomRightSide.style.zIndex = '522'; BottomRightSide.style.opacity = '1'; //一起生成 box.appendChild(verticalLeft); box.appendChild(verticalRight); box.appendChild(verticalTop); box.appendChild(verticalBottom); box.appendChild(LeftTopSide); box.appendChild(TopListSide); box.appendChild(RightTopSide); box.appendChild(TopRightSide); box.appendChild(LeftBottomSide); box.appendChild(BottomListSide); box.appendChild(RightBottomSide); box.appendChild(BottomRightSide); } }, //异步onload图片 onLoadImg(photoUrl: any) { return new Promise(function (resolve, reject) { let reader = new FileReader(); reader.readAsDataURL(photoUrl); reader.onload = (e: any) => { resolve(e.target['result']); }; }); }, /** * 载入文件 * template: * * * javascript: * this.$refs.cropper.loadFile() * * @param file */ loadFile(file: any) { if (file instanceof File) { this.onLoadImg(file).then((base64: any) => { this.img = base64; setTimeout(() => { this.config.autoCrop = true; this.addSlide(); }, 10); }); } else { throw new Error('Arguments file is not File'); } }, /** * * @param base64 */ loadBase64(base64: string) { if (typeof base64 !== 'string') { throw new Error('Arguments base64 is not string'); } const base = base64.split(','); if (!/^data:image\/(.*?);base64$/.test(base[0])) { throw new Error('Arguments base64 MIME is not image/*'); } // Base64 Regex @see https://learnku.com/articles/42295 if ( !/^[\/]?([\da-zA-Z]+[\/+]+)*[\da-zA-Z]+([+=]{1,2}|[\/])?$/.test(base[1]) ) { throw new Error('Not standard base64'); } this.img = base64; setTimeout(() => { this.config.autoCrop = true; this.addSlide(); }, 10); }, rotating(e: any) { (this as any).$refs.cropper.rotateRight(); // document.getElementsByClassName("cropper-modal")[0].style = "background-color: rgba(0,0,0,0.5);transition: 0.88s"; }, canceltailor() { this.img = ''; this.onCancelTailor(); }, tailoring() { // 获取截图的base64数据 (this as any).$refs.cropper.getCropData((data: any) => { this.getBase64Data(data); this.getBlob(data); this.img = ''; this.config.autoCrop = false; }); // 获取截图的blob数据 (this as any).$refs.cropper.getCropBlob((data: BlobPart) => { this.getBase64Data(data); this.getBlob(data); // Blob 转 File const suffix = { jpeg: 'jpg', png: 'png', webp: 'webp' }[this.config.outputType]; const time = new Date().getTime(); const file = new File([data], `${time}.${suffix}`, { type: `image/${this.config.outputType}` }); this.getFile(file); this.img = ''; this.config.autoCrop = false; }); }, async upPhoto(e: any) { let photoUrl = e.target.files[0]; (this as any).$refs.headInput.value = null; if (photoUrl != undefined) { this.imgOriginF(photoUrl); this.img = (await this.onLoadImg(photoUrl)) as string; this.config.autoCrop = true; setTimeout(() => { this.addSlide(); }, 20); } }, onCropMoving(e: any) { // console.log('onCropMoving') }, onImgMoving(e: any) { // console.log('onCropMoving') } }, render() { return (
{this.hideInput} {!this.hideInput ? ( ) : null} {this.img != '' ? (
{this.config.ceilbutton ? (
{this.config.cancelButtonText}
{this.config.confirmButtonText}
) : null}
{!this.config.ceilbutton ? (
{this.config.cancelButtonText}
{this.config.confirmButtonText}
) : null}
) : null}
); } });