質問

I'm new to SVG, so I apologize in advance for my ignorance.

I created a fiddle, just playing around with things. http://jsfiddle.net/a46p8/

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width','200');
svg.setAttribute('height','200');


var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('width', '0');
line.setAttribute('height', '0');
line.setAttribute('x1', '0');
line.setAttribute('y1', '0');
line.setAttribute('x2', '150');
line.setAttribute('y2', '150');
line.setAttribute('stroke', 'rgb(255,0,0)');
line.setAttribute('stroke-width', '2');

svg.appendChild(line);

var ct = document.getElementById('container'); 
ct.appendChild(svg);

Is there really no simpler way to setAttributes? For example, is it at all possible to combine them with something like this:

line.setAttribute('x1', '0', 'y1', '0', 'x2', '150', 'y2', '150');

Yea, I know it doesn't work when I try in the fiddle. But is there some way to do it? If not, what's the reason why you can't?

役に立ちましたか?

解決

Writing your own function would be a solution. As for your example of line.setAttribute('x1', '0', 'y1', '0', 'x2', '150', 'y2', '150');, this would work, but it's going to be difficult to modify, and will expect that the parameters as passed in a particular order.

I would have a function that accepts a single object:

function Line(obj){
    var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    for(prop in obj) {
        line.setAttribute(prop, obj[prop])  
    }
    return line;
}

function SvgContainer(obj) {
    var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    for(prop in obj) {
        svg.setAttribute(prop, obj[prop])  
    }
    return svg;
}

So, all together it would look something like this:

var svgParent = new SvgContainer({
    'width': 200,
    'height': 200
});

var lineOne = new Line({
    'width': 0,
    'height': 0,
    'x1': 0
        // etc
});

var ctn = document.getElementById('container');
svgParent.appendChild(lineOne);
ctn.appendChild(svgParent);

If you're looking to go deeper then this and you need to do a lot of work with SVG in your project then a framework would probably be a worth considering.

他のヒント

Taking susheel's advice, I wrote this function. It works, definitely will be a lot shorter to create new lines when need be now. But this probably isn't the best way to do it I'm guessing. Thoughts?

var line, line2;

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', 1000);
svg.setAttribute('height', 400);


function makeLines(name, xs, ys, xe, ye, color, sw) {
    name = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    name.setAttribute('x1', xs);
    name.setAttribute('y1', ys);
    name.setAttribute('x2', xe);
    name.setAttribute('y2', ye);
    name.setAttribute('stroke', color);
    name.setAttribute('stroke-width', sw);

    svg.appendChild(name);
    var cnt = document.getElementById('container');
    cnt.appendChild(svg);
}

makeLines(line, 100, 0, 900, 200, 'blue', 8);
makeLines(line2, 700, 450, 200, 100, 'red', 2);

EDIT:

Better option:

This is expanding on Matt's answer, adding so there's a complete example for future readers.

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', 1000);
svg.setAttribute('height', 400);

function Line(obj) {
    var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    for(prop in obj) {
        line.setAttribute(prop, obj[prop])  
    }
    svg.appendChild(line);
    var ctn = document.getElementById('container');
    ctn.appendChild(svg);
}

var aline = new Line({
    'x1': 0,
    'y1': 0,
    'x2': 600,
    'y2': 200,
    'stroke': 'green',
    'stroke-width': 8
})


var aline2 = new Line({'x1': 500,'y1': 0,'x2': 100,'y2': 400,'stroke': 'red','stroke-width': 2})

If you would want a simpler way, I would personally look into Snap.svg (for more modern browsers), or Raphael.js (for older), svg.js, pablo.js, d3.js etc. They are basically doing a similar thing behind the scenes, so others have already made it easier for you.

So for Snap it would look like...

var s = Snap(400,400);
var l = s.line(0,0,150,150).attr({ stroke: 'rgb(255,0,0)', 'stroke-width': 2 }); 

jsfiddle http://jsfiddle.net/38jrG/2/

If you really don't want to use a lib to make things easier, just write a func for each like susheel suggests.

ES8 = ECMAScript 8 (2017)

The forEach arrow-function way with Object.entries()

If you want to do it by yourself, there is no native way that I know of, however you can, as other suggested, create your own function that would get the element and object of property => value pairs and would loop over the keys and do it the native way for you.

ES8 - ECMAScript 2017 (8th Edition ECMA-262) brought

ES6 - ECMAScript 2015 (6th Edition, ECMA-262) brought

If you combine these 3, you get a really elegant modern solution to do that:

// FUNCTION
var setAttributes = (el, atts) => {
    Object.entries(atts).forEach(([key, value]) => { // note () around [k,v]!!!
        el.setAttribute(key, value);
    });
};
// USAGE
setAttributes(line, {
   'x1' : 0,
   'y1' : 0,
   // ...
});

TL;DR - minified oneliner

var setAttrs = (e,a)=>Object.entries(a).forEach(([k,v])=>e.setAttribute(k,v));

USAGE:

setAttrs(element, {attribute1: value1, ...}

from https://svgjs.dev/docs/2.7/manipulating/

Set a single attribute:

rect.attr('x', 50)

Set multiple attributes at once:

rect.attr({
  fill: '#f06',
  'fill-opacity': 0.5, 
  stroke: '#000', 
  'stroke-width': 10
})

An improvement to @Matt, I have this utility class.

class zintSvgUtil{

    static createSVGElement(type, obj) {
        let el = document.createElementNS('http://www.w3.org/2000/svg', type);
        for (let prop in obj) {
            el.setAttribute(prop, obj[prop])
        }
        return el;
    }

}

Then,

const svgParent = zintSvgUtil.createSVGElement("svg", {
    width: 200,
    height: 250,
    viewBox: "0 0 200 250"
});

const lineOne = zintSvgUtil.createSVGElement("line", {
    x1: 0,
    y1: 0,
    x2: 100,
    y2: 150,
    stroke: "blue",
    "stroke-width": 2
})

let element = document.querySelector('#idA');
svgParent.appendChild(lineOne);
element.appendChild(svgParent);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top