2013-09-17 1 views
2

Я работаю над проектом с Fabric.js.Метод toSVG не работает в расширенном классе с Fabric.js

Теперь мне нужно создать пользовательский класс и экспортировать его в SVG.

Я использую Fabric.js учебник, чтобы начать:

http://www.sitepoint.com/fabric-js-advanced/

Вот Javascript код:

var LabeledRect = fabric.util.createClass(fabric.Rect, { 
    type: 'labeledRect', 
    initialize: function(options) { 
    options || (options = { }); 
    this.callSuper('initialize', options); 
    this.set('label', options.label || ''); 
    }, 
    toObject: function() { 
    return fabric.util.object.extend(this.callSuper('toObject'), { 
     label: this.get('label') 
    }); 
    }, 
    _render: function(ctx) { 
    this.callSuper('_render', ctx); 
    ctx.font = '20px Helvetica'; 
    ctx.fillStyle = '#333'; 
    ctx.fillText(this.label, -this.width/2, -this.height/2 + 20); 
    } 
}); 

var canvas = new fabric.Canvas('container'); 

var labeledRect = new LabeledRect({ 
    width: 100, 
    height: 50, 
    left: 100, 
    top: 100, 
    label: 'test', 
    fill: '#faa' 
}); 
canvas.add(labeledRect); 
document.getElementById('export-btn').onclick = function() { 
canvas.deactivateAll().renderAll(); 
window.open('data:image/svg+xml;utf8,' + encodeURIComponent(canvas.toSVG())); 

}; 

Здесь HTML:

<canvas id="container" width="780" height="500"></canvas> 
<a href="#" id="export-btn">Export SVG</a> 

Вот мой jsfiddle ..

http://jsfiddle.net/QPDy5/

Что я делаю неправильно?

Заранее спасибо.

ответ

3

Каждый «класс» в Ткань (прямоугольник, круг, изображение, путь и т. Д.) Знает, как выводить свою разметку SVG. Ответственный за него метод - toSVG. Вы можете увидеть toSVG of fabric.Rect, например, или fabric.Text one.

Поскольку вы создали подкласс fabric.Rect здесь и не указали toSVG, toSVG следующего объекта в цепочке прототипов. Следующий «класс» в цепочке наследования - fabric.Rect, поэтому вы видите результат fabric.Rect.prototype.toSVG.

Решение прост: укажите toSVG в вашем подклассе. Теоретически, вы должны объединить код из fabric.Rect#toSVG и fabric.Text#toSVG, но, чтобы избежать повторения и держать вещи ремонтопригодны, мы можем использовать немного хака:

toSVG: function() { 
    var label = new fabric.Text(this.label, { 
     originX: 'left', 
     originY: 'top', 
     left: this.left - this.width/2, 
     top: this.top - this.height/2, 
     fontSize: 20, 
     fill: '#333', 
     fontFamily: 'Helvetica' 
    }); 
    return this.callSuper('toSVG') + label.toSVG(); 
} 

В «FONTSIZE», «заполнить», и " fontFamily "в идеале должны быть перемещены в свойство уровня экземпляра, чтобы избежать повторения их там.

Вот модифицированный тест - http://jsfiddle.net/fabricjs/QPDy5/1/

Что @Sergiu Paraschiv предложил с группой еще один раз-в-жизнеспособное решение.

+0

Спасибо @kangax! :) Это очень помогло мне! –

0

Проблема: нет SVG-эквивалента fillText, поэтому FabricJS, похоже, игнорирует его. My workaround является использование fabric.Group и построить внутренний Rect и Text

var LabeledRect = function(options) { 
    var rect = new fabric.Rect({ 
     width: options.width, 
     height: options.height, 
     fill: options.fill 
    }); 

    var label = new fabric.Text(options.label); 

    var group = new fabric.Group([rect, label]); 

    group.left = options.left; 
    group.top = options.top; 

    group.toSVG = function() { 
     var e=[]; 
     for(var t = 0; t < this._objects.length; t++) 
      e.push(this._objects[t].toSVG()); 

     return'<g transform="'+this.getSvgTransform()+'">'+e.join("")+"</g>" 
    }; 

    return group; 
}; 

Причина я переписал toSVG происходит потому, что циклы в реализации по умолчанию через детей в обратном порядке (for(var t=this._objects.length;t--;)). Я не знаю, почему это происходит, но текст отображается под прямоугольником.

 Смежные вопросы

  • Нет связанных вопросов^_^