我试图用该线将画布上的两个图形连接起来,并且该线将固定在图形上,因此图形在画布上移动的位置相应的箭头也会移动。
它的工作方式与我期望的相同,但是在我通过调用方法"rasterizeJSON()"
生成JSON时却给了我错误,它在应用JSON.stringify(objectName);
时没有将对象更改为字符串< / p>
错误-TypeError:“ instance [methodName]不是函数” _toObjectwebpack-
export class WorkFlowEditorComponent {
@ViewChild('launch') launch: ElementRef;
REC_WIDTH = 60;
REC_HEIGHT = 30;
TRI_WIDTH = 10;
TRI_HEIGHT = 10;
disX;
disY;
_self = this;
start;
private canvas: any;
private props: any = {
canvasFill: '#ffffff',
canvasImage: '',
id: null,
name: null,
opacity: null,
fill: null,
fontSize: null,
lineHeight: null,
charSpacing: null,
fontWeight: null,
fontStyle: null,
textAlign: null,
fontFamily: null,
TextDecoration: ''
};
private textString: string;
private url: string = '';
private size: any = {
width: 1000,
height: 400
};
private json: any;
private globalEditor: boolean = false;
private textEditor: boolean = false;
private imageEditor: boolean = false;
private figureEditor: boolean = false;
private selected: any;
constructor() { }
ngOnInit() {
// ['object:moving'].forEach(this.addChildMoveLine);
//setup front side canvas
this.canvas = new fabric.Canvas('canvas', {
hoverCursor: 'pointer',
selection: true,
selectionBorderColor: 'blue'
});
var HideControls = {
'tl': true,
'tr': false,
'bl': true,
'br': true,
'ml': true,
'mt': true,
'mr': true,
'mb': true,
'mtr': true
};
this.canvas.on({
'object:moving': (e) => {
this.addChildMoveLine(e);
//console.log(e);
//this.addDeleteBtn(e.target.oCoords.tr.x, e.target.oCoords.tr.y);
},
'object:modified': (e) => {
//console.log("object modified");
this.addDeleteBtn(e.target.oCoords.tr.x, e.target.oCoords.tr.y);
},
'object:selected': (e) => {
// console.log("inside canvas selected");
this.addChildMoveLine(e);
this.addDeleteBtn(e.target.oCoords.tr.x, e.target.oCoords.tr.y);
let selectedObject = e.target;
console.log("printing selected object" + selectedObject);
this.selected = selectedObject
selectedObject.hasRotatingPoint = true;
selectedObject.transparentCorners = false;
// selectedObject.cornerColor = 'rgba(255, 87, 34, 0.7)';
this.resetPanels();
if (selectedObject.type !== 'group' && selectedObject) {
this.getId();
this.getOpacity();
switch (selectedObject.type) {
case 'rect':
case 'circle':
case 'triangle':
this.figureEditor = true;
this.getFill();
break;
case 'i-text':
this.textEditor = true;
this.getLineHeight();
this.getCharSpacing();
this.getBold();
this.getFontStyle();
this.getFill();
this.getTextDecoration();
this.getTextAlign();
this.getFontFamily();
break;
case 'image':
console.log('image');
break;
}
}
},
'selection:cleared': (e) => {
this.selected = null;
this.resetPanels();
}
});
this.canvas.setWidth(this.size.width);
this.canvas.setHeight(this.size.height);
// get references to the html canvas element & its context
// this.canvas.on('mouse:down', (e) => {
// let canvasElement: any = document.getElementById('canvas');
// console.log(canvasElement)
// });
}
//method to connect arrow from one shape to another
addChild() {
if (this.canvas.getActiveObject() == null) {
console.log("inside add child if");
return "getactiveobject is null (add child)";
}
this.canvas.addChild = {
start: this.canvas.getActiveObject()
};
//for when addChild is clicked twice
this.canvas.off({
'object:selected': (e) => {
this.addChildLine(e)
console.log("move off" + e);
//this.addDeleteBtn(e.target.oCoords.tr.x, e.target.oCoords.tr.y);
},
})
this.canvas.on({
'object:selected': (e) => {
this.addChildLine(e)
console.log("move line");
},
}
);
}
calcArrowAngle(x1, y1, x2, y2) {
var angle = 0,
x, y;
console.log("arrow angle", x1, y1, x2, y2);
x = (x2 - x1);
y = (y2 - y1);
if (x === 0) {
angle = (y === 0) ? 0 : (y > 0) ? Math.PI / 2 : Math.PI * 3 / 2;
} else if (y === 0) {
angle = (x > 0) ? 0 : Math.PI;
} else {
angle = (x < 0) ? Math.atan(y / x) + Math.PI : (y < 0) ? Math.atan(y / x) + (2 * Math.PI) : Math.atan(y / x);
}
console.log("PI", Math.PI);
return (angle * 180 / Math.PI + 90);
}
addChildLine(options) {
this.canvas.off({
'object:selected': (e) => {
this.addChildLine(e)
console.log("move line in off");
//this.addDeleteBtn(e.target.oCoords.tr.x, e.target.oCoords.tr.y);
},
}
)
var fromObject = this.canvas.addChild.start;
console.log(fromObject);
var toObject = options.target;
console.log(toObject);
var from = fromObject.getCenterPoint();
// console.log(from)
var to = toObject.getCenterPoint();
var fromX = from.x;
var fromY = from.y;
var toX = to.x;
var toY = to.y;
// var disX = REC_WIDTH/2 + TRI_WIDTH/2;
// var disY = REC_HEIGHT/2 + TRI_HEIGHT/2;
//var distanceX, distanceY;
//calibrateLine(fromX, fromY, toX, toY);
var calibrateX = this.REC_WIDTH / 2 + this.TRI_WIDTH / 2;
var calibrateY = this.REC_HEIGHT / 2 + this.TRI_HEIGHT / 2
//storing and calculate x and y axis of the imagrd to be connected
var distanceX, distanceY;
if (fromX < toX) {
distanceX = toX - fromX;
} else {
distanceX = fromX - toX;
}
if (fromY < toY) {
distanceY = toY - fromY;
} else {
distanceY = fromY - toY;
}
if (distanceX > distanceY) {
if (fromX < toX) {
toX -= calibrateX;
} else {
toX += calibrateX;
}
} else {
if (fromY < toY) {
toY -= calibrateY;
} else {
toY += calibrateY;
}
}
var line = new fabric.Line([fromX, fromY, toX, toY], {
fill: 'red',
stroke: 'red',
strokeWidth: 1,
selectable: false,
fromObject: fromObject,
toObject: toObject,
});
// leftover code that we might need but probably not
/*
centerX = (from.x + to.x)/2;
centerY = (from.y + to.y)/2;
deltaX = line.left - centerX;
deltaY = line.top - centerY;
*/
console.log(line.x1)
line.triangle = new fabric.Triangle({
left: line.x2,
top: line.y2,
angle: this.calcArrowAngle(line.x1, line.y1, line.x2, line.y2),
originX: 'center',
originY: 'center',
hasBorders: false,
hasControls: false,
lockScalingX: true,
lockScalingY: true,
lockRotation: true,
pointType: 'arrow_start',
width: this.TRI_WIDTH,
height: this.TRI_HEIGHT,
fill: 'red',
selectable: false,
});
var Group = new fabric.Group([line, line.triangle]);
// canvas.add(Group);
var objs = [line, line.triangle];
var add = new fabric.Group(objs);
// this.extend(add, this.randomId());
this.canvas.add(line, line.triangle);
//this.canvas.add(add);
//this.selectItemAfterAdded(add);
//this.canvas.add(Group);
// so that the line is behind the connected shapes
line.sendToBack();
// add a reference to the line to each object
//console.log(fromObject.addChild);
fromObject.addChild = fromObject.addChild || {};
fromObject.addChild.lines = fromObject.addChild.lines || [];
console.log(fromObject.addChild.lines);
fromObject.addChild.lines.push(line);
toObject.addChild = toObject.addChild || {};
//console.log(toObject.addChild);
toObject.addChild.lines = toObject.addChild.lines || [];
console.log(toObject.addChild.lines);
toObject.addChild.lines.push(line);
// to remove line references when the line gets removed
line.addChildRemove = function () {
fromObject.addChild.lines.forEach(function (e, i, arr) {
if (e === line)
arr.splice(i, 1);
});
};
// undefined instead of delete since we are anyway going to do this many times
this.canvas.addChild = undefined;
}
addChildMoveLine(e) {
var self = this;
//console.log("inside child move line");
// this.canvas.on({
// 'object:moving': (e) => {
// console.log("move");
// console.log(e.target);
// this.canvas.on(event, function(options) {
var object = e.target;
// console.log("addChildMoveLine");
// udpate lines (if any)
if (object.addChild && object.addChild.lines) {
object.addChild.lines.forEach(function (line) {
console.log(line.fromObject.getCenterPoint());
var fcenter = line.fromObject.getCenterPoint(),
fx = fcenter.x,
fy = fcenter.y,
tcenter = line.toObject.getCenterPoint(),
tx = tcenter.x,
ty = tcenter.y,
xdis = self.REC_WIDTH / 2 + self.TRI_WIDTH / 2,
ydis = self.REC_HEIGHT / 2 + self.TRI_HEIGHT / 2,
horizontal = Math.abs(tx - line.x1) > Math.abs(ty - line.y1)
line.set({
'x1': fx,
'y1': fy,
'x2': tx + xdis * (horizontal ? (tx < line.x1 ? 1 : -1) : 0),
'y2': ty + ydis * (horizontal ? 0 : (ty < line.y1 ? 1 : -1)),
});
//this.calcArrowAngle(line.x1, line.y1, line.x2, line.y2)
line.triangle.set({
'left': line.x2, 'top': line.y2,
'angle': self.calcArrowAngle(line.x1, line.y1, line.x2, line.y2)
});
});
}
this.canvas.renderAll();
}
calibrateLine(fromX, fromY, toX, toY) {
var distanceX = 0;
var distanceY = 0;
// if (fromX < toX) {
// distanceX = toX - fromX;
// } else {
// distanceX = fromX - toX;
// }
// if (fromY < toY) {
// distanceY = toY - fromY;
// } else {
// distanceY = fromY - toY;
// }
if (distanceX > distanceY) {
if (fromX < toX) {
toX -= this.disX;
} else {
toX += this.disX;
}
} else {
if (fromY < toY) {
toY -= this.disY;
} else {
toY += this.disY;
}
}
}
addDeleteBtn(x, y) {
$(".deleteBtn").remove();
var btnLeft = x - 10;
var btnTop = y - 10;
// <button data-toggle="tooltip" data-placement="bottom" title="Delete element" type="button" class="btn btn-outline-danger"
// [disabled]="!selected" (click)="removeSelected();">
// </button>
var deleteBtn = ' <i class="fa fa-trash deleteBtn" aria-hidden="true" style="position:absolute;top:' + btnTop + 'px;left:' + btnLeft + 'px;cursor:pointer;width:20px;height:20px; " onclick=alert("hrllo")></i>';
$(".canvas-container").append(deleteBtn);
}
/*------------------------Block elements------------------------*/
//Block "Size"
changeSize(event: any) {
console.log("changeSize")
this.canvas.setWidth(this.size.width);
this.canvas.setHeight(this.size.height);
}
//Block "Add text"
addText() {
let textString = this.textString;
let text = new fabric.IText(textString, {
left: 10,
top: 10,
fontFamily: 'helvetica',
angle: 0,
fill: '#000000',
scaleX: 0.5,
scaleY: 0.5,
fontWeight: '',
hasRotatingPoint: true
});
this.extend(text, this.randomId());
this.canvas.add(text);
this.selectItemAfterAdded(text);
this.textString = '';
}
//Block "Add images"
getImgPolaroid(event: any, src: any) {
console.log("inside polaroid method");
let el = event.target;
console.log(src);
fabric.Image.fromURL(src, (image) => {
image.set({
left: 10,
top: 10,
angle: 0,
padding: 10,
cornersize: 10,
//hasRotatingPoint: true,
peloas: 12,
hasControls: false
});
image.setWidth(50);
image.setHeight(50);
this.extend(image, this.randomId());
this.canvas.add(image);
this.selectItemAfterAdded(image);
});
}
//Block "Upload Image"
addImageOnCanvas(url) {
if (url) {
fabric.Image.fromURL(url, (image) => {
image.set({
left: 10,
top: 10,
angle: 0,
padding: 10,
cornersize: 10,
hasRotatingPoint: true
});
image.setWidth(200);
image.setHeight(200);
this.extend(image, this.randomId());
this.canvas.add(image);
this.selectItemAfterAdded(image);
});
}
}
readUrl(event) {
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = (event) => {
this.url = event.target['result'];
}
reader.readAsDataURL(event.target.files[0]);
}
}
removeWhite(url) {
this.url = '';
};
//Block "Add figure"
addFigure(figure) {
let add: any;
switch (figure) {
case 'rectangle':
add = new fabric.Rect({
width: 60, height: 30, left: 100, top: 100, angle: 0,
fill: '#ffffff',
stroke: 'black',
strokeWidth: 1,
hasControls: false
});
break;
case 'square':
add = new fabric.Rect({
width: 50, height: 50, left: 10, top: 10, angle: 0,
fill: '#ffffff',
stroke: 'black',
strokeWidth: 1,
hasControls: false
});
break;
case 'triangle':
add = new fabric.Rect({
left: 100, top: 100, width: 20, height: 20, angle: 45,
fill: '#ffffff',
stroke: 'black',
strokeWidth: 1,
hasControls: false
});
break;
case 'circle':
add = new fabric.Circle({
radius: 20, left: 10, top: 10,
fill: '#ffffff',
stroke: 'black',
strokeWidth: 1,
hasControls: false
});
break;
case 'line':
var triangle = new fabric.Triangle({
width: 10,
height: 15,
fill: 'red',
left: 235,
top: 65,
angle: 90
});
var line = new fabric.Line([50, 100, 200, 100], {
left: 75,
top: 70,
stroke: 'red'
});
var objs = [line, triangle];
add = new fabric.Group(objs);
break;
}
this.extend(add, this.randomId());
this.canvas.add(add);
this.selectItemAfterAdded(add);
}
/*Canvas*/
cleanSelect() {
this.canvas.deactivateAllWithDispatch().renderAll();
}
selectItemAfterAdded(obj) {
this.canvas.deactivateAllWithDispatch().renderAll();
this.canvas.setActiveObject(obj);
}
setCanvasFill() {
if (!this.props.canvasImage) {
this.canvas.backgroundColor = this.props.canvasFill;
this.canvas.renderAll();
}
}
extend(obj, id) {
obj.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
id: id,
name: name
});
};
})(obj.toObject);
}
setCanvasImage() {
console.log("setCanvasImage");
let self = this;
if (this.props.canvasImage) {
this.canvas.setBackgroundColor({ source: this.props.canvasImage, repeat: 'repeat' }, function () {
// self.props.canvasFill = '';
self.canvas.renderAll();
});
}
}
randomId() {
return Math.floor(Math.random() * 999999) + 1;
}
/*------------------------Global actions for element------------------------*/
getActiveStyle(styleName, object) {
object = object || this.canvas.getActiveObject();
if (!object) return '';
return (object.getSelectionStyles && object.isEditing)
? (object.getSelectionStyles()[styleName] || '')
: (object[styleName] || '');
}
setActiveStyle(styleName, value, object) {
object = object || this.canvas.getActiveObject();
if (!object) return;
if (object.setSelectionStyles && object.isEditing) {
var style = {};
style[styleName] = value;
object.setSelectionStyles(style);
object.setCoords();
}
else {
object.set(styleName, value);
}
object.setCoords();
this.canvas.renderAll();
}
getActiveProp(name) {
var object = this.canvas.getActiveObject();
if (!object) return '';
return object[name] || '';
}
setActiveProp(name, value) {
var object = this.canvas.getActiveObject();
if (!object) return;
object.set(name, value).setCoords();
this.canvas.renderAll();
}
clone() {
let activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
let clone;
switch (activeObject.type) {
case 'rect':
clone = new fabric.Rect(activeObject.toObject());
break;
case 'circle':
clone = new fabric.Circle(activeObject.toObject());
break;
case 'triangle':
clone = new fabric.Triangle(activeObject.toObject());
break;
case 'i-text':
clone = new fabric.IText('', activeObject.toObject());
break;
case 'image':
clone = fabric.util.object.clone(activeObject);
break;
}
if (clone) {
clone.set({ left: 10, top: 10 });
this.canvas.add(clone);
this.selectItemAfterAdded(clone);
}
}
}
getId() {
//console.log("getId");
this.props.id = this.canvas.getActiveObject().toObject().id;
}
setId() {
console.log("setId");
let val = this.props.id;
let complete = this.canvas.getActiveObject().toObject();
console.log(complete);
this.canvas.getActiveObject().toObject = () => {
complete.id = val;
return complete;
};
}
setName() {
console.log("setName");
let val = this.props.name;
let complete = this.canvas.getActiveObject().toObject();
console.log(complete);
this.canvas.getActiveObject().toObject = () => {
complete.name = val;
return complete;
};
}
getOpacity() {
this.props.opacity = this.getActiveStyle('opacity', null) * 100;
}
setOpacity() {
this.setActiveStyle('opacity', parseInt(this.props.opacity) / 100, null);
}
getFill() {
this.props.fill = this.getActiveStyle('fill', null);
}
setFill() {
this.setActiveStyle('fill', this.props.fill, null);
}
getLineHeight() {
console.log("getLineHeight");
this.props.lineHeight = this.getActiveStyle('lineHeight', null);
}
setLineHeight() {
this.setActiveStyle('lineHeight', parseFloat(this.props.lineHeight), null);
}
getCharSpacing() {
this.props.charSpacing = this.getActiveStyle('charSpacing', null);
}
setCharSpacing() {
this.setActiveStyle('charSpacing', this.props.charSpacing, null);
}
getFontSize() {
this.props.fontSize = this.getActiveStyle('fontSize', null);
}
setFontSize() {
this.setActiveStyle('fontSize', parseInt(this.props.fontSize), null);
}
getBold() {
this.props.fontWeight = this.getActiveStyle('fontWeight', null);
}
setBold() {
this.props.fontWeight = !this.props.fontWeight;
this.setActiveStyle('fontWeight', this.props.fontWeight ? 'bold' : '', null);
}
getFontStyle() {
this.props.fontStyle = this.getActiveStyle('fontStyle', null);
}
setFontStyle() {
this.props.fontStyle = !this.props.fontStyle;
this.setActiveStyle('fontStyle', this.props.fontStyle ? 'italic' : '', null);
}
getTextDecoration() {
this.props.TextDecoration = this.getActiveStyle('textDecoration', null);
}
setTextDecoration(value) {
let iclass = this.props.TextDecoration;
if (iclass.includes(value)) {
iclass = iclass.replace(RegExp(value, "g"), "");
} else {
iclass += ` ${value}`
}
this.props.TextDecoration = iclass;
this.setActiveStyle('textDecoration', this.props.TextDecoration, null);
}
hasTextDecoration(value) {
return this.props.TextDecoration.includes(value);
}
getTextAlign() {
this.props.textAlign = this.getActiveProp('textAlign');
}
setTextAlign(value) {
this.props.textAlign = value;
this.setActiveProp('textAlign', this.props.textAlign);
}
getFontFamily() {
this.props.fontFamily = this.getActiveProp('fontFamily');
}
setFontFamily() {
this.setActiveProp('fontFamily', this.props.fontFamily);
}
/*System*/
removeSelected() {
console.log("removeSelected");
let activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
this.canvas.remove(activeObject);
// this.textString = '';
}
else if (activeGroup) {
let objectsInGroup = activeGroup.getObjects();
this.canvas.discardActiveGroup();
let self = this;
objectsInGroup.forEach(function (object) {
self.canvas.remove(object);
});
}
}
bringToFront() {
console.log("bringToFront");
let activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
activeObject.bringToFront();
// activeObject.opacity = 1;
}
else if (activeGroup) {
let objectsInGroup = activeGroup.getObjects();
this.canvas.discardActiveGroup();
objectsInGroup.forEach((object) => {
object.bringToFront();
});
}
}
sendToBack() {
let activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
activeObject.sendToBack();
// activeObject.opacity = 1;
}
else if (activeGroup) {
let objectsInGroup = activeGroup.getObjects();
this.canvas.discardActiveGroup();
objectsInGroup.forEach((object) => {
object.sendToBack();
});
}
}
confirmClear() {
console.log("confirmClear");
if (confirm('Are you sure?')) {
this.canvas.clear();
}
}
rasterize() {
console.log("rasterize");
if (!fabric.Canvas.supports('toDataURL')) {
alert('This browser doesn\'t provide means to serialize canvas to an image');
}
else {
console.log(this.canvas.toDataURL('png'))
//window.open(this.canvas.toDataURL('png'));
var image = new Image();
image.src = this.canvas.toDataURL('png')
var w = window.open("");
w.document.write(image.outerHTML);
}
}
rasterizeSVG() {
console.log("rasterizeSVG");
console.log(this.canvas.toSVG())
// window.open(
// 'data:image/svg+xml;utf8,' +
// encodeURIComponent(this.canvas.toSVG()));
// console.log(this.canvas.toSVG())
// var image = new Image();
// image.src = this.canvas.toSVG()
var w = window.open("");
w.document.write(this.canvas.toSVG());
};
saveCanvasToJSON() {
let json = JSON.stringify(this.canvas);
localStorage.setItem('Kanvas', json);
console.log('json');
console.log(json);
}
loadCanvasFromJSON() {
let CANVAS = localStorage.getItem('Kanvas');
console.log('CANVAS');
console.log(CANVAS);
// and load everything from the same json
this.canvas.loadFromJSON(CANVAS, () => {
console.log('CANVAS untar');
console.log(CANVAS);
// making sure to render canvas at the end
this.canvas.renderAll();
// and checking if object's "name" is preserved
console.log('this.canvas.item(0).name');
console.log(this.canvas);
});
};
rasterizeJSON() {
console.log("inside rasterize json method");
console.log(this.canvas);
try {
this.json = JSON.stringify(this.canvas);
}
catch (error) {
console.log(error);
}
//below line used for storing json locally on browser
localStorage.setItem("Kanvas", this.json);
}
resetPanels() {
console.log("resetPanels");
// this.launch.nativeElement.click();
this.textEditor = false;
this.imageEditor = false;
this.figureEditor = false;
}
}