Text area in svg shapes

↘锁芯ラ 提交于 2019-11-29 22:35:33

问题


Created a text area in svg using joint js. However, I am not able to enter any text in the text area. How to make the text area editable?

Code:

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]);

Also is it possible to scale the svg shape based on the text inside text area?


回答1:


I assume that you are using the CSS stylesheet from the JointJS HTML tutorial (http://jointjs.com/tutorial/html-elements).

Note that .html-element has pointer-events set to none. With that being set all events are propagated to the (JointJS) SVG Element under the HTML Element. The paper therefore knows what element was interacted with and e.g. can start dragging it.

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

I suggest to create an exception for the TextArea by adding the following CSS rule.

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


来源:https://stackoverflow.com/questions/31671743/text-area-in-svg-shapes

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!