UNPKG

vue-cropblg

Version:
1,545 lines (1,348 loc) 54.7 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "fb15"); /******/ }) /************************************************************************/ /******/ ({ /***/ "f6fd": /***/ (function(module, exports) { // document.currentScript polyfill by Adam Miller // MIT license (function(document){ var currentScript = "currentScript", scripts = document.getElementsByTagName('script'); // Live NodeList collection // If browser needs currentScript polyfill, add get currentScript() to the document object if (!(currentScript in document)) { Object.defineProperty(document, currentScript, { get: function(){ // IE 6-10 supports script readyState // IE 10+ support stack trace try { throw new Error(); } catch (err) { // Find the second match for the "at" string to get file src url from stack. // Specifically works with the format of stack traces in IE. var i, res = ((/.*at [^\(]*\((.*):.+:.+\)$/ig).exec(err.stack) || [false])[1]; // For all scripts on the page, if src matches or if ready state is interactive, return the script tag for(i in scripts){ if(scripts[i].src == res || scripts[i].readyState == "interactive"){ return scripts[i]; } } // If no match, return null return null; } } }); } })(document); /***/ }), /***/ "fb15": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js // This file is imported into lib/wc client bundles. if (typeof window !== 'undefined') { if (true) { __webpack_require__("f6fd") } var i if ((i = window.document.currentScript) && (i = i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))) { __webpack_require__.p = i[1] // eslint-disable-line } } // Indicate to webpack that this file can be concatenated /* harmony default export */ var setPublicPath = (null); // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"4f589c96-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./packages/cropblg.vue?vue&type=template&id=5aff7163& var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"mountNode",staticClass:"mount-node",staticStyle:{"overflow":"hidden"},on:{"touchstart":function($event){return _vm.handleStart($event)},"touchmove":function($event){return _vm.handleMove($event)},"touchend":function($event){return _vm.handleEnd($event)}}},[_c('div',{directives:[{name:"show",rawName:"v-show",value:(_vm.noImage),expression:"noImage"}],staticClass:"no-image-file",staticStyle:{"height":"100%","display":"flex","justify-content":"center","align-items":"center","flex-wrap":"wrap"},on:{"click":_vm.inputHandle,"touchstart":function($event){$event.stopPropagation();return (function (){})($event)},"touchmove":function($event){$event.stopPropagation();return (function (){})($event)}}},[_vm._t("placeholder",[_c('span',[_vm._v("暂时没有图片,请选择图像")])]),_c('div',{staticStyle:{"display":"none"}},[_c('input',{attrs:{"type":"file","multiple":false,"id":"file-input","accept":"image/*"},on:{"change":_vm.uploadImg}}),_vm._t("defaultImgUrl")],2)],2)])} var staticRenderFns = [] // CONCATENATED MODULE: ./packages/cropblg.vue?vue&type=template&id=5aff7163& // CONCATENATED MODULE: ./packages/util.js // exif https://github.com/exif-js/exif-js/blob/master/exif.js var getImageDirection = function getImageDirection(img) { return new Promise(function (reslove, reject) { getImageData(img).then(function (data) { var orientation = getOrientation(data) || 1; reslove(orientation); }).catch(function (error) { reject(error); }); }); }; // 这里的获取exif要将图片转ArrayBuffer对象,这里假设获取了图片的baes64 // 步骤一 // base64转ArrayBuffer对象 function getImageData(img) { var data = null; return new Promise(function (reslove, reject) { if (img.src) { // eslint-disable-next-line if (/^data\:/i.test(img.src)) { // Data URI data = base64ToArrayBuffer(img.src); reslove(data); } else { var http = new XMLHttpRequest(); http.onload = function () { if (this.status == 200 || this.status === 0) { data = http.response; reslove(data); } else { throw "Could not load image"; } http = null; }; http.open("GET", img.src, true); http.responseType = "arraybuffer"; http.send(null); } } else { reject('img error'); } }); } /*eslint no-useless-escape: "error"*/ function base64ToArrayBuffer(base64) { // eslint-disable-next-line base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, ''); var binary = atob(base64); var len = binary.length; var buffer = new ArrayBuffer(len); var view = new Uint8Array(buffer); for (var i = 0; i < len; i++) { view[i] = binary.charCodeAt(i); } return buffer; } // 步骤二,Unicode码转字符串 // ArrayBuffer对象 Unicode码转字符串 function getStringFromCharCode(dataView, start, length) { var str = ''; var i; for (i = start, length += start; i < length; i++) { str += String.fromCharCode(dataView.getUint8(i)); } return str; } // 步骤三,获取jpg图片的exif的角度(在ios体现最明显) function getOrientation(arrayBuffer) { var dataView = new DataView(arrayBuffer); var length = dataView.byteLength; var orientation; var exifIDCode; var tiffOffset; var firstIFDOffset; var littleEndian; var endianness; var app1Start; var ifdStart; var offset; var i; // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { offset = 2; while (offset < length) { if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) { app1Start = offset; break; } offset++; } } if (app1Start) { exifIDCode = app1Start + 4; tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { endianness = dataView.getUint16(tiffOffset); littleEndian = endianness === 0x4949; if (littleEndian || endianness === 0x4D4D /* bigEndian */ ) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; } } } } } if (ifdStart) { length = dataView.getUint16(ifdStart, littleEndian); for (i = 0; i < length; i++) { offset = ifdStart + i * 12 + 2; if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */ ) { // 8 is the offset of the current tag's value offset += 8; // Get the original orientation value orientation = dataView.getUint16(offset, littleEndian); // Override the orientation with its default value for Safari (#120) // if (IS_SAFARI_OR_UIWEBVIEW) { // dataView.setUint16(offset, 1, littleEndian); // } break; } } } return orientation; } // canvas-exif-orientation https://github.com/koba04/canvas-exif-orientation/blob/master/index.js // function correctImage(img, orientation, type, x, y, width, height) { if (!/^[1-8]$/.test(orientation)) throw new Error('orientation should be [1-8]'); if (x == null) x = 0; if (y == null) y = 0; if (width == null) width = img.width; if (height == null) height = img.height; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = width; canvas.height = height; ctx.save(); switch (+orientation) { // 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. case 1: break; // 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. case 2: ctx.translate(width, 0); ctx.scale(-1, 1); break; // 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. case 3: ctx.translate(width, height); ctx.rotate(180 / 180 * Math.PI); break; // 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. case 4: ctx.translate(0, height); ctx.scale(1, -1); break; // 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. case 5: canvas.width = height; canvas.height = width; ctx.rotate(90 / 180 * Math.PI); ctx.scale(1, -1); break; // 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. case 6: canvas.width = height; canvas.height = width; ctx.rotate(90 / 180 * Math.PI); ctx.translate(0, -height); break; // 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. case 7: canvas.width = height; canvas.height = width; ctx.rotate(270 / 180 * Math.PI); ctx.translate(-width, height); ctx.scale(1, -1); break; // 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. case 8: canvas.width = height; canvas.height = width; ctx.translate(0, width); ctx.rotate(270 / 180 * Math.PI); break; } ctx.drawImage(img, x, y, width, height); ctx.restore(); return canvas; // return new Promise((reslove) => { // if (!type) { // reslove(canvas) // return // } // canvas.toBlob(function(blob) { // const newImg = new Image() // const url = window.URL.createObjectURL(blob) // newImg.src = url // newImg.onload = function() { // // 手机上有严重的性能问题 // reslove(newImg) // } // }) // }) } // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./packages/cropblg.vue?vue&type=script&lang=js& function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } // // // // // // // // // // // // // // // // // // // // // // // // // // /* harmony default export */ var cropblgvue_type_script_lang_js_ = ({ name: 'crop', //1. props 验证 2.支持pc props: ['value', 'position', 'textWatermark', 'imgLoaded', 'imageWatermark', 'defaultImgUrl', 'color', 'angle', 'rotation', 'shape', 'penBtn', 'revokeBtn', 'rotateBtn'], data: function data() { return { // ready: false, noImage: true, ctx: null, options: null, pixelRatio: null, scale: 1, canvas: null, image: {}, points: [], lines: [], cropper: {}, corePoint: {}, startPoint: {}, nookSide: 20, rotateAngle: 0, bgOpacity: 0, // 三个操作按钮 默认不显示的 touchBar: null, paintBrush: null, revokeBar: null }; }, watch: { shape: function shape() { if (!this.noImage) { this.draw(); } }, rotation: function rotation() { // 内旋转 外旋转 只能有一个 if (!this.noImage && !this.rotateBtn && !this.drawAction) { this.rotateAngle = this.rotation; this.draw(); } } }, methods: { init: function init(img) { this.pointList = []; var clientW = img.width, clientH = img.height, _this$options = this.options, width = _this$options.width, height = _this$options.height; var currentW = clientW, currentH = clientH, k = 1; // contain 时的缩放比 // contain 图片 if (clientW > width) { // alert('12123') currentW = width; k = currentW / clientW; currentH = k * clientH; } if (currentH > height) { currentH = height; k = currentH / clientH; currentW = k * clientW; } // 针对小图片 var minNum = 120; if (clientW < minNum && currentH < minNum) { currentW = minNum; k = currentW / clientW; currentH = k * clientH; } this.scale = k; // 针对小图片 this.image = { element: img, width: currentW, // 显示宽度 height: currentH, // 真是 宽度 x: (width - currentW) / 2, y: (height - currentH) / 2, clientWidth: clientW, clientHeight: clientH }; var corePoint = this.corePoint = { x: width / 2, y: height / 2 }; this.maxRadius = Math.min(width, height) / 2; this.arc = { x: corePoint.x, y: corePoint.y, r: this.maxRadius / 2 }; this.cropper = { x: (width - currentW / 2) / 2, y: (height - currentH / 2) / 2, width: currentW / 2, height: currentH / 2 }; var interval = 8; // 间隔 var number = 0; // 按钮数量 // 三个 if 更好 内聚 -- var rotateBtn = this.rotateBtn === undefined || this.rotateBtn; var penBtn = this.penBtn === undefined || this.penBtn; var revokeBtn = this.revokeBtn === undefined || this.revokeBtn; if (rotateBtn) { this.touchBar = { x: width - 30 - 7, y: 10, width: 30, height: 30 }; number++; } // width 画布宽度 if (penBtn) { this.paintBrush = { x: width - 30 - 7, y: 10 + (30 + interval) * number, width: 30, height: 30 }; number++; } if (revokeBtn) { this.revokeBar = { x: width - 30 - 7, y: 10 + (30 + interval) * number, width: 30, height: 30 }; number++; } this.draw(); }, draw: function draw() { var _this$options2 = this.options, width = _this$options2.width, height = _this$options2.height, shape = this.shape || 'rect'; // 避免预览到背景 this.ctx.clearRect(0, 0, width, height); // // 背景 // 考虑用css 实现 this.fillBackground(); // 处理出片 this.fillImage(); // console.timeEnd('fillImage') this.drawPointFn(this.ctx); if (!this.averageColor) { this.averageColor = this.getImageColor(this.ctx.getImageData(this.corePoint.x - 25, this.corePoint.y - 25, 50, 50).data); } if (shape === 'arc') { this.fillArcCropper(); } else if (shape === 'rect') { this.updatePoint(); this.fillRectCropper(); } // console.time('drawTouchBar') this.drawTouchBar(this.touchBar); this.drawPaintBrush(this.paintBrush); this.drawRevokeBar(this.revokeBar); // 写的 线 // console.timeEnd('drawTouchBar') // this.preview() }, // rotatePoint({ pageX, pageY }, r, angle){ // angle = Math.PI / 180 * angle // return { // x: pageX + Math.cos(angle) * r, // y: pageY + Math.sin(angle) * r // } // }, drawPointFn: function drawPointFn(ctx) { var _this = this; var quality = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var cropper = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.image; var image = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : this.image; var pointList = this.pointList; // const image = this.image if (pointList.length > 0) { pointList.forEach(function (el) { var scale = _this.scale / el.scale; var lineWidth = _this.limit(el.lineWidth * scale, 1, 5); ctx.lineWidth = quality ? lineWidth * 2 : lineWidth; ctx.strokeStyle = el.color; ctx.lineCap = 'round'; ctx.beginPath(); el.pointLine.forEach(function (element, i) { if (i === 0) { // 要相对于图片的位置 才是对的 不能相对于 画布 if (quality) { // console.log(element) ctx.moveTo((image.x + element.x * scale - cropper.x) * quality, (image.y + element.y * scale - cropper.y) * quality); } else { ctx.moveTo(image.x + element.x * scale, image.y + element.y * scale); } } if (quality) { ctx.lineTo((image.x + element.x * scale - cropper.x) * quality, (image.y + element.y * scale - cropper.y) * quality); } else { ctx.lineTo(image.x + element.x * scale, image.y + element.y * scale); } }); ctx.stroke(); }); } // ctx.lineWidth = 5 }, drawPaintBrush: function drawPaintBrush(touchBar) { if (!touchBar) return; var x = touchBar.x, y = touchBar.y; var ctx = this.ctx, // touchBar = touchBar, color = this.color || this.averageColor; ctx.lineWidth = 2; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(x + 20, y + 5); ctx.lineTo(x + 24, y + 9); ctx.lineTo(x + 12, y + 21); ctx.lineTo(x + 7, y + 22); ctx.lineTo(x + 8, y + 17); // ctx.lineTo(x + 20, y + 5) ctx.closePath(); if (this.drawAction) { ctx.fillStyle = color; ctx.fill(); } // ctx.stroke() ctx.moveTo(x + 5, y + 26); ctx.lineTo(x + 25, y + 26); ctx.stroke(); }, drawRevokeBar: function drawRevokeBar(touchBar) { if (!touchBar) return; var x = touchBar.x, y = touchBar.y; // const {x, y, width} = touchBar // 用宽 算个比例 var ctx = this.ctx, // touchBar = touchBar, color = this.color || this.averageColor; ctx.lineWidth = 2; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(x + 15, y + 12); ctx.lineTo(x + 15, y + 8); ctx.lineTo(x + 7, y + 15); ctx.lineTo(x + 15, y + 22); ctx.lineTo(x + 15, y + 18); ctx.stroke(); ctx.fillStyle = color; ctx.fill(); ctx.beginPath(); ctx.arc(x + 15, y + 24, 12, -Math.PI / 2, -Math.PI / 180 * 18, false); ctx.arc(x + 15, y + 35, 17, -Math.PI / 180 * 45, -Math.PI / 2, true); ctx.stroke(); ctx.fillStyle = color; ctx.fill(); }, drawTouchBar: function drawTouchBar(touchBar) { if (!touchBar) return; var ctx = this.ctx, color = this.color || this.averageColor, x = touchBar.x + touchBar.width * 0.6, y = touchBar.y + touchBar.height * 0.64, r = touchBar.width * 0.41, alpha = 6, h1 = touchBar.width * 0.1, h2 = touchBar.width * 0.18; ctx.lineWidth = 1; // 填充颜色 ctx.fillStyle = color; // strokeRect fillRect ctx.fillRect(x - touchBar.width / 6, y - touchBar.height / 6, touchBar.width * 0.43, touchBar.height * 0.43); ctx.beginPath(); ctx.arc(x, y, r, Math.PI / 180 * 180, -Math.PI / 2 + alpha, false); ctx.stroke(); if (alpha < 2 * Math.PI) { var x1 = x + (r - h1) * Math.sin(alpha), y1 = y - (r - h1) * Math.cos(alpha), x2 = x + (r + h1) * Math.sin(alpha), y2 = y - (r + h1) * Math.cos(alpha), x0 = (x1 + x2) / 2 + h2 * Math.sin(alpha + Math.PI / 2), y0 = (y1 + y2) / 2 - h2 * Math.cos(alpha + Math.PI / 2); ctx.beginPath(); ctx.moveTo(x0, y0); ctx.lineTo(x1, y1); ctx.lineTo(x2, y2); ctx.fill(); } }, fillImage: function fillImage() { var image = this.image; var ctx = this.ctx; var rotateAngle = this.rotateAngle; this.canvasRotate('img', ctx, image.element, rotateAngle, image.x, image.y, image.width, image.height); // ctx.drawImage(image.element, image.x, image.y, image.width, image.height) }, updatePoint: function updatePoint() { // 点中点和线 不用 执行 var c = this.cropper, nookSide = this.nookSide, cWidth = c.x + c.width, cHeight = c.y + c.height, forecastX = cWidth - nookSide, forecastY = cHeight - nookSide; this.points = [{ x: c.x, y: c.y, width: nookSide, height: nookSide, diffX: 0, diffY: 0 }, { x: forecastX, y: c.y, width: nookSide, height: nookSide, diffX: nookSide, diffY: 0 }, { x: forecastX, y: forecastY, width: nookSide, height: nookSide, diffX: nookSide, diffY: nookSide }, { x: c.x, y: forecastY, width: nookSide, height: nookSide, diffX: 0, diffY: nookSide }]; // 寻找四根线 var lineHeight = nookSide / .7, halfLineHeight = lineHeight / 2; this.lines = [{ x: c.x, y: c.y - halfLineHeight, width: c.width, height: lineHeight }, { x: cWidth - halfLineHeight, y: c.y, width: lineHeight, height: c.height }, { x: c.x, y: cHeight - halfLineHeight, width: c.width, height: lineHeight }, { x: c.x - halfLineHeight, y: c.y, width: lineHeight, height: c.height }]; }, fillRectCropper: function fillRectCropper() { var ctx = this.ctx, cropper = this.cropper, points = this.points, color = this.color || this.averageColor; ctx.strokeStyle = color; ctx.lineWidth = 2; ctx.strokeRect(cropper.x, cropper.y, cropper.width, cropper.height); ctx.fillStyle = color; var nookSide = this.nookSide / 8; points.forEach(function (element, index) { ctx.save(); ctx.translate(element.x + element.diffX, element.y + element.diffY); ctx.rotate(index * 90 * (Math.PI / 180)); ctx.fillRect(-nookSide, -nookSide, element.height, nookSide * 2); ctx.fillRect(-nookSide, -nookSide, nookSide * 2, element.width); // if(index % 2 === 0){ // ctx.fillRect(-nookSide, cropper.height / 2 - element.nookSide , element.nookSide / 4, element.nookSide * 2) // } else { // ctx.fillRect(-nookSide, cropper.width / 2 - element.nookSide, element.nookSide / 4, element.nookSide * 2) // } ctx.restore(); }); // console.log(this.arc.r) // 圆 }, fillArcCropper: function fillArcCropper() { var ctx = this.ctx; ctx.beginPath(); ctx.strokeStyle = this.color || this.averageColor; ctx.lineWidth = 2; // this.nookSide / 0.7 ctx.arc(this.arc.x, this.arc.y, this.arc.r, 0, Math.PI * 2); ctx.stroke(); }, handleArcMove: function handleArcMove(_ref) { var x = _ref.x, y = _ref.y; this.arc.r = this.limit(this.getDistance({ pageX: x, pageY: y }, { pageX: this.arc.x, pageY: this.arc.y }), this.nookSide * 2, this.maxRadius); this.draw(); }, // 填充背景 fillBackground: function fillBackground() { // 多个变量可以用逗号 一次赋值 var _this$options3 = this.options, width = _this$options3.width, height = _this$options3.height, ctx = this.ctx; ctx.save(); ctx.fillStyle = '#fff'; ctx.fillStyle = "rgba(0, 0, 0, ".concat(this.bgOpacity, ")"); ctx.fillRect(0, 0, width, height); //蒙层 ctx.restore(); }, getNewCropper: function getNewCropper(touchX, touchY, cropper) { return { cropperWidth: cropper.x + cropper.width - touchX, cropperHeight: cropper.y + cropper.height - touchY, cropperX: touchX - cropper.x, cropperY: touchY - cropper.y }; }, handlePointMove: function handlePointMove(_ref2) { var x = _ref2.x, y = _ref2.y; var cropper = this.cropper, newCropper = {}, _this$getNewCropper = this.getNewCropper(x, y, cropper), cropperWidth = _this$getNewCropper.cropperWidth, cropperHeight = _this$getNewCropper.cropperHeight, cropperX = _this$getNewCropper.cropperX, cropperY = _this$getNewCropper.cropperY; switch (this.index) { case 0: newCropper.width = cropperWidth; newCropper.height = cropperHeight; newCropper.x = x; newCropper.y = y; break; case 1: // x 不会动 newCropper.width = cropperX; newCropper.height = cropperHeight; newCropper.y = y; break; case 3: // y 不会动 newCropper.width = cropperWidth; newCropper.height = cropperY; newCropper.x = x; break; case 2: newCropper.width = cropperX; newCropper.height = cropperY; break; default: break; } this.renderCropper(newCropper); }, handleLineMove: function handleLineMove(_ref3) { var x = _ref3.x, y = _ref3.y; var cropper = this.cropper, newCropper = {}, _this$getNewCropper2 = this.getNewCropper(x, y, cropper), cropperWidth = _this$getNewCropper2.cropperWidth, cropperHeight = _this$getNewCropper2.cropperHeight, cropperX = _this$getNewCropper2.cropperX, cropperY = _this$getNewCropper2.cropperY; switch (this.index) { case 3: newCropper.width = cropperWidth; newCropper.x = x; // 限制 break; case 0: newCropper.height = cropperHeight; newCropper.y = y; // 限制 break; case 1: newCropper.width = cropperX; break; case 2: // y 不会动 newCropper.height = cropperY; break; default: break; } this.renderCropper(newCropper); }, renderCropper: function renderCropper(newCropper) { if (newCropper.width <= this.nookSide * 4 || newCropper.height <= this.nookSide * 4) { return; } this.cropper = _objectSpread({}, this.cropper, newCropper); this.draw(); }, handleImageMove: function handleImageMove(_ref4) { var x = _ref4.x, y = _ref4.y; var s = this.startPoint; this.image.x = x - s.offsetX; this.image.y = y - s.offsetY; // 限制图片移动的范围 // 三种情况 // 1. 图片 // 2. 框 // 3. 圆圈 /** let cropper = this.cropper const shape = this.shape || 'rect' if (shape == 'imgage') { // this.options cropper = { x: 0, y: 0, width: this.options.width, height: this.options.height } } else if (shape === 'arc') { cropper = { x: this.arc.x - this.arc.r, y: this.arc.y - this.arc.r, width: this.arc.r * 2, height: this.arc.r * 2 } } const left = cropper.x, right = cropper.x + cropper.width, bottom = cropper.y + cropper.height, top = cropper.y this.image.x = this.limit(x - s.offsetX, right - this.image.width, left) this.image.y = this.limit(y - s.offsetY, bottom - this.image.height, top) */ this.draw(); }, // handleCropperMove({ x, y }) { // const { width, height } = this.options; // const s = this.startPoint; // const oX = s.offsetX; // const oY = s.offsetY; // const maxX = width - this.cropper.width; // const maxY = height - this.cropper.height; // let currentX = x - oX, // currentY = y - oY; // // 判断边界 // this.cropper.x = this.limit(currentX, 0, maxX) // this.cropper.y = this.limit(currentY, 0, maxY) // this.draw() // }, getCoordinateByEvent: function getCoordinateByEvent(e) { var rect = e.target.getBoundingClientRect(), touch = e.touches[0], _this$options4 = this.options, width = _this$options4.width, height = _this$options4.height, coordinate = { x: this.limit(touch.clientX - rect.left, 2, width - 2), y: this.limit(touch.clientY - rect.top, 2, height - 2) // move 到边 }; return coordinate; }, // https://blog.csdn.net/qq_42014697/article/details/80728463 两指缩放 handleEnd: function handleEnd() { if (this.changeDrawAction) { if (this.drawAction) { this.drawAction = false; this.bgOpacity = 0; this.draw(); } else { this.drawAction = true; this.bgOpacity = .4; this.draw(); } this.changeDrawAction = false; return; } if (this.drawAction && this.pointLine.length > 0) { this.drawPoint.x = this.drawPoint.x - this.image.x; this.drawPoint.y = this.drawPoint.y - this.image.y; this.pointLine.push(this.drawPoint); // 点的 宽度 var pointObj = { pointLine: this.pointLine, scale: this.scale, lineWidth: 3, color: this.color || this.averageColor, rotateAngle: this.rotateAngle }; this.pointList.push(pointObj); this.pointLine = []; } }, handleStart: function handleStart(e) { // alert(1) e.preventDefault(); // 双指 if (e.touches.length > 1) { this.startTouches = e.touches; this.startPoint.type = null; return; } // 单指 起点 this.drawPoint = this.getCoordinateByEvent(e); this.startPoint = this.getPointByCoordinate(this.drawPoint); // -- 画画 if (this.drawAction) { this.pointLine = []; this.ctx.beginPath(); this.ctx.moveTo(this.drawPoint.x, this.drawPoint.y); } }, handleMove: function handleMove(e) { e.preventDefault(); var touches = e.touches; var image = this.image; if (touches.length > 1 && !this.drawAction) { var startTouches = this.startTouches; var k; // 最终的缩放系数 var scale = this.scale; // const offset = e.deltaY / 800; k = this.getDistance(touches[0], touches[1]) / this.getDistance(startTouches[0], startTouches[1]); // k = k < 1 ? k / 10 : k * 10 k = k < 1 ? 1 / (1 + k / 80) : 1 + Math.abs(k) / 160; k = k * scale; this.scale = this.limit(k, 0.02, 1.07); var width = image.clientWidth * this.scale, height = image.clientHeight * this.scale; this.image.x += (image.width - width) / 2; this.image.y += (image.height - height) / 2; this.image.width = width; this.image.height = height; this.draw(); return; } if (this.drawAction) { // 划线 // 先实现划线 // 画 相对于 画布 // 存 相对于 画布 // 屡一下 -- 这个东西 想对于画布 在图片在哪里 ===== 根据图片的位置还原 画布位置 var drawPoint = this.drawPoint; var current = this.getCoordinateByEvent(e); var ctx = this.ctx; var color = this.color || this.averageColor; ctx.lineTo(current.x, current.y); ctx.lineWidth = 3; ctx.strokeStyle = color; ctx.lineCap = 'round'; ctx.stroke(); drawPoint.x = drawPoint.x - image.x; drawPoint.y = drawPoint.y - image.y; this.pointLine.push(drawPoint); this.drawPoint = current; return; } // 这是干啥的--画=>图片和 线 var type = this.startPoint ? this.startPoint.type : null; if (type && this.getCoordinateByEvent(e)) { this[type](this.getCoordinateByEvent(e)); } }, checkRegion: function checkRegion(x, y, target) { return x > target.x && x < target.x + target.width && y > target.y && y < target.y + target.height; }, checkArc: function checkArc(x, y) { var ctx = this.ctx; ctx.beginPath(); // ctx.strokeStyle = 'red'//'transparent' ctx.lineWidth = this.nookSide / 0.7; ctx.arc(this.arc.x, this.arc.y, this.arc.r + ctx.lineWidth, 0, Math.PI * 2); // ctx.stroke() return ctx.isPointInPath(x * this.pixelRatio, y * this.pixelRatio) && this.getDistance({ pageX: x, pageY: y }, { pageX: this.arc.x, pageY: this.arc.y }) > this.arc.r - ctx.lineWidth / 2; }, getPointByCoordinate: function getPointByCoordinate(_ref5) { var _this2 = this; var x = _ref5.x, y = _ref5.y; var image = this.image, shape = this.shape || 'rect'; var t = {}; var index = 0; // 旋转 if (this.paintBrush && this.checkRegion(x, y, this.paintBrush)) { this.changeDrawAction = true; return; } else if (this.revokeBar && this.checkRegion(x, y, this.revokeBar)) { // t.type = 'draw' // 接下来 是draw 动作 // 再次进来 保存 起始点 坐标 this.pointList.pop(); this.draw(); return; } else if (this.touchBar && this.checkRegion(x, y, this.touchBar)) { // 旋转后的角度 每次 this.rotateAngle = (this.rotateAngle + this.angle) % 360; this.draw(); return; } else if (this.drawAction) { return; } else if (shape === 'arc' && this.checkArc(x, y)) { t.type = 'handleArcMove'; } // 四个角移动 else if (shape !== 'arc' && this.points.some(function (point, i) { index = i; return _this2.checkRegion(x, y, point); })) { t.type = 'handlePointMove'; this.index = index; } // 四根线移动 else if (shape === 'rect' && this.lines.some(function (line, i) { index = i; return _this2.checkRegion(x, y, line); })) { t.type = 'handleLineMove'; this.index = index; } // else if ( // cropper && // x > cropper.x && // x < cropper.x + cropper.width && // y > cropper.y && // y < cropper.y + cropper.height // ) { // t.offsetX = x - cropper.x; // t.offsetY = y - cropper.y; // t.type = 'handleCropperMove' // } // 图片移动 else if (this.checkRegion(x, y, image)) { t.offsetX = x - image.x; t.offsetY = y - image.y; t.type = 'handleImageMove'; } return t; }, // 求两点之间的 距离 getDistance: function getDistance(p1, p2) { var x = p2.pageX - p1.pageX, y = p2.pageY - p1.pageY; return Math.sqrt(x * x + y * y); }, limit: function limit(value, min, max) { if (value < min) { return min; } if (value > max) { return max; } return value; }, getImage: function getImage() { var _this3 = this; var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Base64'; var mimeType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'image/jpeg'; var quality = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; if (this.noImage) return; var shape = this.shape || 'rect'; var cropper = this.cropper; if (shape == 'imgage') { cropper = this.image; } else if (shape === 'arc') { // 圆形必须 2倍才好 cropper = { x: this.arc.x - this.arc.r, y: this.arc.y - this.arc.r, width: this.arc.r * 2, height: this.arc.r * 2 }; } var image = this.image, pixelRatio = this.pixelRatio, types = { Base64: function Base64(canvas, mimeType, resolve) { resolve(canvas.toDataURL(mimeType)); }, Blob: function Blob(canvas, mimeType, resolve) { canvas.toBlob(function (blob) { resolve(blob); }, mimeType); } }, w = cropper.width * quality, h = cropper.height * quality, // 变量申请 canvasDom = document.createElement('canvas'), cCtx = canvasDom.getContext('2d'); // if (!this.canvas) { // this.canvas = document.createElement('canvas') // this.cCtx = this.canvas.getContext('2d') // const { mountNode } = this.$refs // mountNode.appendChild(this.canvas) // } // const cCtx = this.cCtx canvasDom.width = w * pixelRatio; canvasDom.height = h * pixelRatio; cCtx.scale(pixelRatio, pixelRatio); cCtx.clearRect(0, 0, w, h); var rotateAngle = this.rotateAngle; if (shape === 'arc') { var radius = w / 2; cCtx.beginPath(); // 圆心是当前正方形的(画布) 中间 cCtx.arc(radius, radius, radius, 0, Math.PI * 2, false); cCtx.clip(); } // 圆形 只有 2 倍 缩放 数据是正确的 // 旋转图片 这个是 主图旋转 /也是canvas 上 img this.canvasRotate('img', cCtx, image.element, rotateAngle, (image.x - cropper.x) * quality, (image.y - cropper.y) * quality, image.width * quality, image.height * quality); // 在整个图片上 写写画画 再要框了--- 就是说框是---img this.drawPointFn(cCtx, quality, cropper); return new Promise(function (resolve, reject) { if (!types[type]) { reject('type = Blob || Base64'); return; } var _this3$position = _slicedToArray(_this3.position, 4), _this3$position$ = _this3$position[0], left = _this3$position$ === void 0 ? '50%' : _this3$position$, _this3$position$2 = _this3$position[1], top = _this3$position$2 === void 0 ? '50%' : _this3$position$2, _this3$position$3 = _this3$position[2], size = _this3$position$3 === void 0 ? 1 : _this3$position$3, _this3$position$4 = _this3$position[3], angle = _this3$position$4 === void 0 ? 0 : _this3$position$4; if (_this3.imageWatermark) { var watermarkImg = new Image(); watermarkImg.src = _this3.getFileSrc(_this3.imageWatermark); watermarkImg.crossOrigin = 'anonymous'; watermarkImg.onload = function () { // 等到图片加载进来之后 var width = watermarkImg.width * size * quality / 100, height = watermarkImg.height * size * quality / 100, imgX = (w - width) * parseInt(left) / 100, imgY = (h - height) * parseInt(top) / 100; _this3.canvasRotate('img', cCtx, watermarkImg, angle, imgX, imgY, width, height); types[type](canvasDom, mimeType, resolve); }; return; } if (_this3.textWatermark) { var height = _this3.limit(size, 12, 100); cCtx.font = height + 'px Georgia'; var text = _this3.textWatermark, width = cCtx.measureText(text).width, textX = (w - width * 1.031) * parseInt(left) / 100, textY = (h + height * 0.72) * parseInt(top) / 100; // 变量申请 cCtx.fillStyle = _this3.color || _this3.averageColor; // console.log(this.cCtx.fillStyle) if (cCtx.fillStyle === '#ffffff') { cCtx.fillStyle = '#000'; } _this3.canvasRotate('text', cCtx, text, angle, textX, textY, width, height); types[type](canvasDom, mimeType, resolve); return; } types[type](canvasDom, mimeType, resolve); }); }, canvasRotate: function canvasRotate(type, ctx, target, angle, x, y, width, height) { ctx.save(); var halfHeight = height / 2, halfWidth = width / 2; ctx.translate(x + halfWidth, y + halfHeight); ctx.rotate(Math.PI / 180 * angle); if (type === 'img') { ctx.drawImage(target, -halfWidth, -halfHeight, width, height); } else if (type === 'text') { ctx.fillText(target, -halfWidth, -halfHeight); } ctx.restore(); }, changeImage: function changeImage(imgAddress) { if (this.noImage) return; this.averageColor = null; if (imgAddress) { this.createImage(imgAddress); return; } this.inputHandle(); }, // 工具 getPixelRatio: function getPixelRatio(context) { var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; return (window.devicePixelRatio || 1) / backingStore; }, // isWeiXin() { // const ua = window.navigator.userAgent.toLowerCase(); // if (ua.match(/MicroMessenger/i) == 'micromessenger') { // return true // } else { // return false // } // }, uploadImg: function uploadImg(e) { this.createImage(e.target.files[0]); this.noImage = false; }, getFileSrc: function getFileSrc(src) { if (Object.prototype.toString.call(src) === '[object File]') { src = window.URL.createObjectURL(src); } return src; }, createImage: function createImage(imgfile) { var _this4 = this; var img = new Image(); // url , imgsrc, 文件 三种情况 img.crossOrigin = 'anonymous'; img.src = this.getFileSrc(imgfile); img.onload = function () { // 等到图片加载进来之后 getImageDirection(img).then(function (res) { if (res === 1) { _this4.init(img); _this4.$emit('imgLoaded'); return; } // 只有钉钉 会莫名其妙 卡顿- => 把图片 画在canvas 背景上了 _this4.init(img); _this4.init(correctImage(img, res)); _this4.$emit('imgLoaded'); }).catch(function (err) { // eslint-disable-next-line console.error(err); }); }; }, inputHandle: function inputHandle() { document.getElementById('file-input').click(); }, getImageColor: function getImageColor(data) { var r = 0, g = 0, b = 0; // 取所有像素的平均值 var num = this.limit(data.length, 1, 20); for (var row = 0; row < num; row++) { for (var col = 0; col < num; col++) { r += data[(num * row + col) * 4]; g += data[(num * row + col) * 4 + 1]; b += data[(num * row + col) * 4 + 2]; } } // 求取平均值 r /= num * num; g /= num * num; b /= num * num; // 将最终的值取整 r = Math.round(r); g = Math.round(g); b = Math.round(b); return "rgba(".concat(255 - r, ", ").concat(255 - g, ", ").concat(255 - b, ", 1)"); } }, mounted: function mounted() { // 解决 字体模糊 var mountNode = this.$refs.mountNode; var clientWidth = mountNode.clientWidth, clientHeight = mountNode.clientHeight; // p可以优化 this.options = { width: clientWidth, height: clientHeight // canvas dom }; var canvasDom = document.createElement('canvas'); canvasDom.style.width = clientWidth + 'px'; canvasDom.style.height = clientHeight + 'px'; // 小方格背景 canvasDom.style.backgroundColor = '#fff'; canvasDom.style.backgroundImage = 'linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%), linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%)'; canvasDom.style.backgroundSize = '29px 29px'; canvasDom.style.backgroundPosition = '0 0, 15px 15px'; mountNode.appendChild(canvasDom); // this.options = canvasDom.getBoundingClientRect() this.ctx = canvasDom.getContext('2d'); var pixelRatio = this.pixelRatio = this.getPixelRatio(this.ctx); canvasDom.width = clientWidth * pixelRatio; canvasDom.height = clientHeight * pixelRatio; this.ctx.scale(pixelRatio, pixelRatio); // console.log(this.$slots.initial[0].data.attrs.src) if (this.defaultImgUrl || this.$slots.defaultImgUrl) { var src = this.defaultImgUrl ? this.defaultImgUrl : this.$slots.defaultImgUrl[0].data.attrs.src; this.createImage(src); this.noImage = false; } this.$emit('input', { getImage: this.getImage, changeImage: this.changeImage }); } }); // CONCATENATED MODULE: ./packages/cropblg.vue?vue&type=script&lang=js& /* harmony default export */ var packages_cropblgvue_type_script_lang_js_ = (cropblgvue_type_script_lang_js_); // CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js /* globals __VUE_SSR_CONTEXT__ */ // IMPORTANT: Do NOT use ES2015 features in this file (except for modules). // This module is a runtime utility for cleaner component module output and will // be included in the final webpack user bundle. function normalizeComponent ( scriptExports, render,