使用SVG多边形元素的工作方法

17

我正在尝试使用JavaScript处理SVG多边形。我创建了一个多边形并设置了其初始点列表,代码如下:

var polygon = document.createElementNS('http://www.w3.org/2000/svg','polygon');
polygon.setAttribute("points", "0,0  100,100 200,200");

如果我想修改第二个点(100, 100),我该怎么办?现在我基本上是再次重建整个字符串。但是我们能否以某种方式将“polygon.points”表示为数组,还是它真的只是一个纯简单的字符串?对于非常简单的多边形,这可以很好地工作,但是如果我的多边形最终有成百上千个点对,每次想要修改一个单独的元素时就需要重建整个“points”属性,这让我感到非常不爽。

谢谢

4个回答

27

您可以使用SVG DOM访问各个点的值:

var p = polygon.points.getItem(1);
p.x = 150;
p.y = 300;

(假设您的用户代理实现了此接口。) 请参见 SVGPolygonElementSVGAnimatedPointsSVGPointListSVGPoint

我发现在使用这些 SVG DOM 接口时(至少对我来说,在其中进行大部分 SVG 操作的 Batik 中),通常并不比使用字符串操作更新属性更快。


6

很遗憾,你必须重新构建这个字符串。但把整个字符串包装在一个对象中并不难,可以像这样:

function Polygon () {
    var pointList = [];
    this.node = document.createElementNS('http://www.w3.org/2000/svg','polygon');
    function build (arg) {
        var res = [];
        for (var i=0,l=arg.length;i<l;i++) {
            res.push(arg[i].join(','));
        }
        return res.join(' ');
    }
    this.attribute = function (key,val) {
        if (val === undefined) return node.getAttribute(key);
        node.setAttribute(key,val);
    }
    this.getPoint = function (i) {return pointList[i]}
    this.setPoint = function (i,x,y) {
        pointList[i] = [x,y];
        this.attribute('points',build(pointList));
    }
    this.points = function () {
      for (var i=0,l=arguments.length;i<l;i+=2) {
          pointList.push([arguments[i],arguments[i+1]]);
      }
      this.attribute('points',build(pointList));
    }
    // initialize 'points':
    this.points.apply(this,arguments);
}

var polygon = new Polygon(0,0, 100,100, 200,200);
polygon.setPoint(0, 50,10); // set point and automatically re-build points
polygon.points(50,50, 50,100, 200,100); // set everything
polygon.node; // refer to the actual SVG element

* 这不是最好的实现方式,但你可以理解这个思路。


谢谢,看起来很不错。我明白你的意思了。我会尝试在“原始”表示的基础上实现一个优化的版本。 - user246114
如果我在Chrome 58中运行此代码,我会收到一个错误“Uncaught ReferenceError:node未定义”。这也发生在Chrome开发控制台中,因此我认为它是代码固有的问题。 - Colin D
@ColinD 应该是 this.node。这段代码从来没有打算直接使用。它旨在说明您可以轻松地实现用于管理多边形的代码的想法。 - slebetman

1

你需要使用setAttributeNS。你可能想要在某个变量中缓存该命名空间,以便您不必一直输入它。


我们在设置SVG元素的属性时,是否必须使用setAttributeNS / getAttributeNS?例如,即使我们只想修改矩形的 'x' 参数,我们还需要使用rect.setAttributeNS(ns, 'x', 22)吗?谢谢。 - user246114

0

你需要一次性设置所有点,性能非常稳定。你可能想要做的是在setAttribute调用之外管理数组并将其合并。


好的,如果我想要一个通用的解决方案,为了修改第N对,我需要自己解析字符串,找到它,然后进行修改。这有点糟糕,但我想我可以将点对作为一个单独的结构体来保留,但他们将其设置成这样有点不好!谢谢。 - user246114

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接