diff --git a/.gitignore b/.gitignore index e1105ca..14c0c24 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea node_modules -.history \ No newline at end of file +.history +yarn.lock diff --git a/README.md b/README.md index d236754..8d938b8 100644 --- a/README.md +++ b/README.md @@ -61,10 +61,12 @@ this.$refs.editor.set('text') ``` Object key | Default Value | Description ------------- | ------------- | ------------- -fill | `black` | color -fontFamily | `Arial` | font-family -fontSize | `32` | font-size -placeholder | `Add Text` | default text placeholder when the text will be added +fill | `black` | color +fontFamily | `Arial` | font-family +fontSize | `32` | font-size +fontWeight | `100` | font-weight(`100`,`200`,`300`,`400`,`500`,`600`,`700`,`bold`,`normal`) +fontStyle | `normal` | font-style(`normal`,`italic`,`oblique`) +placeholder | `Add Text` | default text placeholder when the text will be added or you can customize your editor text mode styles by overwriting default values. ```javascript let textModeOptions = { fill: 'red', fontFamily: 'Verdana',fontSize: 16, placeholder: 'Type something'} @@ -228,4 +230,4 @@ mounted:{ ## Credits - [Lilit Simonyan](https://github.com/lilitsimonyan98) -- [Lionix Team](https://github.com/lionix-team) \ No newline at end of file +- [Lionix Team](https://github.com/lionix-team) diff --git a/package.json b/package.json index 7596f66..d2f3a87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-image-markup", - "version": "2.0.7", + "version": "2.0.8", "description": "vue-image-markup will provide you to edit uploaded image easily and save it.", "main": "src/Editor.vue", "repository": { @@ -59,4 +59,4 @@ "dependencies": { "fabric": "^3.4.0" } -} \ No newline at end of file +} diff --git a/src/Editor.vue b/src/Editor.vue index e5b2dae..6791e86 100644 --- a/src/Editor.vue +++ b/src/Editor.vue @@ -1,6 +1,7 @@ @@ -10,12 +11,13 @@ import Text from './assets/js/text'; import Arrow from './assets/js/arrow'; import CropImage from './assets/js/crop'; - import CanvasHistory from './assets/js/canvasHistory'; + import CanvasHistory from './assets/js/canvasHistory'; + export default { name: 'Editor', props: ['canvasWidth', 'canvasHeight'], - data() { - return{ + data() { + return { canvas: null, pointerX: null, pointerY: null, @@ -40,22 +42,22 @@ }, mounted() { this.canvas = new fabric.Canvas('c'); - this.canvas.setDimensions({width: this.canvasWidth, height: this.canvasHeight}); + this.canvas.setDimensions({width: this.canvasWidth, height: this.canvasHeight}); this.canvas.backgroundColor = "#fff"; - new CanvasHistory(this.canvas); + new CanvasHistory(this.canvas); }, - methods: { - setBackgroundImage(imageUrl){ - let img = new Image(); - this.toDataUrl(imageUrl, (dataUri) => { - img.src = dataUri; - let inst = this; - img.onload = function () { + methods: { + setBackgroundImage(imageUrl) { + let img = new Image(); + this.toDataUrl(imageUrl, (dataUri) => { + img.src = dataUri; + let inst = this; + img.onload = function () { if (inst.canvas.width <= img.width || inst.canvas.height <= img.height) { let canvasAspect = inst.canvas.width / inst.canvas.height; let imgAspect = img.width / img.height; - let top,left,scaleFactor; - if (canvasAspect >= imgAspect) { + let top, left, scaleFactor; + if (canvasAspect >= imgAspect) { scaleFactor = inst.canvas.height / img.height top = 0; left = -((img.width * scaleFactor) - inst.canvas.width) / 2; @@ -71,7 +73,7 @@ scaleY: scaleFactor }); inst.canvas.renderAll() - }else{ + } else { let center = inst.canvas.getCenter(); inst.canvas.setBackgroundImage(dataUri, inst.canvas.renderAll.bind(inst.canvas), { top: center.top, @@ -81,16 +83,16 @@ }); inst.canvas.renderAll() } - } - }); + } + }); }, toDataUrl(url, callback) { - var xhr = new XMLHttpRequest(); + let xhr = new XMLHttpRequest(); xhr.onload = function () { - var reader = new FileReader(); + let reader = new FileReader(); reader.onloadend = () => { callback(reader.result); - } + }; reader.readAsDataURL(xhr.response); }; xhr.open('GET', url); @@ -101,25 +103,23 @@ this.canvas.clear(); this.cancelCroppingImage() }, - changeColor(colorProperty) { - this.color = colorProperty; - this.set(this.currentActiveTool) - }, - set(type, params) { + set(type, params) { switch (type) { - case "text": + case "text": this.currentActiveTool = type; this.params = { fill: (params && params.fill) ? params.fill : this.color, fontFamily: (params && params.fontFamily) ? params.fontFamily : 'Arial', fontSize: (params && params.fontSize) ? params.fontSize : this.fontSize, + fontStyle: (params && params.fontStyle) ? params.fontStyle : this.fontStyle, + fontWeight: (params && params.fontWeight) ? params.fontWeight : this.fontWeight, placeholder: (params && params.placeholder) ? params.placeholder : 'Add Text', }; this.addText(this.params); break; - case "circle": - this.cancelCroppingImage(); + case "circle": + this.cancelCroppingImage(); this.currentActiveTool = type; this.params = { fill: (params && params.fill) ? params.fill : 'transparent', @@ -134,8 +134,8 @@ }; this.customCircle(type, this.params); break; - case "rect": - this.cancelCroppingImage(); + case "rect": + this.cancelCroppingImage(); this.currentActiveTool = type; this.params = { fill: (params && params.fill) ? params.fill : 'transparent', @@ -153,12 +153,12 @@ this.customRect(type, this.params); break; - case 'selectMode': + case 'selectMode': this.currentActiveTool = type; this.drag(); break; - case 'arrow': + case 'arrow': this.currentActiveTool = type; this.params = { fill: (params && params.fill) ? params.fill : 'transparent', @@ -169,7 +169,7 @@ }; this.drawArrow(this.params); break; - case 'freeDrawing': + case 'freeDrawing': this.currentActiveTool = type; this.params = { stroke: (params && params.stroke) ? params.stroke : this.color, @@ -193,10 +193,10 @@ cornerColor: (params && params.cornerColor) ? params.cornerColor : "#000", cornerStyle: (params && params.cornerStyle) ? params.cornerStyle : "circle", }; - this.currentActiveMethod = this.cropImage; - this.drag(); - this.croppedImage = true; - new CropImage(this.canvas,true,false,false,this.params); + this.currentActiveMethod = this.cropImage; + this.drag(); + this.croppedImage = true; + new CropImage(this.canvas, true, false, false, this.params); break; default: } @@ -213,11 +213,11 @@ let imgObj = new Image(); imgObj.src = event.target.result; imgObj.onload = function () { - let image = new fabric.Image(imgObj); - if (inst.canvas.width <= image.width || inst.canvas.height <= image.height) { + let image = new fabric.Image(imgObj); + if (inst.canvas.width <= image.width || inst.canvas.height <= image.height) { let canvasAspect = inst.canvas.width / inst.canvas.height; let imgAspect = image.width / image.height; - let top,left,scaleFactor; + let top, left, scaleFactor; if (canvasAspect >= imgAspect) { scaleFactor = inst.canvas.height / image.height top = 0; @@ -225,7 +225,7 @@ } else { scaleFactor = inst.canvas.width / image.width; left = 0; - top = -((image.height * scaleFactor) - inst.canvas.height) / 2; + top = -((image.height * scaleFactor) - inst.canvas.height) / 2; } inst.canvas.setBackgroundImage(image, inst.canvas.renderAll.bind(inst.canvas), { top: top, @@ -233,10 +233,10 @@ scaleX: scaleFactor, scaleY: scaleFactor }); - let croppedImage = { json: inst.canvas.toJSON(), croppedImage: inst.canvas.toDataURL()}; - let saveCanvas = new CanvasHistory(inst.canvas,croppedImage) + let croppedImage = {json: inst.canvas.toJSON(), croppedImage: inst.canvas.toDataURL()}; + new CanvasHistory(inst.canvas, croppedImage) inst.canvas.renderAll(); - }else{ + } else { let center = inst.canvas.getCenter(); inst.canvas.setBackgroundImage(image, inst.canvas.renderAll.bind(inst.canvas), { top: center.top, @@ -244,12 +244,12 @@ originX: 'center', originY: 'center' }); - let croppedImage = { json: inst.canvas.toJSON(), croppedImage: inst.canvas.toDataURL()}; - let saveCanvas = new CanvasHistory(inst.canvas,croppedImage) + let croppedImage = {json: inst.canvas.toJSON(), croppedImage: inst.canvas.toDataURL()}; + new CanvasHistory(inst.canvas, croppedImage); inst.canvas.renderAll(); } } - } + }; reader.readAsDataURL(e.target.files[0]); }, customCircle(type, params) { @@ -260,7 +260,7 @@ this.canvas.isDrawingMode = false; if (!params.disableCircleEditing) { this.createCircle = true; - new Shape(this.canvas, this.createCircle, type, params); + new Shape(this.canvas, this.createCircle, type, params); } else { this.drawCircle(params); } @@ -284,21 +284,21 @@ this.createArrow = true; new Arrow(this.canvas, this.createArrow, params); }, - cancelCroppingImage(){ + cancelCroppingImage() { this.croppedImage = false; - new CropImage(this.canvas,false,false,true) + new CropImage(this.canvas, false, false, true) }, - applyCropping(){ - new CropImage(this.canvas,true,true); - this.cancelCroppingImage(); + applyCropping() { + new CropImage(this.canvas, true, true); + this.cancelCroppingImage(); }, drag() { this.currentActiveMethod = this.drag; - this.canvas.isDrawingMode = false; + this.canvas.isDrawingMode = false; this.canvas.forEachObject(object => { - object.selectable = true; - object.evented = true; - }); + object.selectable = true; + object.evented = true; + }); if (this.createArrow) { this.createArrow = false; new Arrow(this.canvas, false); @@ -311,9 +311,9 @@ if (this.createText) { this.createText = false; new Text(this.canvas, false); - } + } this.cancelCroppingImage(); - + }, addText(params) { this.currentActiveMethod = this.addText; @@ -321,40 +321,39 @@ this.createText = true; new Text(this.canvas, this.createText, params); }, - undo() { + undo() { if (this.canvas.getActiveObject()) { - this.canvas.discardActiveObject().renderAll() - } - this.drag(); - this.history = new CanvasHistory(); + this.canvas.discardActiveObject().renderAll() + } + this.drag(); + this.history = new CanvasHistory(); if (this.history.length) { - - this.objects.push(this.history.pop()) - if(this.history[this.history.length - 1] && this.history[this.history.length - 1].croppedImage){ - - JSON.parse(JSON.stringify(this.history[this.history.length - 1])) - this.canvas.loadFromJSON(this.history[this.history.length - 1].json) - this.setBackgroundImage(this.history[this.history.length - 1].croppedImage) - } - else{ - this.canvas.loadFromJSON(this.history[this.history.length - 1]) - this.canvas.renderAll(); - } - } + + this.objects.push(this.history.pop()) + if (this.history[this.history.length - 1] && this.history[this.history.length - 1].croppedImage) { + + JSON.parse(JSON.stringify(this.history[this.history.length - 1])) + this.canvas.loadFromJSON(this.history[this.history.length - 1].json) + this.setBackgroundImage(this.history[this.history.length - 1].croppedImage) + } else { + this.canvas.loadFromJSON(this.history[this.history.length - 1]) + this.canvas.renderAll(); + } + } }, - redo() { - this.drag(); - if (this.objects.length > 0) { - if(this.objects[this.objects.length - 1] && this.objects[this.objects.length - 1].croppedImage){ - JSON.parse(JSON.stringify(this.objects[this.objects.length - 1])) - this.canvas.loadFromJSON(this.objects[this.objects.length - 1].json) - this.setBackgroundImage(this.objects[this.objects.length - 1].croppedImage); - new CanvasHistory(false,false,this.objects.pop()) - }else{ - this.canvas.loadFromJSON(this.objects[this.objects.length - 1]) - new CanvasHistory(false,false,this.objects.pop()) - } - } + redo() { + this.drag(); + if (this.objects.length > 0) { + if (this.objects[this.objects.length - 1] && this.objects[this.objects.length - 1].croppedImage) { + JSON.parse(JSON.stringify(this.objects[this.objects.length - 1])) + this.canvas.loadFromJSON(this.objects[this.objects.length - 1].json) + this.setBackgroundImage(this.objects[this.objects.length - 1].croppedImage); + new CanvasHistory(false, false, this.objects.pop()) + } else { + this.canvas.loadFromJSON(this.objects[this.objects.length - 1]) + new CanvasHistory(false, false, this.objects.pop()) + } + } }, drawing(params) { this.currentActiveMethod = this.drawing; @@ -368,11 +367,11 @@ color: params.stroke, }); let inst = this; - this.canvas.on("object:added",function(){ - if(inst.canvas.isDrawingMode){ + this.canvas.on("object:added", function () { + if (inst.canvas.isDrawingMode) { new CanvasHistory(inst.canvas) } - }) + }); this.canvas.renderAll(); }, @@ -390,7 +389,6 @@ opacity: params.opacity, left: params.left, top: params.top, - // strokeUniform: params.strokeUniform, noScaleCache: params.noScaleCache }); this.canvas.add(this.rectangle); @@ -407,7 +405,6 @@ stroke: params.stroke, fill: params.fill, borderColor: 'yellow', - // strokeUniform: params.strokeUniform, noScaleCache: params.noScaleCache }); this.canvas.add(this.circle); diff --git a/src/assets/js/text.js b/src/assets/js/text.js index fbc3da8..8724c07 100644 --- a/src/assets/js/text.js +++ b/src/assets/js/text.js @@ -1,28 +1,31 @@ import {fabric} from "fabric"; import CanvasHistory from "./canvasHistory.js"; + export default (function () { let activeObject = false; - let drag,textColor,textFontFamily,textFontSize,customText,color; - function Text(canvas,draggable = false,params) { + let drag, textColor, textFontFamily, textFontSize, customText, color, textFontStyle, textFontWeight; + + function Text(canvas, draggable = false, params) { this.canvas = canvas; - this.className = "text"; this.isDrawing = false; this.origX = 0; this.origY = 0; - this.selectedFont = 32; this.bindEvents(); drag = draggable; - if(color && color !== params.fill){ + if (color && color !== params.fill) { color = params.fill; return Text; } - if(params){ + if (params) { textColor = params.fill; textFontFamily = params.fontFamily; textFontSize = params.fontSize; + textFontStyle = params.fontSize; + textFontWeight = params.fontWeight; customText = params.placeholder; } - }; + } + Text.prototype.bindEvents = function () { let inst = this; inst.selectable = true; @@ -36,7 +39,7 @@ export default (function () { inst.canvas.on("mouse:up", function (o) { inst.onMouseUp(o); }); - Text.prototype.onMouseUp = function () { + Text.prototype.onMouseUp = function () { return Text; }; Text.prototype.onMouseMove = function () { @@ -44,34 +47,31 @@ export default (function () { if (!inst.isEnable()) { return; } - if(inst.canvas.getActiveObject()){ - activeObject = true; - } - else{ - activeObject = false; - } + activeObject = inst.canvas.getActiveObject(); inst.canvas.renderAll(); }; Text.prototype.onMouseDown = function (o) { - let inst = this; - if(drag){ - inst.enable(); - if(inst.canvas.getActiveObject() && !inst.canvas.getActiveObject().text){ + let inst = this; + if (drag) { + inst.enable(); + if (inst.canvas.getActiveObject() && !inst.canvas.getActiveObject().text) { inst.canvas.getActiveObject().selectable = false; inst.canvas.getActiveObject().evented = false; - } - if((!inst.canvas.getActiveObject() && !activeObject) || (inst.canvas.getActiveObject() && !inst.canvas.getActiveObject().text)){ + } + if ((!inst.canvas.getActiveObject() && !activeObject) || (inst.canvas.getActiveObject() && !inst.canvas.getActiveObject().text)) { let pointer = inst.canvas.getPointer(o.e); this.origX = pointer.x; this.origY = pointer.y; let text = new fabric.IText(customText, { - fill:textColor, + fill: textColor, fontFamily: textFontFamily, left: this.origX, top: this.origY, fontSize: textFontSize, - hasBorders:false, - hasControls:false + fontStyle: textFontStyle, + fontWeight: textFontWeight, + hasBorders: false, + hasControls: false }); text.selectionStart = 0; @@ -80,9 +80,9 @@ export default (function () { text.enterEditing(); text.hiddenTextarea.focus(); inst.canvas.requestRenderAll(); - let saveHistory = new CanvasHistory(inst.canvas) - } - if(inst.canvas.getActiveObject() && activeObject && inst.canvas.getActiveObject().hiddenTextarea){ + new CanvasHistory(inst.canvas) + } + if (inst.canvas.getActiveObject() && activeObject && inst.canvas.getActiveObject().hiddenTextarea) { inst.canvas.getActiveObject().hasControls = true; inst.canvas.getActiveObject().hasBorders = true; inst.canvas.getActiveObject().lockMovementX = true;