2015-12-26 12 views
7

Diciamo che ho un elemento SVG con percorsi per tutti gli stati degli Stati Uniti.Creare un componente SVG interattivo utilizzando React

<svg> 
    <g id="nh"> 
     <title>New Hampshire</title> 
     <path d="m 880.79902,142.42476 0.869,-1.0765 1.09022,..." id="NH" class="state nh" /> 
    </g> 
    ... 
</svg> 

I dati SVG viene salvato in un file separato con un'estensione .svg. Diciamo che voglio creare un componente React di quella mappa, con il controllo completo su di esso in modo che possa modificare lo stile dei singoli stati sulla base di alcuni input esterni.

Utilizzando Webpack, per quanto posso dire, ho due opzioni per il caricamento del markup SVG: inserirla come markup grezzo utilizzando il raw-loader e creare un componente utilizzando dangerouslySetInnerHTML:

var InlineSvg = React.createClass({ 
    render() { 
    var svg = require('./' + this.props.name + '.svg'); 
    return <div dangerouslySetInnerHTML={{__html: svg}}></div>; 
    } 
}); 

o manualmente convertire il markup per valida JSX:

var NewComponent = React.createClass({ 
    render: function() { 
    return (
     <svg> 
      <g id="nh"> 
       <title>New Hampshire</title> 
       <path d="m 880.79902,142.42476 0.869,-1.0765 1.09022,..." id="NH" className="state nh" /> 
      </g> 
      ... 
     </svg> 
    ); 
}); 

Infine, diciamo che, oltre alla mappa in formato SVG, c'è un semplice elenco HTML di tutti gli stati. Ogni volta che un utente passa sopra un elemento della lista, il corrispondente percorso SVG dovrebbe spostare il colore di riempimento.

Ora, quello che non riesco a capire è come aggiornare il componente React SVG per riflettere lo stato stazionario. Certo, posso raggiungere il DOM, selezionare lo stato SVG in base al nome della classe e cambiarne il colore, ma questo non sembra essere il modo "reagire" per farlo. Un dito puntato sarebbe molto apprezzato.

PS. Sto usando Redux per gestire tutte le comunicazioni tra i componenti.

risposta

3

Hai bisogno di fare due cose:

1) Impostare un listener di eventi su ogni elemento della lista di informare la vostra applicazione della voce evidenziata.

<li 
    onMouseOver={() => this.handleHover('NH')} 
    onMouseOut={() => this.handleUnhover()} 
> 
    New Hampshire 
</li> 

2) Acquisire i dati e propagarli come componenti SVG.

Questa è la parte più complicata, e si tratta di come hai strutturato la tua app.

  • Se l'intera applicazione è un singolo componente Reagire, quindi handleHover sarebbe semplicemente aggiornare lo stato del componente
  • Se la vostra applicazione è suddivisa in più componenti, quindi handleHover innescherebbe una callback passato come un puntello

Supponiamo che quest'ultimo. I metodi dei componenti potrebbe essere simile a questo:

handleHover(territory) { 
    this.props.onHighlight(territory); 
} 

handleUnhover() { 
    this.props.onHighlight(null); 
} 

Supponendo di avere un componente principale, che contiene sia la mappa SVG e l'elenco, potrebbe essere simile a questa:

class MapWrapper extends React.Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      highlighted: null; 
     }; 
    } 

    setHighlight(territory) { 
     this.setState({ 
      highlighted: territory 
     }); 
    } 

    render() { 
     const highlighted = { this.state }; 
     return (
      <div> 
       <MapDiagram highlighted={highlighted} /> 
       <TerritoryList onHighlight={(terr) => this.setHighlight(terr)} /> 
      </div> 
     ); 
    } 

} 

La chiave qui è la variabile di stato highlighted. Ogni volta che si verifica un nuovo evento di hover, highlighted cambia di valore. Questa modifica attiva un nuovo rendering e il nuovo valore viene passato a che può quindi determinare quale parte dell'SVG deve evidenziare.

+0

Sembra fantastico, grazie! Una cosa però, la chiave 'territory' nell'oggetto stato in' setHighlight' dovrebbe essere 'evidenziato' giusto?In questo modo corrisponde al nome della chiave nell'oggetto stato originale. –

+0

Buon posto. Fisso. –

+1

Per la parte "propagate a SVG" ho creato https://www.npmjs.com/package/react-samy-svg. Semplifica il caricamento e la manipolazione degli attributi degli elementi svg. –

Problemi correlati