我需要能够为SVG元素

时间:2016-06-06 12:37:58

标签: css svg angular

我正在创建一个包含Angular2指令的应用程序,该指令显示包含路径元素的SVG图像,这些路径元素在单击时会将事件发送到应用程序组件。这很好用。但是,我还希望能够通过从指令外的选择器更改CSS类来突出显示这些元素。

作为一个简单的例子,我已经包装了#39;将http://www.petercollingridge.co.uk/sites/files/peter/Australia_compass_with_names.svg的AU映射的简化版本转换为指令,并添加代码以将单击事件添加到SVG元素,如下所示:

import {Component, Renderer, ElementRef, Input, Output, EventEmitter, OnInit, OnChanges, OnDestroy} from '@angular/core';

@Component({
    selector: '[map]',
    template: `
    <svg>
        <g id="map-transform" transform="matrix(1 0 0 1 0 0)">
            <path
            id="WA"
            class="territory"
            fill="#a9a9a9"
            d="m 38.3, 168.2 c -1.9,-0.6 -3.6,-1.1 -3.8,-1.3 -0.2,-0.2 0.8,-2.5 2.25,-5.2 1.4,-2.7 2.6,-5.5 2.6,-6.2 0,-0.8 -1.8,-4.25 -4,-7.7 -2.2,-3.5 -4,-7.1 -4,-8.1 l 0,-1.8 -6.4,-10.3 -6.4,-10.3 1.8,0 -7,-14.8 0.2,-7.3 c 0.1,-4 0.1,-8.9 0.1,-10.9 l -0.1,-3.5 5.5,-6 c 3,-3.3 5.5,-6.3 5.5,-6.7 0,-0.4 0.9,-0.8 1.9,-0.8 l 1.9,0 9.8,-6.1 13.8,-2.2 4.1,-2.6 8.4,-15 -1.2,-3 3.3,-5 1.8,1.1 4,-2.5 0,-3.1 4.6,-4.3 8.5,0 3.4,3.8 c 1.9,2.1 3.4,4.3 3.4,5 l 0,1.3 2.5,-0.6 L 97.5,33.2 c 0,38.3 0,77 0,113.8 l -4.6,1.6 -4.5,2.2 -2.3,5.6 -1.6,0.5 c -0.9,0.3 -4.8,1 -8.6,1.6 l -7,1.1 -8.2,4.9 -8.2,4.9 -5.3,0 c -2.9,0 -6.9,-0.5 -8.8,-1.1 z"/>

        <path
            id="QLD"
            class="territory"
            fill="#a9a9a9"
            d="m 200.3,123.9 c -11.8,-0.7 -14.8,-0.8 -22.8,-1.3 0,-8.5 0,-21 0,-21 l -16,0 c 0,0 0,-39.3 0,-60 l 6,3.5 5.2,3.5 4.4,0 6,-9.8 3.4,-24.6 2.8,-5.7 c 1.6,-3.1 3.3,-6 3.9,-6.3 l 1,-0.6 1.8,4.3 c 1,2.4 2.2,6.6 2.6,9.3 0.4,2.8 1.2,7.1 1.7,9.8 l 1,4.8 4.8,0 3.2,5 2.8,11 c 1.5,6.1 3.3,11.7 4,12.5 0.6,0.8 3.4,2.9 6.2,4.6 l 5,3.2 5,10 3.8,1 1.2,5.2 11.2,14.8 1.2,7.1 c 0.7,3.9 1.5,8.7 1.9,10.8 l 0.6,3.7 -1.3,5.1 -4.6,-1.1 -1.3,1.6 c -1.6,2 -3.7,2 -4.4,0.1 l -0.6,-1.5 -2.4,0 c -1.3,0 -4.3,0.7 -6.7,1.5 -2.3,0.8 -5.4,1.4 -6.9,1.3 -1.4,-0.1 -12.3,-0.7 -24.1,-1.4 z"/>    

        <path
            id="VIC"
            class="territory"
            fill="#a9a9a9"
            d="m 219.5,177.3 0.8,1 c 0,0.6 2.3,2.7 5,4.8 l 5,3.8 -11.4,3.4 -5.7,5.4 -6.9,-3.7 -2.8,1.4 c -1.5,0.8 -3,1.5 -3.3,1.6 -0.3,0.1 -2.3,-0.9 -4.5,-2.2 c -2.2,-1.3 -6.3,-3.1 -9,-4 l -5,-1.6 -2.3,-2 -2.1,-2.1 c 0,-9 0,-17.9 0,-26.6 l 3.9,-1.3 3.1,0 1.6,3.4 1.9,0.5 2.4,0.5 1.5,0.9 4.7,6 3.2,3.9 c 3.2,0.9 6.5,1.7 9.2,2.4 3,0.8 4.7,0.9 6.2,1 l 2.9,2.6"/>

        <path
            id="NSW"
            class="territory"
            fill="#a9a9a9"
            d="m 220.5,176.4 -2.4,-2.7 -2.4,-1.5 c -2.1,-0.3 -6.2,-1.1 -9.1,-1.8 l -5.4,-1.4 -8.2,-10.4 -2.8,-0.7 -2.8,-0.7 -1,-1.9 -1,-1.9 -3.9,0 -4,1.5 0,-30.9 c 5.8,0.4 22.5,1.4 25.3,1.6 l 23.5,1.4 4.8,-1.2 c 4.6,-1.1 5.7,-2.1 8.3,-2 0,0 0.9,2.3 1.9,2.8 1.1,0.5 2.5,0.1 3.7,-0.3 1.1,-0.4 2,-2 3.1,-1.8 l 2.8,0.5 -1.3,5.1 c -0.7,2.7 -2.1,7.5 -2.9,10.9 -1.8,8.3 -3.1,11.6 -5.3,13.4 l -1.8,1.5 -4.1,12.5 c -2.2,6.9 -4.2,13.5 -4.4,14.7 l -0.3,2.2 -5.3,-4 -4.4,-4.2" />

        <path
            id="SA"
            class="territory"
            fill="#a9a9a9"
            d="m 176,181 -6.8,-9.4 0.7,-3.7 0.7,-3.7 -5.6,-6 -2.2,0.8 0.7,-7.8 -1.1,0 c -1.1,0 -2.2,1.1 -4.6,4.5 l -1.4,2 1,-4.8 c 0.6,-2.7 0.8,-5 0.6,-5.3 -0.8,-0.8 -6.1,2.5 -7.9,4.8 -0.9,1.2 -1.9,2 -2.1,1.8 -0.2,-0.3 -1.6,-2.6 -3.1,-5.2 l -2.7,-4.7 -11.4,-2.6 -19.2,0.2 -5.8,2.6 C 102.7,146.2 99,147.2 99,147 l 0,-44 77,0 z"/>    

        <g
            id="NT"
            class="territory"
            fill="#a9a9a9">
            <path
                d="m 99,33 3.9,0.4 c 2,0.2 4.4,-0.5 5.5,-1 l 1.9,-1 0,-2.5 0,-2.5 -2,0 0,-4 1.9,-1.7 c 1,-0.9 1.7,-2 1.5,-2.4 l -0.5,-0.7 6.8,-4.2 11.5,-1.4 0.8,-2.4 -5.6,-3 1.7,0 c 0.9,0 2,0.4 2.3,1 0.3,0.6 1.2,0.9 1.8,0.8 0.6,-0.1 3.4,0.8 6.2,2.1 l 5,2.4 7.5,0 0,3.7 -4.2,4 1.2,3.2 -3,5.8 17,11.2 0,60.8 -61,0 z" />
            <path
                d="m 115,8.7 -2.8,-0.4 0.8,-2.4 4.2,0 c 2.3,0 4.2,0.2 4.2,0.5 0,0.8 -2.3,3 -2.9,2.8 -0.3,-0 -1.8,-0.3 -3.4,-0.6 z"/>
        </g>

        <g
            id="TAS"
            class="territory"
            fill="#a9a9a9">
            <path
                d="m 202.7,223.9 -2.7,-3.6 -0.1,-3.4 c -0.1,-1.9 -0.4,-3.7 -0.8,-4.1 -0.4,-0.4 -0.7,-1.8 -0.7,-3.1 l 0,-2.3 1,0 c 0.6,0 2.4,0.7 4.2,1.6 l 3.1,1.6 9.6,-1.2 0,7.2 -3.4,5.8 -2.6,-1 -1.7,3 c -0.9,1.6 -2,3 -2.4,3 -0.4,0 -1.9,-1.6 -3.4,-3.6 z" />
        </g>

        <g 
            id="ACT"
            class="territory"
            fill="#a9a9a9">
            <path
            stroke-width="1.5"
            stroke="#ffffff"
            d="m 222,165.7 0.1,2.8 0.4,1.4 1,1 0.4,-0.9 0.2,2.9 2.6,1.6 1,-2.2 0,-3.6 c 0,0 -0.3,-0.5 -0.6,-1.1 0.8,-0.3 1.2,0.1 1.2,0.1 l 0.1,-3.4 1.5,-2 2.4,0.3 0.5,-1 -2.7,-1.3 c 0,0 -0.7,-1.8 -1.8,-2.4 -1.6,1.1 -4,2 -5.2,3.9 -0.4,0.7 -0.5,2.3 -0.5,2.3 z"/>
        </g>
    </g>
</svg>
`
})
export class Map implements OnInit, OnDestroy {
    @Input() public territory:string;
    @Output() territorySelected = new EventEmitter<any>();
    private element:ElementRef;
    private ctx: any;

    listenFunc: Function;   
    globalListenFunc: Function;

    constructor(elementRef: ElementRef, renderer: Renderer) {

        this.listenFunc = renderer.listen(elementRef.nativeElement, 'click', (event) => {
        this.territorySelected.emit(event);
        });
    }
    ngOnInit() {
        console.log(this.ctx);
    }
    removeListeners() {
        this.listenFunc();
        this.globalListenFunc();
    }

    highlightTerritory(id: string)
    {
        console.log('highlighting territory ' + id);
        // need to understand how to access the elements in the SVG and update the CSS class to highlight the territory
    }
    public ngOnChanges(changes: {[propName: string]: any}) {        
        if (changes['territory']) {         
            this.highlightComponent(changes['territory'].currentValue);
        }
    }

    ngOnDestroy() {
        // Remove the listeners!
        this.listenFunc();
        this.globalListenFunc();
    }
}

我希望能够允许用户从应用的其他子组件中选择区域,例如包含所有区域的下拉列表,并以与点击它相同的方式突出显示地图中的区域在地图上会这样做。对输入进行编码并捕获更改非常简单。它找到了相关的SVG元素,并更新了我所挣扎的填充色。

非常感谢任何有关在NG2中实现这一目标的最佳方式的帮助(使用最佳实践!)。

2 个答案:

答案 0 :(得分:2)

您可以使用

(click)="highlightTerritory('XXX')"

[class.className]="selected == 'XXX'"

获取所选区域并更新所选区域的类别。

Plunker example

我从你的代码中无法理解你需要什么

@Output() territorySelected = new EventEmitter<any>();

您可以使用它将更改绑定到父级的功能

<map (territorySelected)="dosSomething($event)"></map> 

但我无法从你的问题中看出这是不是意图。如果没有,那么你不需要它(也不是'this.territorySelected.emit(id);`)

答案 1 :(得分:1)

我找到了一个简单的问题解决方案,即使用d3.js然后使用select函数。

我在app.component.js文件中包含了对d3.js的引用,然后将以下声明添加到map.component.ts文件中:

declare var d3:any;

最后,我将highlightTerritory函数更改为:

highlightTerritory(id: string) {
    console.log('highlighting ' + id);
    d3.selectAll('.territory').style('fill', '#a9a9a9');
    d3.select("#" + id).style("fill", "purple");
}

这就像我希望的那样有效。