svg 形状的文本区域

Text area in svg shapes

使用联合 js 在 svg 中创建了一个文本区域。但是,我无法在文本区域中输入任何文本。如何使文本区域可编辑?

代码:

var graph = new joint.dia.Graph;

                var paper = new joint.dia.Paper({
                    el: $('#myholder'),
                    width: 1500,
                    height: 700,
                    model: graph
                });

                // Create a custom element.
                // ------------------------
                joint.shapes.html = {};
                joint.shapes.html.Element = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
                    markup: '<g class="rotatable"><g class="scalable"><rect/></g><g class="inPorts"/><g class="outPorts"/></g>',
                    portMarkup: '<g class="port<%=1%>"><circle/></g>',
                    defaults: joint.util.deepSupplement({
                        type: 'html.Element',
                        size: {width: 100, height: 80},
                        inPorts: [],
                        outPorts: [],
                        attrs: {
                            '.': {magnet: false},
                            rect: {
                                stroke: 'none', 'fill-opacity': 0, width: 150, height: 250,
                            },
                            circle: {
                                r: 6, //circle radius
                                magnet: true,
                                stroke: 'black'
                            },
                            '.inPorts circle': {fill: 'green', magnet: 'passive', type: 'input'},
                            '.outPorts circle': {fill: 'red', type: 'output'}
                        }
                    }, joint.shapes.basic.Generic.prototype.defaults),
                    getPortAttrs: function (portName, index, total, selector, type) {

                        var attrs = {};
                        var portClass = 'port' + index;
                        var portSelector = selector + '>.' + portClass;
                        var portCircleSelector = portSelector + '>circle';
                        attrs[portCircleSelector] = {port: {id: portName || _.uniqueId(type), type: type}};
                        attrs[portSelector] = {ref: 'rect', 'ref-y': (index + 1) * (10 / total)};
                        if (selector === '.outPorts') {
                            attrs[portSelector]['ref-dx'] = 0;
                        }
                        return attrs;
                    }
                }));


                // 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 id="lbl" value="Please write here"></span>',
                        '<textarea id="txt" type="text" value="Please write here"></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 is an example of reacting on the input change and storing the input data in the cell model.
                        this.$box.find('textarea').on('change', _.bind(function (evt) {
                            this.model.set('textarea', $(evt.target).val());
                        }, 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.paper.$el.mousemove(this.onMouseMove.bind(this)), this.paper.$el.mouseup(this.onMouseUp.bind(this));
                        this.updateBox();
                        return this;
                    },
                    renderPorts: function () {
                        var $inPorts = this.$('.inPorts').empty();
                        var $outPorts = this.$('.outPorts').empty();

                        var portTemplate = _.template(this.model.portMarkup);

                        _.each(_.filter(this.model.ports, function (p) {
                            return p.type === 'in'
                        }), function (port, index) {

                            $inPorts.append(V(portTemplate({id: index, port: port})).node);
                        });
                        _.each(_.filter(this.model.ports, function (p) {
                            return p.type === 'out'
                        }), function (port, index) {

                            $outPorts.append(V(portTemplate({id: index, port: port})).node);
                        });
                    },
                    update: function () {

                        // First render ports so that `attrs` can be applied to those newly created DOM elements
                        // in `ElementView.prototype.update()`.
                        this.renderPorts();
                        joint.dia.ElementView.prototype.update.apply(this, arguments);
                    },
                    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.
                        // paper.on('blank:pointerdown', function(evt, x, y) { this.$box.find('textarea').toBack(); });
                        this.$box.find('span').text(this.model.get('textarea'));
                        this.model.on('cell:pointerclick', function (evt, x, y) {
                            this.$box.find('textarea').toFront();
                        });
                        this.$box.css({width: bbox.width, height: bbox.height, left: bbox.x, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)'});
                    },
                    removeBox: function (evt) {
                        this.$box.remove();
                    }
                });


// Create JointJS elements and add them to the graph as usual.
// -----------------------------------------------------------

                var el1 = new joint.shapes.html.Element({
                    position: {x: 600, y: 250},
                    size: {width: 170, height: 100},
                    inPorts: ['in'],
                    outPorts: ['out'],
                    textarea: 'Start writing'
                });

                var el2 = new joint.shapes.html.Element({
                    position: {x: 600, y: 400},
                    size: {width: 170, height: 100},
                    inPorts: ['in'],
                    outPorts: ['out'],
                    textarea: 'Start writing'
                });

                graph.addCells([el1, el2]);

是否可以根据文本区域内的文本缩放 svg 形状?

我假设您使用的是 JointJS HTML 教程 (http://jointjs.com/tutorial/html-elements) 中的 CSS 样式表。

请注意 .html-element 已将 pointer-events 设置为 none。设置后,所有事件都会传播到 HTML 元素下的 (JointJS) SVG 元素。因此,该论文知道与什么元素进行了交互,例如可以开始拖了。

.html-element {
   pointer-events: none;
}

我建议通过添加以下 CSS 规则为 TextArea 创建一个例外。

.html-element textarea {
   pointer-events: all;
}