2016-07-29 7 views
0

Ich habe eine SVG defs Gruppe (erstellt mit Hilfe von d3js) verwendet, um ein komplexes Element zu erstellen, das ich instanziieren und dann ändern möchte, aber von all meinen Spielen und Recherchen ist die einzige Schlussfolgerung, die ich zeichnen kann ist eigentlich eine verknüpfte Instanz, keine unabhängige Instanz. Ich bin sicher, es gibt tief technische Computer-Science-Namen für diese, aber ich bin sicher, Sie wissen, was ich meine: o)Gibt es eine Möglichkeit, ein SVG USE nachträglich modifizierbar (oder eine andere Technik) zu machen?

Ich habe einige Beispielcode erstellt, um das Problem zu veranschaulichen, das ich habe. Es gibt eine Gruppe, die in einer SVG DEFS-Sektion definiert ist, die aus zwei Quadraten und einem Textelement besteht. Dann wird eine ähnliche Struktur unter dem SVG-Container erstellt. Schließlich habe ich mit Hilfe von USE + XLINK: HREF zwei Kopien der Gruppenelemente erstellt, die die zwei Quadrate und den Text enthalten. Ursprünglich hatten alle Deklarationen Klassen, die auch im Abschnitt STYLE angegeben wurden.

Um das Problem zu veranschaulichen und damit zu experimentieren, habe ich einige Elementmodifikationen hinzugefügt und auf die Objekte mit jQuery zugegriffen (ich fand es einfacher als d3 oder direkte Javascript-DOM-Manipulation). Es scheint mir verboten zu sein, innerhalb der Hierarchien, die von DEFS instanziiert wurden, mit USE abzufragen, aber ich kann auf die volle Hierarchie der direkt gezeichneten Bereiche zugreifen. Dies ist ein Problem in meinem Projekt, da ich eine Reihe kleinerer Formabweichungen bei häufig vorkommenden Unterelementen habe, die jedoch jeweils unterschiedlich gekennzeichnet sind. Ich möchte nicht jede lange Hand erstellen, es sei denn, ich muss sogar programmatisch. Im Idealfall möchte ich nur ein paar Unterkomponenten auf Opazität = 0 umschalten und Texte und Beschreibungen mit d3js einfügen. Welche Alternative zu DEFS/USE gibt es, die bedeutet, dass ich eine kopierte Instanz nicht zu einer verknüpften Instanz machen kann?

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
    <title> 
    Testing how to navigate 'DEFS' &amp; 'USE' to change attributes of the elements in the instance 
    </title> 
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script> 
    <!--script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script--> 

    <style> 
    .pinkBox { 
    fill: #fdc4fe; 
    stroke: black; 
    stroke-width: 2px; 
    stroke-linecap: square; 
    stroke-linejoin: round; 
    opacity: 1; 
    } 
    .redBox { 
    fill: #fb198e; 
    stroke: black; 
    stroke-width: 2px; 
    stroke-linecap: square; 
    stroke-linejoin: round; 
    opacity: 1; 
    } 
    .lightGreenBox { 
    fill: #bdf07c; 
    stroke: black; 
    stroke-width: 2px; 
    stroke-linecap: square; 
    stroke-linejoin: round; 
    opacity: 1; 
    } 
    .GreenBox { 
    fill: #4a9a03; 
    stroke: black; 
    stroke-width: 2px; 
    stroke-linecap: square; 
    stroke-linejoin: round; 
    opacity: 1; 
    } 
    .greyText{ 
    font-family:sans-serif; 
    font-size: 12px; 
    fill: grey; 
    } 
    </style> 
</head> 
<body> 
<script type="text/javascript"> 
    var svgContainer = d3.select("body") 
     .append("svg") 
     .attr("width", 1024) 
     .attr("height", 768); 

    var BG = svgContainer.append("rect") 
     .attr("width", "100%") 
     .attr("height", "100%") 
     .attr("fill", "#2d2525"); 

    var reusables = svgContainer.append("defs") 

    var USEgrp = reusables.append("g") 
     //.attr("id","Ugrp") 
     .attr("transform","translate(20,20)"); 

    var RB = USEgrp.append("rect") 
     //.attr("id","RB") 
     .attr("x","10") 
     .attr("y","10") 
     .attr("height","100") 
     .attr("width","100") 
     .attr("rx","10") 
     .attr("ry","10") 
     //.attr("class","redBox") 
     ; 

    var BB = USEgrp.append("rect") 
     //.attr("id","BB") 
     .attr("x","120") 
     .attr("y","10") 
     .attr("height","100") 
     .attr("width","100") 
     .attr("rx","10") 
     .attr("ry","10") 
     //.attr("class","blueBox") 
     ; 

    var Txt = USEgrp.append("text") 
     //.attr("id","TxtU") 
     .attr("x",250) 
     .attr("y",70) 
     //.attr("class","greyText") 
     //.attr("fill","white") 
     .text("These boxes are 'USEed' from the prototype in the 'DEFS' section"); 

    var canvasgrp = svgContainer.append("g") 
     .attr("id","Cgrp") 
     .attr("transform","translate(0,0)"); 

    var GB = canvasgrp.append("rect") 
     .attr("id","GB") 
     .attr("x","30") 
     .attr("y","350") 
     .attr("height","100") 
     .attr("width","100") 
     .attr("rx","10") 
     .attr("ry","10") 
     .attr("class","greenBox") 
     ; 

    var OB = canvasgrp.append("rect") 
     .attr("id","OB") 
     .attr("x","140") 
     .attr("y","350") 
     .attr("height","100") 
     .attr("width","100") 
     .attr("rx","10") 
     .attr("ry","10") 
     .attr("class","orangeBox") 
     ; 

    var Txt2 = canvasgrp.append("text") 
     .attr("id","TxtC") 
     .attr("x",270) 
     .attr("y",400) 
     .attr("class","greyText") 
     .attr("fill","white") 
     .text("These boxes drawn directly to SVG canvas"); 

    var inst1 = svgContainer.append("use") 
     .attr("xlink:href","#Ugrp") 
     .attr("id","inst1") 
     .attr("transform","translate(0,0)"); 

    var inst2 = svgContainer.append("use") 
     .attr("xlink:href","#Ugrp") 
     .attr("id","inst1") 
     .attr("transform","translate(0,150)"); 

    var USEbox1 = ($("g").filter("#Ugrp").children().first().attr("stroke","yellow").attr("stroke-width","6")); 
    var USEtext = ($("g").filter("#Ugrp").children().last().attr("fill","brown")); 
    var USEbox2 = ($("g").filter("#Ugrp").children().first().next().attr("style",".GreenBox")); 


    var SVGbox1 = ($("g").filter("#Cgrp").children().first().attr("stroke","pink").attr("stroke-width","6")); 
    var SVGtext = ($("g").filter("#Cgrp").children().last().attr("fill","cyan")); 
    var SVGbox2 = ($("g").filter("#Cgrp").children().first().next().attr("stroke","magenta").attr("stroke-width","1")); 

</script> 

+1

verfügbar Sie wollen nicht verwenden, möchten Sie einige Basisobjekt in Javascript zu bekommen, es klonen und dann den Klon ändern. –

+0

Robert, danke für deine schnelle Antwort (wie immer :-)). Bitte würdest du Code hinzufügen, um zu verdeutlichen, was du meinst? (oder einen Link zu einem Beispiel in?) Ich dachte, JS-Objekte könnten nützlich sein, aber ich kann das Zusammenspiel mit dem SVG nicht visualisieren! – Greg

+0

getElementById ("Sache"). Clone() dann ändern Sie es und fügen Sie es mit appendChild an –

Antwort

0

Robert hatte recht mit clone() aber ich wollte waren eine Vielzahl von Ideen und was ihre Möglichkeiten und Grenzen erkunden, so baute ich ein wenig d3js Code, um sie auszuprobieren. Ich beschloss, eine komplexe Assembly zu definieren, die instanziiert wird, und dann zu versuchen, Änderungen an den Unterkomponenten der Assembly vorzunehmen. Das Modell war ein group, enthaltend zwei rects und einen text. Die verschiedenen Alternativen, die ich erforschte, waren:

Erstellen Sie meine komplexe Hierarchie direkt im SVG-Container. Dies stellte das Worst-Case-Szenario dar, bei dem alles von Hand gefertigt werden muss.

var canvasgrp = svgContainer.append("g") 
     .attr("id","Cgrp") 
     ...snipped 
    ); 

    var BA = canvasgrp.append("rect") 
     .attr("id","BA") 
     ...snipped); 

    var BB = canvasgrp.append("rect") 
     .attr("id","BB") 
     ...snipped); 

    var BC = canvasgrp.append("text") 
     .attr("id","BC") 
     ...snipped 
     .text("These boxes drawn directly to SVG canvas"); 

erstellen <defs> Abschnitt, auch die gleiche komplexe Hierarchie enthält, so dass der Inhalt nicht wiedergegeben werden. Die oberste Ebene der Hierarchie ist 'USEgrp'.

var reusables = svgContainer.append("defs") 

    var USEgrp = reusables.append("g") 
     .attr("id","Ugrp") 
    var AA = USEgrp.append("rect")...etc 
    var AB = USEgrp.append("rect")...etc 
    var AC = USEgrp.append("text")...etc 

Directly USEgrp klonen, indem Code folgte eine neue eindeutige ID für die Gruppe und die Position zu setzen es:

var clonedInst1 = svgContainer 
    .append(function(){ return sidingTemplate.cloneNode(true); }) 
    .attr("id","clonedInst1") 
    .attr("transform","translate(20,380)"); 

eine Objektmethode verwenden USEgrp zu klonen, mit der Möglichkeit, ein Objekt zu bilden mit Methoden zum Erstellen, Steuern und Ablegen einer komplexen Hierarchie, die einmal im Abschnitt <defs> definiert ist. Das war mein Ziel.

var boxCollection = { 
     new: function (parent) { 
     var defaultID = "instance"; 
     var ID = '_'+ defaultID + "-" + Math.random().toString(36).substr(2, 9); 
     var template = document.getElementById("Ugrp"); 
     var objInst = svgContainer.append(function(){ return template.cloneNode(true); }) 
     .attr("id",ID) 
     .attr("transform","translate(20,140)"); 
     } 

zusammen mit var newInstance = boxCollection.new("svgContainer"); es zu verwenden, um eine Kopie zu instanziieren und richtet ihn auf.

Schließlich versuchte ich den Befehl .append('use'), der sich als fast völlig ungeeignet erwies, um verschiedene Instanzen einer komplexen Hierarchie zu erzeugen, in der jede Instanz eine vorhersehbare Anpassung erforderte.Firefox erlaubte pro Instanz Änderungen an der Füllung und dem Strich des Rechtecks, aber nicht an dem Text (soweit ich das beurteilen konnte), während Chrome den Text änderte und die Füllung und den Strich (mit viel Flackern) aber nur für alle erlaubte Instanzen des definierten Objekts gleichzeitig.

var inst1 = svgContainer.append("use") 
     .attr("xlink:href","#Ugrp") 
     .attr("id","inst1") 
     .attr("transform","translate(20,260)"); 

testete ich die Möglichkeit, die Rechtecke und Textereignisse mithilfe von Rollover und Rollout für den Zugriff auf die Füllungen, Striche, Schlaganfall Breiten & Text ändern und wiederherzustellen.

Der Code auf https://jsfiddle.net/nohjose/1mktmbvp/9/

Verwandte Themen