| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602 |
- <template name="cropper">
- <view>
- <image :src="imgSrc.imgSrc" class="my-avatar" mode="aspectFill" :style="imgStyle"></image>
- <!-- 上传图片 -->
- <canvas canvas-id="avatar-canvas" id="avatar-canvas" class="my-canvas" :style="{top: styleTop, height: cvsStyleHeight}"
- disable-scroll="false"></canvas>
- <!-- 截取边框 -->
- <canvas canvas-id="oper-canvas" id="oper-canvas" class="oper-canvas" :style="{top: styleTop, height: cvsStyleHeight}"
- disable-scroll="false" @touchstart="fStart" @touchmove="fMove" @touchend="fEnd"></canvas>
- <view class="oper-wrapper" :style="{display: styleDisplay}">
- <view class="btn-wrapper" v-if="showOper">
- <view @click="fClose" hover-class="hover">取消</view>
- <view @click="fUpload" hover-class="hover">选取</view>
- </view>
- </view>
- </view>
- </template>
- <script>
- const tabHeight = 70;
- export default {
- name: "cropper",
- data() {
- return {
- cvsStyleHeight: '0px',
- styleDisplay: 'none',
- styleTop: '-10000px',
- prvTop: '-10000px',
- imgStyle: {},
- selStyle: {},
- showOper: true,
- imgSrc: {
- imgSrc: ''
- },
- qlty: 0.9,
- postWidthFirst: {},
- };
- },
- watch: {
- avatarSrc() {
- this.imgSrc.imgSrc = this.avatarSrc;
- }
- },
- props: {
- avatarSrc: '',
- avatarStyle: '',
- selWidth: '',
- selHeight: '',
- expWidth: '',
- expHeight: '',
- minScale: '',
- maxScale: '',
- canScale: '',
- noTop: '',
- quality: '',
- index: ''
- },
- created() {
- this.ctxCanvas = uni.createCanvasContext('avatar-canvas', this);
- this.ctxCanvasOper = uni.createCanvasContext('oper-canvas', this);
- this.qlty = parseInt(this.quality) || 0.9;
- this.imgSrc.imgSrc = this.avatarSrc;
- this.letScale = this.canScale === 'false' ? 0 : 1;
- this.indx = this.index || undefined;
- this.mnScale = this.minScale || 0.3;
- this.mxScale = this.maxScale || 4;
- this.noBar = this.noTop ? false : true;
- if (!!this.noBar) {
- this.moreHeight = 0;
- this.fWindowResize();
- } else {
- uni.showTabBar({
- complete: (res) => {
- this.moreHeight = (res.errMsg === 'showTabBar:ok') ? 50 : 0;
- this.fWindowResize();
- }
- });
- }
- },
- methods: {
- fWindowResize() {
- let sysInfo = uni.getSystemInfoSync();
- this.platform = sysInfo.platform;
- this.pixelRatio = sysInfo.pixelRatio;
- this.windowWidth = sysInfo.windowWidth;
- // #ifdef H5
- this.drawTop = sysInfo.windowTop;
- this.windowHeight = sysInfo.windowHeight + sysInfo.windowBottom;
- this.cvsStyleHeight = this.windowHeight - tabHeight + 'px';
- // #endif
- // #ifdef MP-WEIXIN
- this.windowHeight = sysInfo.windowHeight;
- this.cvsStyleHeight = this.windowHeight - tabHeight + 'px';
- this.cvsStyleHeight = this.windowHeight - tabHeight + 'px'
- // #endif
- this.pxRatio = this.windowWidth / 750;
- let style = this.avatarStyle;
- this.imgStyle = style;
- this.expWidth && (this.exportWidth = this.expWidth.indexOf('rpx') >= 0 ? parseInt(this.expWidth) * this.pxRatio :
- parseInt(this.expWidth));
- this.expHeight && (this.exportHeight = this.expHeight.indexOf('rpx') >= 0 ? parseInt(this.expHeight) * this.pxRatio :
- parseInt(this.expHeight));
- if (this.styleDisplay === 'flex') {
- this.fDrawInit(true);
- }
- this.fHideImg();
- },
- fSelect() {
- let self=this;
- if (this.fSelecting) return;
- this.fSelecting = true;
- setTimeout(() => {
- this.fSelecting = false;
- }, 500);
- uni.chooseImage({
- count: 1,
- sizeType: ['original', 'compressed'],
- sourceType: ['camera', 'album'],
- success: (r) => {
- uni.showLoading({
- mask: true
- });
- let path = this.imgPath = r.tempFilePaths[0];
- uni.getImageInfo({
- src: path,
- success: r => {
- this.imgWidth = r.width;
- this.imgHeight = r.height;
- this.path = path;
- if (!this.hasSel) {
- let style = this.selStyle || {};
- if (this.selWidth && this.selHeight) {
- let selWidth = this.selWidth.indexOf('rpx') >= 0 ? parseInt(this.selWidth) * this.pxRatio :
- parseInt(this.selWidth),
- selHeight = this.selHeight.indexOf('rpx') >= 0 ? parseInt(this.selHeight) * this.pxRatio :
- parseInt(this.selHeight);
- style.width = parseInt(selWidth);
- style.height = parseInt(selHeight);
- style.top = parseInt((this.windowHeight - style.height - tabHeight) / 2);
- style.left = parseInt((this.windowWidth - style.width) / 2);
- } else {
- uni.showModal({
- title: '裁剪框的宽或高没有设置',
- showCancel: false
- })
- return;
- }
- this.selStyle = style;
- }
- if (!!self.noBar) {
- self.fDrawInit(true);
- } else {
- uni.hideTabBar({
- complete: () => {
- self.fDrawInit(true);
- }
- });
- }
- },
- fail: () => {
- uni.showToast({
- title: "error3",
- duration: 2000,
- })
- },
- complete() {
- uni.hideLoading();
- }
- });
- }
- })
- },
- fUpload() {
- if (this.fUploading) return;
- this.fUploading = true;
- setTimeout(() => {
- this.fUploading = false;
- }, 1000)
- let style = this.selStyle,
- x = parseInt(style.left),
- y = parseInt(style.top),
- width = parseInt(style.width),
- height = parseInt(style.height),
- expWidth = this.exportWidth || width,
- expHeight = this.exportHeight || height;
- this.styleDisplay = 'none';
- this.styleTop = '-10000px';
- this.hasSel = false;
- this.fHideImg();
- uni.canvasToTempFilePath({
- x: x,
- y: y,
- width: width,
- height: height,
- destWidth: expWidth,
- destHeight: expHeight,
- canvasId: 'avatar-canvas',
- fileType: 'png',
- quality: this.qlty,
- success: (r) => {
- console.log(r,'裁剪后的图片')
- this.$emit("uploadImg", r.tempFilePath);
- },
- fail: (res) => {
- uni.showToast({
- title: "error1",
- duration: 2000,
- })
- },
- complete: () => {
- this.noBar || uni.showTabBar();
- }
- }, this);
- },
- fDrawInit(ini = false) {
- let allWidth = this.windowWidth,
- allHeight = this.windowHeight,
- imgWidth = this.imgWidth,
- imgHeight = this.imgHeight,
- imgRadio = imgWidth / imgHeight,
- useWidth = allWidth,
- useHeight = allHeight - tabHeight,
- pixelRatio = this.pixelRatio,
- selWidth = parseInt(this.selStyle.width),
- selHeight = parseInt(this.selStyle.height);
- this.fixWidth = 0;
- this.fixHeight = 0;
- if (this.fixWidth) {
- useWidth = selWidth;
- useHeight = useWidth / imgRadio;
- } else if (this.fixHeight) {
- useHeight = selHeight;
- useWidth = useHeight * imgRadio;
- } else if (imgRadio < 1) {
- useWidth = selWidth;
- useHeight = parseInt(useWidth / imgRadio);
- } else {
- useHeight = selHeight;
- useWidth = parseInt(useHeight * imgRadio);
- }
- this.scaleSize = 1;
- this.rotateDeg = 0;
- this.posWidth = parseInt((allWidth - useWidth) / 2);
- this.posHeight = parseInt((allHeight - useHeight - tabHeight) / 2);
- this.useWidth = useWidth;
- this.useHeight = useHeight;
- let style = this.selStyle,
- left = parseInt(style.left),
- top = parseInt(style.top),
- width = parseInt(style.width),
- height = parseInt(style.height),
- canvas = this.canvas,
- canvasOper = this.canvasOper,
- ctxCanvas = this.ctxCanvas,
- ctxCanvasOper = this.ctxCanvasOper;
- ctxCanvasOper.setFillStyle('rgba(0,0,0, 0.5)');
- ctxCanvasOper.fillRect(0, 0, this.windowWidth, top);
- ctxCanvasOper.fillRect(0, top, left, height);
- ctxCanvasOper.fillRect(0, top + height, this.windowWidth, this.windowHeight - height - tabHeight - top);
- ctxCanvasOper.fillRect(left + width, top, this.windowWidth - width - left, height);
- ctxCanvasOper.setLineWidth(1);
- ctxCanvasOper.setStrokeStyle('rgba(255, 255, 255,1)'); //细线的颜色
- ctxCanvasOper.strokeRect(left, top, width, height);
- // #ifdef H5
- ctxCanvasOper.draw();
- // #endif
- ctxCanvasOper.setLineWidth(3);
- ctxCanvasOper.setStrokeStyle('rgba(255, 255, 255, 1)'); //粗线的颜色
- ctxCanvasOper.moveTo(left + 20, top);
- ctxCanvasOper.lineTo(left, top);
- ctxCanvasOper.lineTo(left, top + 20);
- ctxCanvasOper.moveTo(left + width - 20, top);
- ctxCanvasOper.lineTo(left + width, top);
- ctxCanvasOper.lineTo(left + width, top + 20);
- ctxCanvasOper.moveTo(left + 20, top + height);
- ctxCanvasOper.lineTo(left, top + height);
- ctxCanvasOper.lineTo(left, top + height - 20);
- ctxCanvasOper.moveTo(left + width - 20, top + height);
- ctxCanvasOper.lineTo(left + width, top + height);
- ctxCanvasOper.lineTo(left + width, top + height - 20);
- ctxCanvasOper.stroke();
- this.postFirst = {
- left: left,
- top: top,
- width: width,
- height: selWidth,
- posWidth: this.posWidth,
- posHeight: this.posHeight
- };
- // #ifdef MP-WEIXIN
- ctxCanvasOper.draw(false, () => {
- if (ini) {
- this.styleDisplay = 'flex';
- this.styleTop = '0';
- ctxCanvas.setFillStyle('black');
- this.fDrawImage();
- }
- });
- // #endif
- // #ifdef H5
- ctxCanvasOper.draw(true, () => {
- if (ini) {
- this.styleDisplay = 'flex';
- this.styleTop = this.drawTop + 'px';
- ctxCanvas.setFillStyle('black');
- this.fDrawImage();
- }
- });
- // #endif
- this.$emit("avtinit");
- },
- fDrawImage() {
- let tm_now = Date.now();
- if ((tm_now - this.drawTm )< 20) return;
- this.drawTm = tm_now;
- let ctxCanvas = this.ctxCanvas;
- ctxCanvas.fillRect(0, 0, this.windowWidth, this.windowHeight - tabHeight);
- //中心点坐标
- ctxCanvas.translate(this.posWidth + this.useWidth / 2, this.posHeight + this.useHeight / 2);
- //比例缩放
- ctxCanvas.scale(this.scaleSize, this.scaleSize);
- ctxCanvas.drawImage(this.imgPath, -this.useWidth / 2, -this.useHeight / 2, this.useWidth, this.useHeight);
- ctxCanvas.draw(false);
- },
- fHideImg() {
- this.prvImg = '';
- this.prvTop = '-10000px';
- this.showOper = true;
- this.prvImgData = null;
- this.target = null;
- },
- fClose() {
- this.styleDisplay = 'none';
- this.styleTop = '-10000px';
- this.hasSel = false;
- this.fHideImg();
- this.noBar || uni.showTabBar();
- },
- // #ifdef MP-WEIXIN
- fStart(e) {
- let touches = e.touches,
- touch0 = touches[0],
- touch1 = touches[1];
- this.touch0 = touch0;
- this.touch1 = touch1;
- if (touch1) {
- let x = touch1.x - touch0.x,
- y = touch1.y - touch0.y;
- this.fgDistance = Math.sqrt(x * x + y * y);
- }
- },
- // #endif
- // #ifdef H5
- fStart(e) {
- let touches = e.touches,
- touch0 = touches[0],
- touch1 = touches[1];
- this.touch0 = touch0;
- this.touch1 = touch1;
- if (touch1) {
- let x = touch1.clientX - touch0.clientX,
- y = touch1.clientY - touch0.clientY;
- this.fgDistance = Math.sqrt(x * x + y * y);
- }
- },
- // #endif
- // #ifdef MP-WEIXIN
- fMove(e) {
- let touches = e.touches,
- touch0 = touches[0],
- touch1 = touches[1];
- if (touch1) {
- let x = touch1.x - touch0.x,
- y = touch1.y - touch0.y,
- fgDistance = Math.sqrt(x * x + y * y),
- scaleSize = 0.005 * (fgDistance - this.fgDistance),
- beScaleSize = this.scaleSize + scaleSize;
- do {
- if (!this.letScale) break;
- if (beScaleSize < this.mnScale) break;
- if (beScaleSize > this.mxScale) break;
- this.scaleSize = beScaleSize;
- } while (0);
- this.fgDistance = fgDistance;
- if (touch1.x !== touch0.x && this.letRotate) {
- x = (this.touch1.y - this.touch0.y) / (this.touch1.x - this.touch0.x);
- y = (touch1.y - touch0.y) / (touch1.x - touch0.x);
- this.rotateDeg += Math.atan((y - x) / (1 + x * y)) * 180 / Math.PI;
- this.touch0 = touch0;
- this.touch1 = touch1;
- }
- this.fDrawImage();
- } else if (this.touch0) {
- let x = touch0.x - this.touch0.x,
- y = touch0.y - this.touch0.y,
- beX = this.posWidth + x,
- beY = this.posHeight + y;
- if (Math.abs(x) < 100 && !this.lckWidth) this.posWidth = beX;
- if (Math.abs(y) < 100 && !this.lckHeight) this.posHeight = beY;
- this.touch0 = touch0;
- this.fDrawImage();
- }
- },
- // #endif
- // #ifdef H5
- fMove(e) {
- let touches = e.touches,
- touch0 = touches[0],
- touch1 = touches[1];
- if (touch1) {
- let x = touch1.clientX - touch0.clientX,
- y = touch1.clientY - touch0.clientY,
- fgDistance = Math.sqrt(x * x + y * y),
- scaleSize = 0.005 * (fgDistance - this.fgDistance),
- beScaleSize = this.scaleSize + scaleSize;
- do {
- if (!this.letScale) break;
- if (beScaleSize < this.mnScale) break;
- if (beScaleSize > this.mxScale) break;
- this.scaleSize = beScaleSize;
- } while (0);
- this.fgDistance = fgDistance;
- if (touch1.x !== touch0.x && this.letRotate) {
- x = (this.touch1.clientY - this.touch0.clientY) / (this.touch1.clientX - this.touch0.clientX);
- y = (touch1.clientY - touch0.clientY) / (touch1.clientX - touch0.clientX);
- this.rotateDeg += Math.atan((y - x) / (1 + x * y)) * 180 / Math.PI;
- this.touch0 = touch0;
- this.touch1 = touch1;
- }
- this.fDrawImage();
- } else if (this.touch0) {
- let x=touch0.clientX - this.touch0.clientX,
- y=touch0.clientY - this.touch0.clientY,
- // let x = touch0.x - this.touch0.x,
- // y = touch0.y - this.touch0.y,
- beX = this.posWidth + x,
- beY = this.posHeight + y;
- if (Math.abs(x) < 100 && !this.lckWidth) this.posWidth = beX;
- if (Math.abs(y) < 100 && !this.lckHeight) this.posHeight = beY;
- this.touch0 = touch0;
- this.fDrawImage();
- }
- },
- // #endif
- async fEnd(e) {
- let self = this;
- let touches = e.touches,
- touch0 = touches && touches[0],
- touch1 = touches && touches[1];
- if (self.scaleSize < 1) {
- let style = self.selStyle;
- let imgRadio = self.imgWidth / self.imgHeight;
- //高长宽短
- if (imgRadio < 1 && self.scaleSize * self.useWidth < style.width) {
- self.posWidth = style.left;
- self.scaleSize = 1
- setTimeout(function() {
- self.fDrawImage();
- }, 100)
- } else if (self.scaleSize * self.useHeight < style.width) {
- //高短宽长
- self.posHeight = style.top;
- self.scaleSize = 1
- setTimeout(function() {
- self.fDrawImage();
- }, 100)
- }
- } else if (this.scaleSize == 1) {
- let endWidth = this.posWidth - this.postFirst.posWidth,
- firstWidth = this.postFirst.left - this.postFirst.posWidth;
- let endHeight = this.posHeight - this.postFirst.posHeight,
- firstHigth = this.postFirst.top - this.postFirst.posHeight;
- if (endWidth > 0 && this.posWidth > this.postFirst.left) {
- //右滑动过长
- this.posWidth = this.postFirst.left;
- } else if (endWidth < 0 && endWidth < firstWidth) {
- //左滑动过长
- this.posWidth = -this.postFirst.left + this.postFirst.posWidth * 2;
- }
- if (endHeight < 0 && this.posHeight < this.postFirst.top) {
- //上滑动过长
- this.posHeight = -this.postFirst.top + this.postFirst.posHeight * 2 ;
- } else if (endHeight > 0 && endHeight > firstHigth) {
- //下滑动过长
- this.posHeight = this.postFirst.top;
- }
- setTimeout(function() {
- self.fDrawImage();
- }, 100);
- }
- if (touch0) {
- this.touch0 = touch0;
- } else {
- this.touch0 = null;
- this.touch1 = null;
- }
- },
- btop(base64) {
- return new Promise(function(resolve, reject) {
- var arr = base64.split(','),
- mime = arr[0].match(/:(.*?);/)[1],
- bstr = atob(arr[1]),
- n = bstr.length,
- u8arr = new Uint8Array(n);
- while (n--) {
- u8arr[n] = bstr.charCodeAt(n);
- }
- return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([u8arr], {
- type: mime
- })));
- });
- },
- }
- }
- </script>
- <style>
- .my-canvas {
- display: flex;
- position: fixed !important;
- background: #000000;
- left: 0;
- z-index: 100;
- width: 100%;
- }
- .my-avatar {
- width: 100vw;
- height: 100vw;
- }
- .oper-canvas {
- display: flex;
- position: fixed !important;
- left: 0;
- z-index: 101;
- width: 100%;
- }
- .oper-wrapper {
- height: 71px;
- position: fixed !important;
- box-sizing: border-box;
- width: 100%;
- left: 0;
- bottom: 0;
- z-index: 200;
- flex-direction: row;
- }
- .btn-wrapper {
- background-color: #000000;
- color: #ffffff;
- display: flex;
- height: 100%;
- width: 100%;
- justify-content: space-around;
- align-items: center
- }
- .btn-wrapper view {
- width: 160rpx;
- height: 80rpx;
- line-height: 80rpx;
- text-align: center;
- font-size: 16px;
- color: #ffffff;
- z-index: 300;
- }
- .hover {
- color: #f1f1f1;
- }
- </style>
|