mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-05-19 11:01:08 +00:00
parent
3d022bc4a0
commit
f157f930ef
14 changed files with 127 additions and 22 deletions
3
build.js
3
build.js
|
|
@ -313,7 +313,8 @@ else {
|
|||
|
||||
exec(mininfierCmd, function (error, output) {
|
||||
if (error) {
|
||||
console.error('Minification failed using', minifier, 'with', mininfierCmd);
|
||||
console.log('Minification failed using', minifier, 'with', mininfierCmd);
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('Minified using', minifier, 'to ' + distributionPath + 'fabric.min.js');
|
||||
|
|
|
|||
|
|
@ -1573,7 +1573,7 @@
|
|||
* @chainable
|
||||
*/
|
||||
dispose: function () {
|
||||
this.callSuper('dispose');
|
||||
fabric.StaticCanvas.prototype.dispose.call(this);
|
||||
var wrapper = this.wrapperEl;
|
||||
this.removeListeners();
|
||||
wrapper.removeChild(this.upperCanvasEl);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@
|
|||
fabric.util.string.escapeXml(_char),
|
||||
'</tspan>\n'
|
||||
].join('');
|
||||
}
|
||||
},
|
||||
});
|
||||
})();
|
||||
/* _TO_SVG_END_ */
|
||||
|
|
|
|||
|
|
@ -6,9 +6,15 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
|
|||
initHiddenTextarea: function() {
|
||||
this.hiddenTextarea = fabric.document.createElement('textarea');
|
||||
this.hiddenTextarea.setAttribute('autocapitalize', 'off');
|
||||
this.hiddenTextarea.setAttribute('autocorrect', 'off');
|
||||
this.hiddenTextarea.setAttribute('autocomplete', 'off');
|
||||
this.hiddenTextarea.setAttribute('spellcheck', 'false');
|
||||
this.hiddenTextarea.setAttribute('data-fabric-hiddentextarea', '');
|
||||
this.hiddenTextarea.setAttribute('wrap', 'off');
|
||||
var style = this._calcTextareaPosition();
|
||||
this.hiddenTextarea.style.cssText = 'white-space: nowrap; position: absolute; top: ' + style.top +
|
||||
'; left: ' + style.left + '; opacity: 0; width: 1px; height: 1px; z-index: -999;';
|
||||
this.hiddenTextarea.style.cssText = 'position: absolute; top: ' + style.top +
|
||||
'; left: ' + style.left + '; z-index: -999; opacity: 0; width: 1px; height: 1px; font-size: 1px;' +
|
||||
' line-height: 1px; paddingーtop: ' + style.fontSize + ';';
|
||||
fabric.document.body.appendChild(this.hiddenTextarea);
|
||||
|
||||
fabric.util.addListener(this.hiddenTextarea, 'keydown', this.onKeyDown.bind(this));
|
||||
|
|
|
|||
|
|
@ -627,8 +627,9 @@
|
|||
*/
|
||||
fabric.Group.fromObject = function(object, callback) {
|
||||
fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {
|
||||
delete object.objects;
|
||||
callback && callback(new fabric.Group(enlivenedObjects, object, true));
|
||||
var options = fabric.util.object.clone(object, true);
|
||||
delete options.objects;
|
||||
callback && callback(new fabric.Group(enlivenedObjects, options, true));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1859,7 +1859,12 @@
|
|||
* @chainable
|
||||
*/
|
||||
remove: function() {
|
||||
this.canvas && this.canvas.remove(this);
|
||||
if (this.canvas) {
|
||||
if (this.group && this.group === this.canvas._activeGroup) {
|
||||
this.group.remove(this);
|
||||
}
|
||||
this.canvas.remove(this);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@
|
|||
'\t<g ', this.getSvgId(), 'transform="', this.getSvgTransform(), this.getSvgTransformMatrix(), '"',
|
||||
style, '>\n',
|
||||
textAndBg.textBgRects.join(''),
|
||||
'\t\t<text ',
|
||||
'\t\t<text xml:space="preserve" ',
|
||||
(this.fontFamily ? 'font-family="' + this.fontFamily.replace(/"/g, '\'') + '" ' : ''),
|
||||
(this.fontSize ? 'font-size="' + this.fontSize + '" ' : ''),
|
||||
(this.fontStyle ? 'font-style="' + this.fontStyle + '" ' : ''),
|
||||
|
|
@ -945,6 +945,11 @@
|
|||
);
|
||||
},
|
||||
|
||||
getSvgStyles: function(skipShadow) {
|
||||
var svgStyle = fabric.Object.prototype.getSvgStyles.call(this, skipShadow);
|
||||
return svgStyle + ' white-space: pre;';
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Number} textTopOffset Text top offset
|
||||
|
|
|
|||
|
|
@ -1107,7 +1107,7 @@
|
|||
* @private
|
||||
*/
|
||||
__serializeBgOverlay: function(methodName, propertiesToInclude) {
|
||||
var data = { };
|
||||
var data = { }, bgImage = this.backgroundImage, overlay = this.overlayImage;
|
||||
|
||||
if (this.backgroundColor) {
|
||||
data.background = this.backgroundColor.toObject
|
||||
|
|
@ -1120,11 +1120,11 @@
|
|||
? this.overlayColor.toObject(propertiesToInclude)
|
||||
: this.overlayColor;
|
||||
}
|
||||
if (this.backgroundImage) {
|
||||
data.backgroundImage = this._toObject(this.backgroundImage, methodName, propertiesToInclude);
|
||||
if (bgImage && !bgImage.excludeFromExport) {
|
||||
data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);
|
||||
}
|
||||
if (this.overlayImage) {
|
||||
data.overlayImage = this._toObject(this.overlayImage, methodName, propertiesToInclude);
|
||||
if (overlay && !overlay.excludeFromExport) {
|
||||
data.overlayImage = this._toObject(overlay, methodName, propertiesToInclude);
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
@ -1462,19 +1462,21 @@
|
|||
if (!object) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var activeGroup = this._activeGroup,
|
||||
i, obj, idx, newIdx, objs;
|
||||
i, obj, idx, newIdx, objs, objsMoved = 0;
|
||||
|
||||
if (object === activeGroup) {
|
||||
objs = activeGroup._objects;
|
||||
for (i = 0; i < objs.length; i++) {
|
||||
obj = objs[i];
|
||||
idx = this._objects.indexOf(obj);
|
||||
if (idx !== 0) {
|
||||
if (idx > 0 + objsMoved) {
|
||||
newIdx = idx - 1;
|
||||
removeFromArray(this._objects, obj);
|
||||
this._objects.splice(newIdx, 0, obj);
|
||||
}
|
||||
objsMoved++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -1530,19 +1532,21 @@
|
|||
if (!object) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var activeGroup = this._activeGroup,
|
||||
i, obj, idx, newIdx, objs;
|
||||
i, obj, idx, newIdx, objs, objsMoved = 0;
|
||||
|
||||
if (object === activeGroup) {
|
||||
objs = activeGroup._objects;
|
||||
for (i = objs.length; i--;) {
|
||||
obj = objs[i];
|
||||
idx = this._objects.indexOf(obj);
|
||||
if (idx !== this._objects.length - 1) {
|
||||
if (idx < this._objects.length - 1 - objsMoved) {
|
||||
newIdx = idx + 1;
|
||||
removeFromArray(this._objects, obj);
|
||||
this._objects.splice(newIdx, 0, obj);
|
||||
}
|
||||
objsMoved++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -82,17 +82,20 @@
|
|||
/** @ignore */
|
||||
addListener = function (element, eventName, handler, options) {
|
||||
// since ie10 or ie9 can use addEventListener but they do not support options, i need to check
|
||||
element.addEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);
|
||||
element && element.addEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);
|
||||
};
|
||||
/** @ignore */
|
||||
removeListener = function (element, eventName, handler, options) {
|
||||
element.removeEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);
|
||||
element && element.removeEventListener(eventName, handler, shouldUseAttachEventDetachEvent ? false : options);
|
||||
};
|
||||
}
|
||||
|
||||
else if (shouldUseAttachEventDetachEvent) {
|
||||
/** @ignore */
|
||||
addListener = function (element, eventName, handler) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
var uid = getUniqueId(element);
|
||||
setElement(uid, element);
|
||||
if (!listeners[uid]) {
|
||||
|
|
@ -108,6 +111,9 @@
|
|||
};
|
||||
/** @ignore */
|
||||
removeListener = function (element, eventName, handler) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
var uid = getUniqueId(element), listener;
|
||||
if (listeners[uid] && listeners[uid][eventName]) {
|
||||
for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) {
|
||||
|
|
@ -123,6 +129,9 @@
|
|||
else {
|
||||
/** @ignore */
|
||||
addListener = function (element, eventName, handler) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
var uid = getUniqueId(element);
|
||||
if (!handlers[uid]) {
|
||||
handlers[uid] = { };
|
||||
|
|
@ -139,6 +148,9 @@
|
|||
};
|
||||
/** @ignore */
|
||||
removeListener = function (element, eventName, handler) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
var uid = getUniqueId(element);
|
||||
if (handlers[uid] && handlers[uid][eventName]) {
|
||||
var handlersForEvent = handlers[uid][eventName];
|
||||
|
|
|
|||
|
|
@ -599,6 +599,17 @@
|
|||
equal(canvas._objects[1], rect1, 'rect1 should be the new second');
|
||||
equal(canvas._objects[2], rect2, 'rect2 should be the third object');
|
||||
equal(canvas._objects[3], rect4, 'rect4 did not move');
|
||||
canvas.bringForward(group);
|
||||
equal(canvas._objects[0], rect3, 'rect3 should be the new last');
|
||||
equal(canvas._objects[1], rect4, 'rect4 should be the new second');
|
||||
equal(canvas._objects[2], rect1, 'rect1 should be the third object');
|
||||
equal(canvas._objects[3], rect2, 'rect2 is the new top');
|
||||
canvas.bringForward(group);
|
||||
canvas.bringForward(group);
|
||||
equal(canvas._objects[0], rect3, 'rect3 should be the new last');
|
||||
equal(canvas._objects[1], rect4, 'rect4 should be the new second');
|
||||
equal(canvas._objects[2], rect1, 'rect1 is still third');
|
||||
equal(canvas._objects[3], rect2, 'rect2 is still new top');
|
||||
});
|
||||
|
||||
test('activeGroup sendBackwards', function() {
|
||||
|
|
@ -618,6 +629,17 @@
|
|||
equal(canvas._objects[1], rect3, 'rect3 should be shifted down by 1');
|
||||
equal(canvas._objects[2], rect4, 'rect4 should be shifted down by 1');
|
||||
equal(canvas._objects[3], rect2, 'rect2 is the new top');
|
||||
canvas.sendBackwards(group);
|
||||
equal(canvas._objects[0], rect3, 'rect3 is last');
|
||||
equal(canvas._objects[1], rect4, 'rect4 should be shifted down by 1');
|
||||
equal(canvas._objects[2], rect1, 'rect1 should be shifted down by 1');
|
||||
equal(canvas._objects[3], rect2, 'rect2 is still on top');
|
||||
canvas.sendBackwards(group);
|
||||
canvas.sendBackwards(group);
|
||||
equal(canvas._objects[0], rect3, 'rect3 is still last');
|
||||
equal(canvas._objects[1], rect4, 'rect4 should be steady');
|
||||
equal(canvas._objects[2], rect1, 'rect1 should be steady');
|
||||
equal(canvas._objects[3], rect2, 'rect2 is still on top');
|
||||
});
|
||||
|
||||
test('toDataURL', function() {
|
||||
|
|
|
|||
|
|
@ -897,6 +897,24 @@
|
|||
equal(canvas.toObject().objects.length, 1, 'only one object gets exported');
|
||||
});
|
||||
|
||||
test('toObject excludeFromExport bgImage overlay', function() {
|
||||
var rect = makeRect(), rect2 = makeRect(), rect3 = makeRect();
|
||||
canvas.clear();
|
||||
canvas.backgroundImage = rect;
|
||||
canvas.overlayImage = rect2;
|
||||
canvas.add(rect3);
|
||||
var rectToObject = rect.toObject();
|
||||
var rect2ToObject = rect2.toObject();
|
||||
var canvasToObject = canvas.toObject();
|
||||
deepEqual(canvasToObject.backgroundImage, rectToObject, 'background exported');
|
||||
deepEqual(canvasToObject.overlayImage, rect2ToObject, 'overlay exported');
|
||||
rect.excludeFromExport = true;
|
||||
rect2.excludeFromExport = true;
|
||||
canvasToObject = canvas.toObject();
|
||||
equal(canvasToObject.backgroundImage, undefined, 'background not exported');
|
||||
equal(canvasToObject.overlayImage, undefined, 'overlay not exported');
|
||||
});
|
||||
|
||||
|
||||
test('toDatalessObject', function() {
|
||||
ok(typeof canvas.toDatalessObject == 'function');
|
||||
|
|
|
|||
|
|
@ -814,4 +814,31 @@
|
|||
notEqual(measuredBy_getWidthOfWords_preservedSpaces, measuredBy_getWidthOfWords_omittedSpaces);
|
||||
});
|
||||
|
||||
test('space wrap attribute', function() {
|
||||
var iText = new fabric.IText('test foo bar-baz\nqux');
|
||||
iText.enterEditing();
|
||||
equal(iText.hiddenTextarea.getAttribute('wrap'), 'off', 'HiddenTextarea needs wrap off attribute');
|
||||
});
|
||||
|
||||
// test('measuring width of words', function () {
|
||||
// var ctx = canvas.getContext('2d');
|
||||
// var text = 'test foo bar';
|
||||
// var iText = new fabric.IText(text, {
|
||||
// styles: {
|
||||
// 0: {
|
||||
// 9: { fontWeight: 'bold' },
|
||||
// 10: { fontWeight: 'bold' },
|
||||
// 11: { fontWeight: 'bold' },
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// var textSplitted = text.split(' ');
|
||||
// var measuredBy_getWidthOfWords_preservedSpaces = iText._getWidthOfWords(ctx, textSplitted.join(' '), 0, 0);
|
||||
// var measuredBy_getWidthOfWords_omittedSpaces = iText._getWidthOfWords(ctx, textSplitted.join(''), 0, 0);
|
||||
//
|
||||
// notEqual(measuredBy_getWidthOfWords_preservedSpaces, measuredBy_getWidthOfWords_omittedSpaces);
|
||||
// });
|
||||
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@
|
|||
'charSpacing': 0
|
||||
};
|
||||
|
||||
var TEXT_SVG = '\t<g transform="translate(10.5 26.72)">\n\t\t<text font-family="Times New Roman" font-size="40" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" >\n\t\t\t<tspan x="-10" y="12.6" fill="rgb(0,0,0)">x</tspan>\n\t\t</text>\n\t</g>\n';
|
||||
var TEXT_SVG_JUSTIFIED = '\t<g transform="translate(50.5 26.72)">\n\t\t<text font-family="Times New Roman" font-size="40" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" >\n\t\t\t<tspan x="-50" y="12.6" fill="rgb(0,0,0)">x</tspan>\n\t\t\t<tspan x="30" y="12.6" fill="rgb(0,0,0)">y</tspan>\n\t\t</text>\n\t</g>\n';
|
||||
var TEXT_SVG = '\t<g transform="translate(10.5 26.72)">\n\t\t<text xml:space="preserve" font-family="Times New Roman" font-size="40" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1; white-space: pre;" >\n\t\t\t<tspan x="-10" y="12.6" fill="rgb(0,0,0)">x</tspan>\n\t\t</text>\n\t</g>\n';
|
||||
var TEXT_SVG_JUSTIFIED = '\t<g transform="translate(50.5 26.72)">\n\t\t<text xml:space="preserve" font-family="Times New Roman" font-size="40" font-weight="normal" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1; white-space: pre;" >\n\t\t\t<tspan x="-50" y="12.6" fill="rgb(0,0,0)">x</tspan>\n\t\t\t<tspan x="30" y="12.6" fill="rgb(0,0,0)">y</tspan>\n\t\t</text>\n\t</g>\n';
|
||||
|
||||
test('constructor', function() {
|
||||
ok(fabric.Text);
|
||||
|
|
|
|||
|
|
@ -731,10 +731,14 @@
|
|||
|
||||
test('fabric.util.addListener', function() {
|
||||
ok(typeof fabric.util.addListener === 'function', 'fabric.util.addListener is a function');
|
||||
fabric.util.addListener(null, 'mouseup');
|
||||
ok(true, 'test did not throw on null element addListener');
|
||||
});
|
||||
|
||||
test('fabric.util.removeListener', function() {
|
||||
ok(typeof fabric.util.removeListener === 'function', 'fabric.util.removeListener is a function');
|
||||
fabric.util.removeListener(null, 'mouseup');
|
||||
ok(true, 'test did not throw on null element removeListener');
|
||||
});
|
||||
|
||||
test('fabric.util.drawDashedLine', function() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue