"vue js image crop"
Bootstrap 3.0.0 Snippet by evarevirus

<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <!------ Include the above in your HEAD tag ----------> <!DOCTYPE html><html lang='en' class=''> <head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/eanka/pen/WRmOQY?depth=everything&order=popularity&page=61&q=vue&show_forks=false" /> <style class="cp-pen-styles"></style></head><body> <div id="app"> <h1>Vue.js Image Cropper Component</h1> <vue-cropper></vue-cropper> </div> <script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js'></script> <script >Vue.component('vueCropper', { template: '<div><input type="file" @change="selectFile"/> <div v-if="cropping" ref="cropperdiv" :style="cropperDivStyle"><canvas ref="canvas" :width="canvasWidth" :height="canvasHeight" @mousemove="moveMouse" @mousedown="startDrag" @mouseup="stopDrag" @dragover="stopDrag"></canvas></div><img v-bind:src="croppedImage" :style="roundCorners"/></div>', data: function () { return { cropperDivWidth: '100%', //this can be anything passed to css width cropperDivHeight: false, //this should be either false or number (in pixels) cropperDivMaxHeight: 600, //this should be either false or number (in pixels). Must be number if cropperDivHeight is false cropping: false, image: false, imageWidth: 0, imageHeight: 0, canvasWidth: 300, canvasHeight: 150, ctx: false, mainStroke: 'rgba(255,255,255,0.99)', //color of the line around cropping area. Set to rgba(0,0,0,0) for no line lineDash: [5,3], //dash style of line around cropping area, set to empty array for solid line ([]) overlayStyle: 'rgba(0,0,0,0.4)', //overlay around cropped area fillStyle: 'rgba(0,0,0,0.7)', //corner handles style, fill strokeStyle: 'rgba(255,255,255,0.7)', //corner handles style, stroke hoverFillStyle: 'rgba(255,255,255,0.4)', //corner handles style, fill on hover hoverStrokeStyle: 'white', //corner handles style, stroke on hover x: 20, y: 20, w: 200, h: 100, //initial cropping values, x, y, width, height markerSize: 20, deltaX: 0, deltaY: 0, dragged: false, aspectRatio: 2, //aspect ratio of the cropping area. false for non locked ratio, or number for locked croppedWidth: 400, //desired width of cropped image croppedHeight: 200, //desired height of cropped image. If width/height is not equal to aspect ratio, final image will be distorted minWidth: 10, //minimal cropping area width minHeight: 10, //minimal cropping area height croppedImage: false, circle: false //for cropping round images. If set to true, it will change aspect ratio of cropping area to 1. CroppedWidth and croppedHeight should be equal, otherwise strange effects will occur }; }, computed: { cropperDivStyle: function () { return {width: this.cropperDivWidth, height: this.cropperHeight+'px', textAlign: 'center'}; }, cropperHeight: function () { return this.cropperDivHeight ? this.cropperDivHeight : this.cropperDivMaxHeight; }, cropperWidth: function () { return this.cropping && this.$refs.cropperdiv.offsetWidth; }, cropperDivRatio: function () { return this.cropperWidth/this.cropperHeight; }, imageRatio: function () { return this.imageWidth/this.imageHeight; }, markers: function () { return { nw: {x: this.x - this.markerSize/2, y: this.y - this.markerSize/2}, ne: {x: this.x + this.w - this.markerSize/2, y: this.y - this.markerSize/2}, sw: {x: this.x - this.markerSize/2, y: this.y + this.h - this.markerSize/2}, se: {x: this.x + this.w - this.markerSize/2, y: this.y + this.h - this.markerSize/2} }; }, cw: function () { return this.croppedWidth || this.w; }, ch: function () { return this.croppedHeight || this.h; }, roundCorners: function () { if (this.circle) {return {borderRadius: '100%'};} else return false; } }, methods: { selectFile: function (evt) { var file = evt.currentTarget.files[0]; var reader = new FileReader(); var cropper = this; reader.onload = function (evt) { cropper.cropping = true; if (cropper.circle) {cropper.aspectRatio = 1; cropper.h = cropper.w;} var image = new Image(); image.src = evt.target.result; image.onload = function() { cropper.image = image; cropper.drawing = true; cropper.imageWidth = image.width; cropper.imageHeight = image.height; cropper.canvasWidth = cropper.cropperWidth; cropper.canvasHeight = cropper.cropperHeight; if (cropper.imageRatio < cropper.cropperDivRatio) { cropper.canvasWidth = cropper.canvasHeight * cropper.imageRatio; } if (cropper.imageRatio > cropper.cropperDivRatio) { cropper.canvasHeight = cropper.canvasWidth / cropper.imageRatio; } Vue.nextTick(function () { var canvas = cropper.$refs.canvas; cropper.ctx = canvas.getContext('2d'); cropper.ctx.drawImage(cropper.image, 0, 0, cropper.canvasWidth, cropper.canvasHeight); }); }; }; reader.readAsDataURL(file); }, moveMouse: function (event) { if (event === undefined) return false; var doc = document.documentElement; var scrollLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0); var scrollTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); var x = event.clientX - event.target.offsetLeft + scrollLeft; var y = event.clientY - event.target.offsetTop + scrollTop; var ctx = this.ctx; //draw the image ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); ctx.drawImage(this.image, 0, 0, this.canvasWidth, this.canvasHeight); //update coords if (this.dragged) this.updateCoords(x,y); //draw crop area and handles this.drawSelection(ctx,x,y); //crop image var scaleX = this.imageWidth / this.canvasWidth; var scaleY = this.imageHeight / this.canvasHeight; resultCanvas = document.createElement('canvas'); resultCanvas.width = this.cw; resultCanvas.height = this.ch; resultCanvas.getContext('2d').drawImage(this.image, this.x * scaleX, this.y * scaleY, this.w * scaleX, this.h * scaleY, 0, 0, this.cw, this.ch); this.croppedImage = resultCanvas.toDataURL(); }, drawSelection: function (ctx,x,y) { this.drawOverlay(ctx); this.$refs.canvas.style.cursor = 'default'; ctx.beginPath(); if (!this.circle) {ctx.rect(this.x, this.y, this.w, this.h);} else { ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, 0, 2 * Math.PI); } if (ctx.isPointInPath(x, y)) { this.$refs.canvas.style.cursor = 'move'; } ctx.setLineDash(this.lineDash); ctx.strokeStyle = this.mainStroke; ctx.stroke(); ctx.setLineDash([]); for (var p in this.markers) {if (window.CP.shouldStopExecution(1)){break;} var rectangle = this.markers[p]; ctx.beginPath(); ctx.rect(rectangle.x, rectangle.y, this.markerSize, this.markerSize); ctx.fillStyle = this.fillStyle; ctx.strokeStyle = this.strokeStyle; if (ctx.isPointInPath(x, y)) { ctx.fillStyle = this.hoverFillStyle; ctx.strokeStyle = this.hoverStrokeStyle; this.$refs.canvas.style.cursor = p+'-resize'; } ctx.fill(); ctx.stroke(); } window.CP.exitedLoop(1); }, drawOverlay: function (ctx) { ctx.fillStyle = this.overlayStyle; ctx.fillRect(0,0,this.canvasWidth, this.y); ctx.fillRect(0,this.y, this.x, this.h); ctx.fillRect(this.x+this.w, this.y, this.canvasWidth - (this.x+this.w), this.h); ctx.fillRect(0, this.y+this.h, this.canvasWidth, this.canvasHeight - (this.y+this.h)); if (this.circle) { ctx.beginPath(); ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, Math.PI, 1.5 * Math.PI); ctx.lineTo(this.x, this.y); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, 1.5 * Math.PI, 2 * Math.PI); ctx.lineTo(this.x + this.w, this.y); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, 0, 0.5 * Math.PI); ctx.lineTo(this.x + this.w, this.y + this.h); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, 0.5 * Math.PI, Math.PI); ctx.lineTo(this.x, this.y + this.h); ctx.closePath(); ctx.fill(); } }, startDrag: function (event) { var doc = document.documentElement; var scrollLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0); var scrollTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); var x = event.clientX - event.target.offsetLeft + scrollLeft; var y = event.clientY - event.target.offsetTop + scrollTop; var ctx = this.ctx; for (var p in this.markers) {if (window.CP.shouldStopExecution(2)){break;} var rectangle = this.markers[p]; ctx.beginPath(); ctx.rect(rectangle.x, rectangle.y, this.markerSize, this.markerSize); if (ctx.isPointInPath(x, y)) { this.dragged = p; this.deltaX = x - rectangle.x; this.deltaY = y - rectangle.y; return;} } window.CP.exitedLoop(2); ctx.beginPath(); if (!this.circle) {ctx.rect(this.x, this.y, this.w, this.h);} else { ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, 0, 2 * Math.PI); } if (ctx.isPointInPath(x, y)) { this.dragged = 'all'; this.deltaX = x - this.x; this.deltaY = y - this.y; return;} }, stopDrag: function () { this.dragged = false; this.deltaX = 0; this.deltaY = 0; }, updateCoords: function (x,y) { var newX, newY, newW, newH; if (this.dragged == 'all') { newX = x - this.deltaX; newY = y - this.deltaY; newW = this.w; newH = this.h; } else { var ox = this.dragged[1] == 'w' ? 'e' : 'w'; var oy = this.dragged[0] == 'n' ? 's' : 'n'; var oppositeIdx = oy+ox; if (ox == 'e') { newX = x - this.deltaX + this.markerSize / 2; newW = this.markers[oppositeIdx].x - newX + this.markerSize / 2; } else { newX = this.x; newW = x - this.deltaX - this.markers[oppositeIdx].x; } if (oy == 's') { newY = y - this.deltaY + this.markerSize / 2; newH = this.markers[oppositeIdx].y - newY + this.markerSize / 2; } else { newY = this.y; newH = y - this.deltaY - this.markers[oppositeIdx].y; } } if (this.aspectRatio) {newH = newW / this.aspectRatio;} if (newX < 0) newX = 0; if (newY < 0) newY = 0; if (newX + newW > this.canvasWidth) { newW = this.canvasWidth - newX; if (this.aspectRatio) {newH = newW / this.aspectRatio;} } if (newY + newH > this.canvasHeight) { newH = this.canvasHeight - newY; if (this.aspectRatio) {newW = newH * this.aspectRatio;} } if (newW < this.minWidth) {newW = this.minWidth; newH = newW / this.aspectRatio;} if (newH < this.minHeight) {newH = this.minHeight; newW = newH * this.aspectRatio;} this.x = newX; this.y = newY; this.w = newW; this.h = newH; } } }); var app = new Vue({ el: '#app', }); //# sourceURL=pen.js </script> </body></html>

Related: See More


Questions / Comments: