diff --git a/package.json b/package.json index ff687ad..d47dd8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-image-markup", - "version": "2.0.9", + "version": "3.0.0", "description": "vue-image-markup will provide you to edit uploaded image easily and save it.", "main": "src/Editor.vue", "repository": { diff --git a/src/Editor.vue b/src/Editor.vue index 6791e86..565921e 100644 --- a/src/Editor.vue +++ b/src/Editor.vue @@ -131,6 +131,7 @@ radius: (params && params.radius) ? params.radius : 20, strokeUniform: (params && params.strokeUniform) ? params.strokeUniform : true, noScaleCache: (params && params.noScaleCache) ? params.noScaleCache : false, + strokeDashArray: (params && params.strokeDashArray) ? params.strokeDashArray : false }; this.customCircle(type, this.params); break; @@ -149,10 +150,50 @@ opacity: (params && params.opacity) ? params.opacity : 1, strokeUniform: (params && params.strokeUniform) ? params.strokeUniform : true, noScaleCache: (params && params.noScaleCache) ? params.noScaleCache : false, + strokeDashArray: (params && params.strokeDashArray) ? params.strokeDashArray : false, + borderRadius: (params && params.borderRadius) ? params.borderRadius : 0 + }; + this.customRect(type, this.params); + break; + case "comment": + this.cancelCroppingImage(); + this.currentActiveTool = type; + this.params = { + fill: (params && params.fill) ? params.fill : 'transparent', + stroke: (params && params.stroke) ? params.stroke : this.color, + strokeWidth: (params && params.strokeWidth) ? params.strokeWidth : this.strokeWidth, + angle: (params && params.angle) ? params.angle : 0, + width: (params && params.width) ? params.width : null, + height: (params && params.height) ? params.height : null, + top: (params && params.top) ? params.top : 0, + left: (params && params.left) ? params.left : 0, + opacity: (params && params.opacity) ? params.opacity : 1, + strokeUniform: (params && params.strokeUniform) ? params.strokeUniform : true, + noScaleCache: (params && params.noScaleCache) ? params.noScaleCache : false, + strokeDashArray: (params && params.strokeDashArray) ? params.strokeDashArray : false, + borderRadius: (params && params.borderRadius) ? params.borderRadius : 0 + }; + this.customRect(type, this.params); + break; + case "line": + this.cancelCroppingImage(); + this.currentActiveTool = type; + this.params = { + fill: (params && params.fill) ? params.fill : 'transparent', + stroke: (params && params.stroke) ? params.stroke : this.color, + strokeWidth: (params && params.strokeWidth) ? params.strokeWidth : this.strokeWidth, + angle: (params && params.angle) ? params.angle : 0, + width: (params && params.width) ? params.width : null, + height: (params && params.height) ? params.height : null, + top: (params && params.top) ? params.top : 0, + left: (params && params.left) ? params.left : 0, + opacity: (params && params.opacity) ? params.opacity : 1, + strokeUniform: (params && params.strokeUniform) ? params.strokeUniform : true, + noScaleCache: (params && params.noScaleCache) ? params.noScaleCache : false, + strokeDashArray: (params && params.strokeDashArray) ? params.strokeDashArray : false }; this.customRect(type, this.params); break; - case 'selectMode': this.currentActiveTool = type; this.drag(); @@ -166,6 +207,7 @@ strokeWidth: (params && params.strokeWidth) ? params.strokeWidth : this.strokeWidth, strokeUniform: (params && params.strokeUniform) ? params.strokeUniform : true, noScaleCache: (params && params.noScaleCache) ? params.noScaleCache : false, + strokeDashArray: (params && params.strokeDashArray) ? params.strokeDashArray : false }; this.drawArrow(this.params); break; diff --git a/src/assets/js/arrow.js b/src/assets/js/arrow.js index 8e8472c..b1c1ef5 100644 --- a/src/assets/js/arrow.js +++ b/src/assets/js/arrow.js @@ -1,19 +1,22 @@ import {fabric} from 'fabric'; import CanvasHistory from "./canvasHistory"; + +let params; fabric.LineArrow = fabric.util.createClass(fabric.Line, { type: 'lineArrow', - - initialize: function(element, options) { + initialize: function (element, options) { + params = options; options || (options = {}); this.callSuper('initialize', element, options); }, - toObject: function() { + toObject: function () { return fabric.util.object.extend(this.callSuper('toObject')); }, - _render: function(ctx) { + _render: function (ctx) { + console.log('render', params); this.ctx = ctx; this.callSuper('_render', ctx); let p = this.calcLinePoints(); @@ -25,19 +28,19 @@ fabric.LineArrow = fabric.util.createClass(fabric.Line, { xDiff = -this.x2 + this.x1; yDiff = -this.y2 + this.y1; angle = Math.atan2(yDiff, xDiff); - this.drawArrow(angle, p.x1, p.y1,this.heads[1]); + this.drawArrow(angle, p.x1, p.y1, this.heads[1]); }, - drawArrow: function(angle, xPos, yPos, head) { + drawArrow: function (angle, xPos, yPos, head) { this.ctx.save(); - if (head) { this.ctx.translate(xPos, yPos); this.ctx.rotate(angle); this.ctx.beginPath(); this.ctx.moveTo(10, 0); - this.ctx.lineTo(-15, 15); - this.ctx.lineTo(-15, -15); + let width = params.strokeWidth < 2 ? params.strokeWidth * 6 : params.strokeWidth * 2; + this.ctx.lineTo(-(width - 2), width); + this.ctx.lineTo(-(width - 2), -width); this.ctx.closePath(); } @@ -48,12 +51,11 @@ fabric.LineArrow = fabric.util.createClass(fabric.Line, { }); - -fabric.LineArrow.fromObject = function(object, callback) { +fabric.LineArrow.fromObject = function (object, callback) { callback && callback(new fabric.LineArrow([object.x1, object.y1, object.x2, object.y2], object)); }; fabric.LineArrow.async = true; -fabric.LineArrow.fromObject = function(object, callback) { +fabric.LineArrow.fromObject = function (object, callback) { callback && callback(new fabric.LineArrow([object.x1, object.y1, object.x2, object.y2], object)); }; fabric.LineArrow.async = true; @@ -63,38 +65,41 @@ export default (function () { let color; let lineWidth; let fillArrow; + let strokeDashArray; let properties; - function Arrow(canvas,draggable = false,params) { - if(!draggable){ + function Arrow(canvas, draggable = false, params) { + + if (!draggable) { drag = false; return Arrow; } - if(color && color !== params.stroke){ + if (color && color !== params.stroke) { color = params.stroke; - new Arrow(canvas,draggable,params) + new Arrow(canvas, draggable, params) return Arrow; } properties = params; - if(properties){ + if (properties) { fillArrow = params.fill; color = params.stroke; lineWidth = params.strokeWidth; + strokeDashArray = params.strokeDashArray; } this.canvas = canvas; this.className = 'Arrow'; this.isDrawing = false; this.bindEvents(); drag = draggable; - + } Arrow.prototype.bindEvents = function () { let inst = this; - document.onkeydown=(e)=>{ - if(e.which === 46 || e.keycode === 46){ + document.onkeydown = (e) => { + if (e.which === 46 || e.keycode === 46) { inst.canvas.getActiveObjects().forEach((obj) => { inst.canvas.remove(obj) }); @@ -102,39 +107,39 @@ export default (function () { inst.canvas.renderAll() }; inst.selectable = true; - - inst.canvas.off('mouse:down'); - inst.canvas.on('mouse:down', function (o) { - inst.onMouseDown(o); - }); - inst.canvas.on('mouse:move', function (o) { - inst.onMouseMove(o); - }); - inst.canvas.on('mouse:up', function (o) { - inst.onMouseUp(o); - - }); - inst.canvas.on('object:moving', function () { - inst.disable(); - }); + + inst.canvas.off('mouse:down'); + inst.canvas.on('mouse:down', function (o) { + inst.onMouseDown(o); + }); + inst.canvas.on('mouse:move', function (o) { + inst.onMouseMove(o); + }); + inst.canvas.on('mouse:up', function (o) { + inst.onMouseUp(o); + + }); + inst.canvas.on('object:moving', function () { + inst.disable(); + }); }; Arrow.prototype.onMouseUp = function () { let inst = this; if (!inst.isEnable()) { - return; + return; } - if(drag){ + if (drag) { this.line.set({ dirty: true, objectCaching: true - }); - if(inst.canvas.getActiveObject()){ + }); + if (inst.canvas.getActiveObject()) { inst.canvas.getActiveObject().hasControls = false; inst.canvas.getActiveObject().hasBorders = false; inst.canvas.getActiveObject().lockMovementX = true; inst.canvas.getActiveObject().lockMovementY = true; inst.canvas.getActiveObject().lockUniScaling = true; - } + } inst.canvas.renderAll(); let saveHistory = new CanvasHistory(inst.canvas) } @@ -159,20 +164,20 @@ export default (function () { Arrow.prototype.onMouseDown = function (o) { let inst = this; - if(!drag){ - if( inst.canvas.getActiveObject()){ + if (!drag) { + if (inst.canvas.getActiveObject()) { inst.canvas.getActiveObject().hasControls = true; inst.canvas.getActiveObject().hasBorders = true; inst.canvas.getActiveObject().lockMovementX = false; inst.canvas.getActiveObject().lockMovementY = false; - inst.canvas.getActiveObject().lockUniScaling = false; + inst.canvas.getActiveObject().lockUniScaling = false; inst.canvas.renderAll(); } inst.disable(); return; } inst.enable(); - if(inst.canvas.getActiveObject()){ + if (inst.canvas.getActiveObject()) { inst.canvas.getActiveObject().hasControls = false; inst.canvas.getActiveObject().hasBorders = false; inst.canvas.getActiveObject().lockMovementX = true; @@ -184,6 +189,7 @@ export default (function () { let points = [pointer.x, pointer.y, pointer.x, pointer.y]; this.line = new fabric.LineArrow(points, { strokeWidth: lineWidth, + strokeDashArray: strokeDashArray, fill: color, stroke: color, originX: 'center', @@ -192,9 +198,8 @@ export default (function () { hasControls: false, objectCaching: false, perPixelTargetFind: true, - heads: [1, 0] + heads: [1, 0], }); - inst.canvas.add(this.line).setActiveObject(this.line); }; diff --git a/src/assets/js/shape.js b/src/assets/js/shape.js index 249ef11..b708bb0 100644 --- a/src/assets/js/shape.js +++ b/src/assets/js/shape.js @@ -1,36 +1,43 @@ import {fabric} from 'fabric'; import CanvasHistory from "./canvasHistory"; + export default (function () { let drag; let shape; let color; - let lineWidth,fillCircle,angle; + let lineWidth, fillCircle, angle; + let strokeDashArray; + let borderRadius; let properties; - function Shape(canvas,draggable = false,type,params) { - if(!draggable){ + let isDown = false; + + function Shape(canvas, draggable = false, type, params) { + if (!draggable) { drag = false; return Shape; } - if(color && color !== params.stroke){ + if (color && color !== params.stroke) { color = params.stroke; shape = type; - new Shape(canvas,true,shape,params) + new Shape(canvas, true, shape, params) return Shape; } - if((shape && shape !== type)){ + if ((shape && shape !== type)) { shape = type; drag = true; - new Shape(canvas,true,shape,params) + new Shape(canvas, true, shape, params) return Shape; } properties = params; - if(properties){ + if (properties) { fillCircle = properties.fill; color = properties.stroke; lineWidth = properties.strokeWidth; angle = properties.angle; + strokeDashArray = properties.strokeDashArray; + borderRadius = properties.borderRadius; } - this.canvas = canvas; + this.canvas = canvas; this.className = 'Shape'; this.isDrawing = false; this.origX = 0; @@ -44,8 +51,8 @@ export default (function () { Shape.prototype.bindEvents = function () { let inst = this; - document.onkeydown=(e)=>{ - if(e.which === 46 || e.keycode === 46){ + document.onkeydown = (e) => { + if (e.which === 46 || e.keycode === 46) { inst.canvas.getActiveObjects().forEach((obj) => { inst.canvas.remove(obj) }); @@ -53,39 +60,39 @@ export default (function () { inst.canvas.renderAll() }; inst.selectable = true; - inst.canvas.off('mouse:down'); - - inst.canvas.on('mouse:down', function (o) { - inst.onMouseDown(o); - }); - inst.canvas.on('mouse:move', function (o) { - inst.onMouseMove(o); - }); - inst.canvas.on('mouse:up', function (o) { - inst.onMouseUp(o); - }); - inst.canvas.on('object:moving', function () { - inst.disable(); - }); - + inst.canvas.off('mouse:down'); + + inst.canvas.on('mouse:down', function (o) { + inst.onMouseDown(o); + }); + inst.canvas.on('mouse:move', function (o) { + inst.onMouseMove(o); + }); + inst.canvas.on('mouse:up', function (o) { + inst.onMouseUp(o); + }); + inst.canvas.on('object:moving', function () { + inst.disable(); + }); + }; Shape.prototype.onMouseUp = function () { - + isDown = false; let inst = this; if (!inst.isEnable()) { return; } - if(drag){ - inst.canvas.getObjects().forEach(function(object,index,array) { - if (index === (array.length -1)) { - if(inst.canvas.getActiveObject() && inst.canvas.getActiveObject()._objects && inst.canvas.getActiveObject()._objects.length > 1){ + if (drag) { + inst.canvas.getObjects().forEach(function (object, index, array) { + if (index === (array.length - 1)) { + if (inst.canvas.getActiveObject() && inst.canvas.getActiveObject()._objects && inst.canvas.getActiveObject()._objects.length > 1) { inst.canvas.setActiveObject(object); } } }); - if(inst.canvas.getActiveObject()){ + if (inst.canvas.getActiveObject()) { inst.canvas.getActiveObject().hasControls = false; inst.canvas.getActiveObject().hasBorders = false; inst.canvas.getActiveObject().lockMovementX = true; @@ -106,15 +113,15 @@ export default (function () { inst.canvas.selection = false; let pointer = inst.canvas.getPointer(o.e); let activeObj; - if(inst.canvas.getActiveObject()){ + if (inst.canvas.getActiveObject()) { activeObj = inst.canvas.getActiveObject(); + console.log(color, fillCircle); activeObj.stroke = color; activeObj.strokeWidth = lineWidth; activeObj.fill = fillCircle; activeObj.noScaleCache = false; activeObj.strokeUniform = true; } - if (this.origX > pointer.x) { activeObj.set({ left: Math.abs(pointer.x) @@ -125,19 +132,25 @@ export default (function () { top: Math.abs(pointer.y) }); } - if(shape == "rect"){ - activeObj.set({ - width: Math.abs(this.origX - pointer.x) - }); + if (shape == "rect") { activeObj.set({ - height: Math.abs(this.origY - pointer.y) + width: Math.abs(this.origX - pointer.x), + height: Math.abs(this.origY - pointer.y), }); } - if(shape == "circle"){ + if (shape == "comment") { activeObj.set({ - rx: Math.abs(this.origX - pointer.x) / 2 + scaleX: Math.abs(this.origY - pointer.y) / 50, + scaleY: Math.abs(this.origY - pointer.y) / 50 }); + } + if (shape == "line") { + if (!isDown) return; + activeObj.set({x2: pointer.x, y2: pointer.y}); + } + if (shape == "circle") { activeObj.set({ + rx: Math.abs(this.origX - pointer.x) / 2, ry: Math.abs(this.origY - pointer.y) / 2 }); } @@ -146,13 +159,13 @@ export default (function () { }; Shape.prototype.onMouseDown = function (o) { - - let inst = this; - if(!drag){ - - if( inst.canvas.getActiveObject()){ - inst.canvas.getActiveObject().hasControls = true; - inst.canvas.getActiveObject().hasBorders = true; + isDown = true; + let inst = this; + if (!drag) { + + if (inst.canvas.getActiveObject()) { + inst.canvas.getActiveObject().hasControls = shape === 'line' ? false : true; + inst.canvas.getActiveObject().hasBorders = shape === 'line' ? false : true; inst.canvas.getActiveObject().lockMovementX = false; inst.canvas.getActiveObject().lockMovementY = false; inst.canvas.getActiveObject().lockUniScaling = false; @@ -161,47 +174,88 @@ export default (function () { inst.disable(); return; } - inst.enable(); - - if(inst.canvas.getActiveObject()){ - inst.canvas.getActiveObject().hasControls = false; - inst.canvas.getActiveObject().hasBorders = false; - inst.canvas.getActiveObject().lockMovementX = true; - inst.canvas.getActiveObject().lockMovementY = true; - inst.canvas.getActiveObject().lockUniScaling = true; - inst.canvas.renderAll(); - } - let pointer = inst.canvas.getPointer(o.e); - this.origX = pointer.x; - this.origY = pointer.y; - if(shape === "rect"){ - let rect = new fabric.Rect({ - left: this.origX, - top: this.origY, - originX: 'left', - originY: 'top', - width: pointer.x - this.origX, - height: pointer.y - this.origY, - angle: angle, - fill: fillCircle, - transparentCorners: false, - stroke: color, - strokeWidth: lineWidth - }); - inst.canvas.add(rect).setActiveObject(rect); - } - if(shape === "circle"){ - let circle = new fabric.Ellipse({ - top: this.origY, - left: this.origX, - rx: 0, - ry: 0, - transparentCorners: false, - hasBorders: true, - hasControls: true, - }); - inst.canvas.add(circle).setActiveObject(circle); - } + inst.enable(); + + if (inst.canvas.getActiveObject()) { + inst.canvas.getActiveObject().hasControls = false; + inst.canvas.getActiveObject().hasBorders = false; + inst.canvas.getActiveObject().lockMovementX = true; + inst.canvas.getActiveObject().lockMovementY = true; + inst.canvas.getActiveObject().lockUniScaling = true; + inst.canvas.renderAll(); + } + let pointer = inst.canvas.getPointer(o.e); + this.origX = pointer.x; + this.origY = pointer.y; + console.log('dash array', borderRadius); + if (shape === "rect") { + let rect = new fabric.Rect({ + left: this.origX, + top: this.origY, + originX: 'left', + originY: 'top', + width: pointer.x - this.origX, + height: pointer.y - this.origY, + angle: angle, + fill: fillCircle, + transparentCorners: false, + stroke: color, + strokeWidth: lineWidth, + strokeDashArray: strokeDashArray, + rx: borderRadius, + ry: borderRadius, + }); + inst.canvas.add(rect).setActiveObject(rect); + } + if (shape === 'comment') { + let comment = new fabric.Path("M44 48L34 58V48H12C5.373 48 0 42.627 0 36V12C0 5.373 5.373 0 12 0h40c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12h-8z", { + left: this.origX, + top: this.origY, + originX: 'left', + originY: 'top', + scaleX: 0, + scaleY: 0, + angle: angle, + fill: fillCircle, + transparentCorners: false, + stroke: color, + strokeWidth: lineWidth, + strokeDashArray: strokeDashArray, + rx: borderRadius, + ry: borderRadius, + }); + inst.canvas.add(comment).setActiveObject(comment); + } + if (shape === "circle") { + let circle = new fabric.Ellipse({ + top: this.origY, + left: this.origX, + rx: 0, + ry: 0, + transparentCorners: false, + hasBorders: true, + hasControls: true, + fill: fillCircle, + stroke: color, + strokeWidth: lineWidth, + strokeDashArray: strokeDashArray + }); + inst.canvas.add(circle).setActiveObject(circle); + } + if (shape === "line") { + var points = [pointer.x, pointer.y, pointer.x, pointer.y]; + let line = new fabric.Line(points, { + strokeDashArray: strokeDashArray, + stroke: fillCircle, + originX: 'center', + originY: 'center', + angle: angle, + transparentCorners: false, + hasBorders: false, + hasControls: false + }); + inst.canvas.add(line).setActiveObject(line); + } }; Shape.prototype.isEnable = function () { return this.isDrawing; diff --git a/src/assets/js/text.js b/src/assets/js/text.js index 70cb711..cd059f4 100644 --- a/src/assets/js/text.js +++ b/src/assets/js/text.js @@ -23,7 +23,7 @@ export default (function () { textFontStyle = params.fontStyle; textFontWeight = params.fontWeight; customText = params.placeholder; - if (canvas.getActiveObject()) { + if (canvas.getActiveObject() && canvas.getActiveObject().hasOwnProperty('text')) { canvas.getActiveObject().set({ fill: textColor, fontFamily: textFontFamily,