向SVG动态添加元素



我使用的是创建的映射的修改版本https://azgaar.github.io/Fantasy-Map-Generator/作为Angular(9(模板svg。该文件长达12000行,因此大大降低了编译速度。当枚举所有5248个网格单元格(通过按快捷键e显示在链接的地图上(并为每个单元格设置id时,我的性能进一步降低。不幸的是,这对于我的用例来说是必要的。

由于这张地图有12种不同类型的覆盖组(例如城市、湖泊、路线、海岸线(,并且不是一次需要所有的覆盖组,我想我可以把这个.svg减少到最小skeletton,一旦用户选择这样做,就可以通过REST请求不同的元素。

下面将把正确的行(与从原始svg中裁剪出来的行完全一样(添加到模板中。然而,这群人不会出现。我需要重新发送整个SVG吗?我该怎么做?

public async toggleVisibility(elementToDisplay): void {
try {
// if elementToDisplay already is part of the .svg, set it visible / invisible here
} catch(_) {
this._http.get<string>(`${environment.backend}/worldmap/data/${elementToDisplay}`, { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }).toPromise()
.then((res: string) => {
// as an unrelated issue: my spring application is returning a String, yet angular would not resolve this promise
}.catch((rej: any) => {
const parser = new DOMParser();
const doc = parser.parseFromString(rej.error.text, "image/svg+xml");
this.svgMap.nativeElement.children.namedItem('viewbox').appendChild(doc.lastChild);
}
}

调用之前的SVG看起来类似于以下内容:

<svg _ngcontent-lys-c61 xmlns:dc="http://purl.org/dc/elements/1.1/" 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" 
[...]
id="worldmap"
width="100%" height="100%"
background-color="#000000"
viewBox="145 45 1000 1000">
[...]
<g _ngcontent-lys-c61 id="viewbox" style="cursor:default;">
<g _ngcontent-lys-c61 id="ocean"> [...] </g>
<g _ngcontent-lys-c61 id="lakes"> [...] </g>
<g _ngcontent-lys-c61 id="landmass">[...] </g>      
[...]
</g>
</svg>

在呼叫之后,在陆地群之后有一个额外的<g id="biomes"> [...] </g>(如果我明显要求生物群落(。我能发现的唯一区别是_ngContent-lys-c61不见了。然而,changeDetectorRef.detectChanges((事件不会导致显示该组。它也不超越其他东西。我在chrome调试器中删除了所有组,但生物群落仍然没有出现。

顺便说一句:我发现了很多类似的问题,都是使用D3.js的。我不想包括这些。

当我终于找到解决方案时,我会完全删除并编辑这个答案。这个问题与发送一个无法转换为json的String有关,我正在定义一个json头作为标准响应类型。

长话短说,我将展示向现有svg动态添加svg组的整个过程。技术:Angular&弹簧引导

角度:

// component.ts
@ViewChild('svg') public svgMap: ElementRef<SVGElement>;
// function
const svg = await this._http.get(`pathToServer`, { responseType: 'text' }).toPromise();
const document: Document = new DOMParser().parseFromString(svg, "image/svg+xml");
const group: HTMLCollectionOf<SVGElement> = document.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'g');
const groupToAttach: SVGElement = this.svgMap.nativeElement.children.namedItem('myGroup') as SVGElement;
groupToAttach.appendChild(group.namedItem('paths'))
// component.svg
<svg id="svg">
<g id="myGroup"></g>
</svg>

弹簧套:

// imports:
import java.io.InputStreamReader;
import java.io.BufferedReader;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
// class-level
@Autowired
private ResourceLoader resourceLoader;
//function
@GetMapping(path = "endpoint/{element}")
public ResponseEntity<String> function(@PathVariable String element) throws Exception {
Resource elementResource = resourceLoader.getResource("classpath:/" + element + ".svg");
InputStreamReader is = new InputStreamReader(elementResource.getInputStream(), StandardCharsets.UTF_8);
String data = new BufferedReader(is).lines().collect(Collectors.joining("n"));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("image/svg+xml"));
return ResponseEntity.ok().headers(headers).contentLength(data.length()).body(data);

懒惰加载svg

<svg xmlns="http://www.w3.org/2000/svg">
<g id="paths">
// ...
</g>
</svg>

最新更新