如何根据文本内容调整svg形状的大小

时间:2015-07-29 08:27:11

标签: jointjs

我想根据文本区域或文本输入的文本内容设置svg形状比例。随着文本内容的增加,底层svg元素的大小也应该增加

这是我到目前为止所做的:

    var graph = new joint.dia.Graph;
                var paper = new joint.dia.Paper({
                    el: $('#myholder'),
                    width: 1330,
                    height: 660,
                    model: graph,
                    gridSize: 1,
                    defaultLink: new joint.dia.Link({
                        attrs: {'.marker-target': {d: 'M 10 0 L 0 5 L 10 10 z'}}
                    }),
                    validateConnection: function (cellViewS, magnetS, cellViewT, magnetT, end, linkView) {
                        // Prevent linking from input ports.
                        if (magnetS && magnetS.getAttribute('type') === 'input')
                            return false;
                        // Prevent linking from output ports to input ports within one element.
                        if (cellViewS === cellViewT)
                            return false;
                        // Prevent loop linking
                        return (magnetS !== magnetT);
                        // Prevent linking to input ports.
                        return magnetT && magnetT.getAttribute('type') === 'input';
                    },
                    // Enable marking available cells & magnets
                    markAvailable: true,
                    //Enable link snapping within 75px lookup radius
//                    snapLinks: {radius: 75},
                    interactive: function (cellView, methodName)
                    {
                        if (cellView.model.get('isInteractive') === false)
                            return false;
//                        return true;
                    }
                });

                joint.shapes.devs.CircleModel = joint.shapes.devs.Model.extend({
                    markup: '<g class="rotatable"><g class="scalable"><circle class="body"/></g><text class="label"/><g class="inPorts"/><g class="outPorts"/></g>',
//                    portMarkup: '<g class="port port<%=1%>"><rect class="port-body"/><text class="port-label"/></g>',
                    defaults: joint.util.deepSupplement({
                        type: 'devs.CircleModel',
                        attrs: {
                            '.body': {r: 50, cx: 50, stroke: '', fill: 'white'},
                            '.label': {text: '', 'ref-y': 0.5, 'y-alignment': 'middle'},
                            '.port-body': {r: 3, width: 10, height: 10, x: -5, stroke: 'gray', fill: 'lightgray', magnet: 'active'}
                        }

                    }, joint.shapes.devs.Model.prototype.defaults)
                });
                joint.shapes.devs.CircleModelView = joint.shapes.devs.ModelView;

                var rect = new joint.shapes.basic.Rect({
                    isInteractive: false,
                    position: {x: 10, y: 50},
                    size: {width: 51, height: 41},
                    attrs: {rect: {fill: '#D6F2FC', stroke: '#7E7E7E'}, '.': {magnet: false}}
                });

                // Create a custom element.
// ------------------------
                joint.shapes.html = {};
                joint.shapes.html.Element = joint.shapes.basic.Rect.extend({
                    defaults: joint.util.deepSupplement({
                        type: 'html.Element',
                        attrs: {
                            rect: {stroke: 'none', 'fill-opacity': 0}
                        }
                    }, joint.shapes.basic.Rect.prototype.defaults)
                });

// Create a custom view for that element that displays an HTML div above it.
// -------------------------------------------------------------------------

                joint.shapes.html.ElementView = joint.dia.ElementView.extend({
                    template: [
                        '<div class="html-element">',
                         '<button class="delete">x</button>',
                        '<span></span>', '<br/>',
//                        '<input type="text" value="" />',
                        '<textarea id="txt" type="text" rows="10" value="Start writing"></textarea>',
                        '</div>'
                    ].join(''),
                    initialize: function () {
                        _.bindAll(this, 'updateBox');
                        joint.dia.ElementView.prototype.initialize.apply(this, arguments);

                        this.$box = $(_.template(this.template)());
                        // Prevent paper from handling pointerdown.
                        this.$box.find('input,select').on('mousedown click', function (evt) {
                            evt.stopPropagation();
                        });

                        this.$ruler = $('<span>', {style: 'visibility: hidden; white-space: pre'});
                        $(document.body).append(this.$ruler);

                        // This is an example of reacting on the input change and storing the input data in the cell model.
                        this.$box.find('textarea').on('input', _.bind(function (evt) {

                            var val = $(evt.target).val();
                            this.model.set('textarea', val);
                            this.$ruler.html(val);
                            var width = this.$ruler[0].offsetWidth;
                            var height = this.$ruler[0].offsetHeight;
                            var area = width * height;
                            height = area / 150;
                            width = 150;
                            if ((area > 9000)) 
                            {
                                this.model.set('size', {width: width + 50, height: height + 80});
                                this.$box.find('textarea').css({width: width, height: height + 30});
//                                this.$box.find('.color-edit').css({width: width + 50, height: height + 80});
                                this.$box.find('.in').css({top: height + 75});
                            }
                        }, this));

                        this.$box.find('textarea').on('click', _.bind(function () {
                            this.$box.find('.delete').css({opacity: 1});
                            this.$box.find('textarea').css({opacity: 1});
                        }, this));

                        this.$box.find('textarea').on('blur', _.bind(function () {
                            this.$box.find('.delete').css({opacity: 0});
                            this.$box.find('textarea').css({opacity: 0});
                        }, this));

                        this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
                        // Update the box position whenever the underlying model changes.
                        this.model.on('change', this.updateBox, this);
                        // Remove the box when the model gets removed from the graph.
                        this.model.on('remove', this.removeBox, this);

                        this.updateBox();
                        this.listenTo(this.model, 'process:ports', this.update);
                        joint.dia.ElementView.prototype.initialize.apply(this, arguments);
                    },
                    render: function () {
                        joint.dia.ElementView.prototype.render.apply(this, arguments);
                        this.paper.$el.prepend(this.$box);
                        this.updateBox();
                        return this;
                    },
                    updateBox: function ()
                    {
                        // Set the position and dimension of the box so that it covers the JointJS element.
                        var bbox = this.model.getBBox();
                        // Example of updating the HTML with a data stored in the cell model.
                        this.$box.find('label').text(this.model.get('label'));
                        this.$box.find('span').text(this.model.get('select'));
                        this.$box.css({width: bbox.width + 6, height: bbox.height, left: bbox.x, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)'});
                    },
                    removeBox: function (evt) {
                        this.$ruler.remove();
                        this.$box.remove();
                    }
                });

                paper.on('cell:pointerdblclick', function (cellView, evt, x, y)
                {
                    var clone = cellView.model.clone();
                    if (rect.id === cellView.model.id)
                    {
                        clone = new joint.shapes.html.Element({
                            position: {x: 100, y: 60},
                            size: {width: 81, height: 69},
                            inPorts: [''],
                            outPorts: [''],
                            attrs: {
                                '.': {magnet: true},
                                '.label': {text: '', 'ref-x': .4, 'ref-y': .2},
                                '.inPorts circle': {type: 'input'},
                                '.outPorts circle': {type: 'output'},
                                '.port-body': {r: 3}
                            }
                        });
//                        clone.resize(2*81,2*39)
                        graph.addCell(clone);
                    }
                });

//                // First, unembed the cell that has just been grabbed by the user.
                paper.on('cell:pointerdown', function (cellView, evt, x, y) {

                    var cell = cellView.model;
                    if (!cell.get('embeds') || cell.get('embeds').length === 0) {
                        // Show the dragged element above all the other cells (except when the
                        // element is a parent).
                        cell.toFront();
                        _.invoke(graph.getConnectedLinks(cell), 'toFront');
                    }

                    if (cell.get('parent')) {
                        graph.getCell(cell.get('parent')).unembed(cell);
                    }
                });
                // When the dragged cell is dropped over another cell, let it become a child of the
                //element below.
                paper.on('cell:pointerup', function (cellView, evt, x, y) {

                    if (cellView.model.isLink())
                        return;

                    var cell = cellView.model;
                    var cellViewsBelow = paper.findViewsFromPoint(cell.getBBox().center());
                    if (cellViewsBelow.length) {
                        // Note that the findViewsFromPoint() returns the view for the `cell` itself.
                        var cellViewBelow = _.find(cellViewsBelow, function (c) {
                            return c.model.id !== cell.id;
                        });
                        // Prevent recursive embedding.
                        if (cellViewBelow && cellViewBelow.model.get('parent') !== cell.id) {
                            cellViewBelow.model.embed(cell);
                        }
                    }
                });
                graph.addCells([rect]);

无法在其他地方找到解决方案。任何帮助,将不胜感激。感谢

1 个答案:

答案 0 :(得分:0)

  1. 您必须根据内部文本调整HTML输入大小。
  2. Auto-scaling input[type=text] to width of value?

    1. ElementView必须侦听HTML输入更改(input事件)并根据HTML输入的宽度和高度更新模型的大小。
    2. 示例:

      function onTextInput(evt) {    
           var $input = $(evt.target);
           // 1. auto-scaling the input based on the text inside.
           $input.attr('size', Math.max($input.val().length, 10));    
           // 2. resizing the model to the size of the input + padding.
           model.resize($input.outerWidth() + 5, $input.outerHeight() + 40);
      }
      
      $('input').on('input', onTextInput);
      

      JS小提琴:http://jsfiddle.net/kumilingus/Lrffgvqn/

      与HTML TextArea类似,唯一的区别在于如何根据内部文本自动缩放它。

相关问题