2017-01-04 11 views
1

У меня возникли проблемы с использованием функции Element.append(el) в API Snap.svg. Мне нужно сохранить экземпляр этого 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) 


    } 

Edit (1/5):

Вот HTML-код, где я пустой SVGs загружен:

<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. Есть лучший способ сделать это?

Edit (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

ли уже загружен SVG? Или вы просто загружаете его на Snap.load? – MiltoxBeyond

+0

@MiltoxBeyond Yep, SVG загружается на мою HTML-страницу. – KS7X

+0

Что вы пытаетесь сделать, сохраните элементы svg, которые будут добавлены позже? Или сохраните элементы SVG, одновременно добавив некоторые или все элементы в DOM, так что они все находятся в DOM и отображаются, но вы просто обращаетесь к ним позже? Вероятно, нет смысла добавлять (f) дважды, но нужно немного больше информации. – Ian

ответ

1

Попробуйте что-то вроде этого, он использует клона(), как это выглядит, как вы загружаются в каждый раз то же SVG-файла, так что мы могли бы загрузить его в один раз, а затем клон() чтобы сохранить повторные вызовы на сервер.

Это зависит от того, что файл svg будет иметь внешнюю разметку. Если это частичный svg и имеет только элемент, измените select ('svg') на выбор ('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' }); 
} 

Working example

+0

Привет, Ян, я редактировал свое сообщение о том, что уже есть в DOM. Мне нужен этот массив, поэтому я могу ссылаться на каждый конкретный экземпляр загружаемого SVG, чтобы я мог использовать для каждого экземпляра такие функции, как Element.animate или Element.attr. – KS7X

+0

Это тот же svg, который будет загружен в каждую группу, или есть много разных svgs? Непонятно, что в загружаемом файле svg. – Ian

+0

Это тот же самый svg, который я загружаю. Мне просто нужно несколько экземпляров этого svg для корреляции с данными на внутреннем сервере. Файл svg содержит несколько элементов, которые все коррелируют с переменными на внутреннем сервере. – KS7X

0

проблема заключается в том, что йо u использует асинхронную функцию внутри цикла, поэтому файл не загружается до тех пор, пока он не завершится (тем более, что вы вызываете тот же файл 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>

+0

Большое спасибо за подробное объяснение и пример того, что происходит в моем коде. Я попробовал оба решения, которые вы предоставили, и я все еще сталкиваюсь с проблемой. 'Uncaught TypeError: Не удается установить свойство '0' из неопределенного' – KS7X

+0

Не думаю, что ваш второй пример не создает область видимости? Также неясно, есть ли 2 приложения, но это требует большей ясности в исходном вопросе. – Ian

+0

Первый пример - это не полный код. вы должны установить 'groupView = [];' – MiltoxBeyond