我正在将FabricJS集成到我的角度应用程序中。我已经设法将画布缩小并自动将图形添加到画布中。
我的目标是通过8英寸使图形8英寸并添加具有动态网格高度和宽度的网格(比如说1/16英寸x 1/16英寸)。
以下是我的问题: 1.添加图形时,我无法以英寸为单位设置图形高度和宽度。我只能使用一个数字。我怎样才能使用不同的单位呢?我使用了cssOnly:true用于画布,但我似乎无法弄清楚这个数字。
addFigure(figure) {
let add: any;
switch (figure) {
case 'rectangle':
add = new fabric.Rect({
width: 500, height: 500, left: 150, top: 10, angle: 0, opacity: .3,
fill: '#3f51b5'
});
break;
case 'square':
add = new fabric.Rect({
width: 200, height: 200, left: 0, top: 0, angle: 0, opacity: .15,
fill: '#4caf50'
});
break;
case 'triangle':
add = new fabric.Triangle({
width: 100, height: 100, left: 10, top: 10, fill: '#2196f3'
});
break;
case 'circle':
add = new fabric.Circle({
radius: 50, left: 10, top: 10, fill: '#ff5722'
});
break;
}
this.extend(add, this.randomId());
console.log(add);
this.canvas.add(add);
// this.selectItemAfterAdded(add);
}
注意上面的网格。我有同样的问题。这是我从Adding grid over Fabric.js canvas提取的网格代码。我遇到的问题是我不知道如何将这个网格均匀地分成1/16英寸1/16英寸,因为这是一个8英寸乘8英寸的画布。
onst gridGroup = new fabric.Group([],{left:0,top:0});
const gridSize = 16;
const gridWidth = 400;
const gridHeight = 400;
const lineOption = {stroke: 'rgba(0,0,0,.4)', strokeWidth: 1, selectable: false, strokeDashArray: [3, 3]};
for (let i = Math.ceil(gridWidth / gridSize); i--;) {
this.canvas.add( new fabric.Line([gridSize * i, 0, gridSize * i, gridHeight], lineOption) );
}
for (let i = Math.ceil(gridHeight / gridSize); i--;) {
this.canvas.add( new fabric.Line([0, gridSize * i, gridWidth, gridSize * i], lineOption) );
}
this.canvas.add(gridGroup);
以下是供审核的整个组件。在设置中有什么我做错了吗?
// private canvas: any;
uploading = false;
uploaded = false;
pdfUrl = '';
canvas: any;
props: any = {
canvasFill: '#ffffff',
canvasImage: '',
id: null,
opacity: null,
fill: null,
fontSize: null,
lineHeight: null,
charSpacing: null,
fontWeight: null,
fontStyle: null,
textAlign: null,
fontFamily: null,
TextDecoration: ''
};
textString: string;
url = '';
size: any = {
width: '6in',
height: '6in'
};
json: any;
globalEditor = false;
textEditor = false;
imageEditor = false;
figureEditor = false;
selected: any;
constructor(
private router: Router,
private userService: UserService,
private fileService: FileService
) { }
ngOnInit() {
this.getActive();
// this.activateCanvas();
//setup front side canvas
this.canvas = new fabric.Canvas('canvas', {
hoverCursor: 'pointer',
selection: true,
selectionBorderColor: 'blue'
});
this.canvas.on({
'object:moving': (e) => { },
'object:modified': (e) => { },
'object:selected': (e) => {
const selectedObject = e.target;
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':
break;
}
}
},
'selection:cleared': (e) => {
this.selected = null;
this.resetPanels();
}
});
this.canvas.setWidth(this.size.width, {cssOnly: true});
this.canvas.setHeight(this.size.height, {cssOnly: true});
this.addFigure('square');
const gridGroup = new fabric.Group([], {left: 0, top: 0});
const gridSize = 16;
const gridWidth = 400;
const gridHeight = 400;
const lineOption = {stroke: 'rgba(0,0,0,.4)', strokeWidth: 1, selectable: false, strokeDashArray: [3, 3]};
for (let i = Math.ceil(gridWidth / gridSize); i--;) {
this.canvas.add( new fabric.Line([gridSize * i, 0, gridSize * i, gridHeight], lineOption) );
}
for (let i = Math.ceil(gridHeight / gridSize); i--;) {
this.canvas.add( new fabric.Line([0, gridSize * i, gridWidth, gridSize * i], lineOption) );
}
this.canvas.add(gridGroup);
// for ( let x = 1; x < ( this.canvas.width / gridsize); x++) {
// this.canvas.add(new fabric.Line([cellWidth * x, 0, cellWidth * x, 800],
// { stroke: '#000000', strokeWidth: 1, selectable: false}));
// this.canvas.add(new fabric.Line([0, cellWidth * x, 800, cellWidth * x],
// { stroke: '#000000', strokeWidth: 1, selectable: false}));
// }
// get references to the html canvas element & its context
// this.canvas.on('mouse:down', (e) => {
// let canvasElement: any = document.getElementById('canvas');
// console.log(canvasElement)
// });
}
/*------------------------Block elements------------------------*/
//Block "Size"
changeSize(event: any) {
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) {
let el = event.target;
fabric.Image.fromURL(el.src, (image) => {
image.set({
left: 10,
top: 10,
angle: 0,
padding: 10,
cornersize: 10,
hasRotatingPoint: true,
peloas: 12
});
// image.setWidth(150);
// image.setHeight(150);
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,
// scaleX: 200,
// scaleY: 200,
padding: 10,
cornersize: 10,
hasRotatingPoint: true
});
image.scale(0.2);
// image.setWidth(200);
// image.height = 200;
// image.width = 200;
this.extend(image, this.randomId());
this.canvas.add(image);
this.selectItemAfterAdded(image);
});
}
}
readUrl(event) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
reader.onload = (e) => {
this.url = e.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: 500, height: 500, left: 150, top: 10, angle: 0, opacity: .3,
fill: '#3f51b5'
});
break;
case 'square':
add = new fabric.Rect({
width: 200, height: 200, left: 0, top: 0, angle: 0, opacity: .4,
fill: '#4caf50'
});
break;
case 'triangle':
add = new fabric.Triangle({
width: 100, height: 100, left: 10, top: 10, fill: '#2196f3'
});
break;
case 'circle':
add = new fabric.Circle({
radius: 50, left: 10, top: 10, fill: '#ff5722'
});
break;
}
this.extend(add, this.randomId());
console.log(add);
this.canvas.add(add);
// this.selectItemAfterAdded(add);
}
/*Canvas*/
cleanSelect() {
this.canvas.discardActiveObject();
}
selectItemAfterAdded(obj) {
this.canvas.discardActiveObject();
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
});
};
})(obj.toObject);
}
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) {
let style = {};
style[styleName] = value;
object.setSelectionStyles(style);
object.setCoords();
} else {
object.set(styleName, value);
}
object.setCoords();
this.canvas.renderAll();
}
getActiveProp(name) {
let object = this.canvas.getActiveObject();
if (!object) {return '';}
return object[name] || '';
}
setActiveProp(name, value) {
const object = this.canvas.getActiveObject();
if (!object) {return ''};
object.set(name, value).setCoords();
this.canvas.renderAll();
}
clone() {
const 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() {
this.props.id = this.canvas.getActiveObject().toObject().id;
}
setId() {
const val = this.props.id;
const complete = this.canvas.getActiveObject().toObject();
console.log(complete);
this.canvas.getActiveObject().toObject = () => {
complete.id = val;
return complete;
};
}
getOpacity() {
this.props.opacity = this.getActiveStyle('opacity', null) * 100;
}
setOpacity() {
this.setActiveStyle('opacity', +this.props.opacity / 100, null);
}
getFill() {
this.props.fill = this.getActiveStyle('fill', null);
}
setFill() {
this.setActiveStyle('fill', this.props.fill, null);
}
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', +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() {
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() {
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() {
const activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
activeObject.sendToBack();
// activeObject.opacity = 1;
} else if (activeGroup) {
const objectsInGroup = activeGroup.getObjects();
this.canvas.discardActiveGroup();
objectsInGroup.forEach((object) => {
object.sendToBack();
});
}
}
confirmClear() {
if (confirm('Are you sure?')) {
this.canvas.clear();
}
}
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'));
let image = new Image();
image.src = this.canvas.toDataURL('png')
let w = window.open('');
w.document.write(image.outerHTML);
}
}
rasterizeSVG() {
console.log(this.canvas.toSVG())
// window.open(
// 'data:image/svg+xml;utf8,' +
// encodeURIComponent(this.canvas.toSVG()));
// console.log(this.canvas.toSVG())
// let image = new Image();
// image.src = this.canvas.toSVG()
const w = window.open('');
w.document.write(this.canvas.toSVG());
}
saveCanvasToJSON() {
const json = JSON.stringify(this.canvas);
localStorage.setItem('Kanvas', json);
console.log('json');
console.log(json);
}
loadCanvasFromJSON() {
const 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() {
this.json = JSON.stringify(this.canvas, null, 2);
}
resetPanels() {
this.textEditor = false;
this.imageEditor = false;
this.figureEditor = false;
}
总之,我希望在8英寸乘8英寸的画布上使用1/16英寸x 1/16英寸(可能是动态的)网格,并在此画布中添加一个偶数正方形的图形。
答案 0 :(得分:1)
对于有同样问题的人。似乎cssOnly boolean param选项Im传递不是实际将画布缩放到英寸的解决方案。
以下是我的解决方法。
1)我现在有一个输入,允许用户手动输入他们的PPI,给出关于此网址的信息 - http://dpi.lv/
2)我保存PPI
3)我创建了一个方法calcPixels(inches:number),它使用pixels = inches * ppi来计算所需的像素数
4)我在整个应用程序中使用该方法获取所有宽度,高度,网格线等。
这给了我一个7英寸乘7英寸网格线。它的自动化程度稍低,但如果您保存PPI,用户只需输入一次!
新结果