我在使用Snap.svg API中的函数Element.append(el)
时遇到了一些麻烦。我需要在变量数组中存储该SVG的实例,以便我可以在整个运行时访问特定的SVG。
当我尝试将此代码存储到groupViews
时,它可以正常工作。但是,把它放在一个数组(groupView
)给我带来了这个错误:
Uncaught TypeError: Cannot read proerty 'append' of undefined
当我记录groupViews
和groupView[i]
时,控制台会向我显示相同的输出,所以我不确定还有什么可以尝试。
关于如何解决这个问题的任何想法?谢谢。
for(var i = 0; i < numOfGroups; i++)
{
var sel = '#GroupView' + i;
groupView[i] = Snap(sel);
console.log(groupView[i]);
groupViews = Snap('#GroupView0');
console.log(groupViews);
Snap.load("/svg/groupView-12_13_2016-01.svg", function(f) {
groupView[i].append(f);
groupViews.append(f);
}); //end of Snap.load(groupView)
}
编辑(1/5):
这是我加载了空SVG的HTML代码:
<div class = "groupView0">
<svg viewBox='0 0 3640.9 540.5' id='GroupView0'></svg>
</div>
<div class = "groupView1">
<svg viewBox='0 0 3640.9 540.5' id='GroupView1'></svg>
</div>
因此,这就是我加载特定SVG文件并将其附加到JS中的原因。有一个更好的方法吗?
编辑(1/6):
以下是我的svg文件的一小部分:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 3640.9 540.5" style="enable-background:new 0 0 3640.9 540.5;" xml:space="preserve">
<g id="A" onclick="detailedView();" cursor="pointer">
<rect id="PanelBackground" x="35.4" y="55.5" class="st2" width="173.2" height="155"/> <!--height="444" -->
<g id="UpperBar">
<linearGradient id="Header_20_" gradientUnits="userSpaceOnUse" x1="35.3937" y1="67.0279" x2="208.5774" y2="67.0279">
<stop offset="0" style="stop-color:#F68E1E"/>
<stop offset="0.5" style="stop-color:#F16A22"/>
<stop offset="0.903" style="stop-color:#F05F22"/>
<stop offset="1" style="stop-color:#F05C22"/>
</linearGradient>
<polygon id="Header" class="st3" points="35.4,55.5 208.6,55.5 208.6,78.6 35.4,78.6 "/>
<g>
<rect x="82.1" y="61.8" class="st4" width="121" height="10.8"/>
<text id="GroupName" transform="matrix(1 0 0 1 82.0885 71.6627)" class="st5 st6 st7">A</text>
<text id="FloorNumber" transform="matrix(1 0 0 1 182.3287 141.8773)" class="st2 st19 st7">X</text>
</g>
</g>
</svg>
执行您发布的代码后.. 如果我尝试运行如下代码:
groupName[0] = groupView[0].select('#GroupName');
groupName[0].attr({
text: "something"
});
我收到此错误:Uncaught TypeError: Cannot set property '0' of undefined
答案 0 :(得分:1)
尝试类似这样的东西,它使用clone(),因为它看起来每次都在同一个SVG文件中加载,所以我们可以加载一次,然后克隆()它以保存对服务器的重复调用。 / p>
这依赖于svg文件中包含外部标记的基础。如果它是部分svg,并且只有一个元素,则将select('svg')更改为select('group')或其他任何内容。
然后我们存储对该克隆的引用,然后将该元素附加到索引的svg元素。
这是一个完整的例子,加载的svg test.svg只是..
<svg>
<rect x="20" y="20" width="100" height="100" />
</svg>
主要html / js
<body>
<div class="groupView0">
<svg id="groupView0"></svg>
</div>
<div class="groupView1">
<svg id="groupView1"></svg>
</div>
<div class="groupView2">
<svg id="groupView2"></svg>
</div>
<script>
var sel = "#groupView";
var groupView = [];
var numOfGroups = 3;
Snap.load("test.svg",onSVGLoaded);
function onSVGLoaded ( fragment ) {
groupView[0] = Snap( sel + '0' ).append( fragment ).select('svg');
for( var i = 1; i < numOfGroups; i++ ) {
groupView[i] = groupView[0].clone().appendTo( Snap( sel + i ) );
}
groupView[0].attr({ fill: 'yellow' });
groupView[1].attr({ fill: 'red' });
groupView[2].attr({ fill: 'green' });
}
答案 1 :(得分:0)
问题是你在循环中使用异步函数,所以文件在完成之后才会加载(特别是因为你调用相同的文件numOfGroups - 1
次。基本上当结果是返回,我已经处理了整个数组,并且i的值不再在你期望的范围内(确切地说numOfGroups
)。
由于groupView[numOfGroups]
从未设置为值,因此未定义。
理想的解决方案是在循环之前(在回调函数中)等待外部文件加载,如下所示:
var sel = '#GroupView';
var groupView = [];
Snap.load("/svg/groupView-12_13_2016-01.svg", function(f) {
for(var i = 0; i < numOfGroups; i++) {
groupView[i] = new Snap(sel+i);
groupView[i].append(f);
}
});
或者在循环范围内定义一个变量,以便在分配负载值时欺骗回调函数使用范围变量,同样如下:
for(var i = 0; i < numOfGroups; i++)
{
var sel = '#GroupView' + i;
var cur = i; //This creates a scope variable for the current callback.
groupView[i] = Snap(sel);
console.log(groupView[i]);
groupViews = Snap('#GroupView0');
console.log(groupViews);
Snap.load("/svg/groupView-12_13_2016-01.svg", function(f) {
groupView[cur].append(f);
groupViews.append(f);
}); //end of Snap.load(groupView)
}
然而,考虑到第二个解决方案对同一个文件发出numOfGroups
次请求,并将numOfGroups
个回调加载到内存中,实际上效率非常低。唯一需要的是你实际上打算调用不同的文件。
最后,我将举例说明正在发生的事情。
var d = document.getElementById("testOutput");
var b = document.getElementById("trigger");
function RunTest() {
var arr = [];
d.innerHTML = "";
for (var i = 0; i < 10; i++) {
d.innerHTML += "Loop: " + i;
arr[i] = i;
setTimeout(function() {
d.innerHTML += "i is " + i + "<br />";
}, 1000); //Simulates Delay while loading...
d.innerHTML += "...Finished Loop </br>";
}
}
<input id="trigger" type="button" onClick="RunTest()" value="Test" />
<div id="testOutput"></div>