Sostituire d3.transform in D3 v4

In D3.js v4 il metodo d3.transform è stato rimosso, senza alcun suggerimento su come sostituirlo. Qualcuno sa come sostituire la seguente istruzione D3.js v3?

d3.transform(String).translate; 

Modifica, 2016-10-07: per un approccio più generale vedi l’appendice qui sotto.


Secondo il changelog è sparito. Esiste una funzione in transform/decompose.js , che esegue i calcoli per uso interno. Purtroppo, non è esposto per uso esterno.

Detto questo, questo si può fare facilmente anche senza usare D3:

 function getTranslation(transform) { // Create a dummy g for calculation purposes only. This will never // be appended to the DOM and will be discarded once this function // returns. var g = document.createElementNS("http://www.w3.org/2000/svg", "g"); // Set the transform attribute to the provided string value. g.setAttributeNS(null, "transform", transform); // consolidate the SVGTransformList containing all transformations // to a single SVGTransform of type SVG_TRANSFORM_MATRIX and get // its SVGMatrix. var matrix = g.transform.baseVal.consolidate().matrix; // As per definition values e and f are the ones for the translation. return [matrix.e, matrix.f]; } console.log(getTranslation("translate(20,30)")) // simple case: should return [20,30] console.log(getTranslation("rotate(45) skewX(20) translate(20,30) translate(-5,40)")) 

Se si passa da d3 v4 a npm, è ansible importare direttamente il file src/transform/parse e chiamare parseSvg :

 // using es2015 modules syntax import { parseSvg } from "d3-interpolate/src/transform/parse"; parseSvg("translate(20, 20)"); 

Sugli elementi che hanno il listener di zoom d3.js su di essi – in genere l’elemento aggiunto all’elemento svg – puoi utilizzare questa chiamata per ottenere gli attributi di trasformazione al di fuori della funzione di zoom:

 var self = this; var t = d3.zoomTransform(self.svg.node()); // t = {k: 1, x: 0, y: 0} or your current transformation values 

Questo restituisce gli stessi valori di quando si chiama d3.event.transform all’interno della funzione di evento dello zoom stesso.

Chiamando d3.event.transform al di fuori della funzione dell’evento di zoom si verificherà l’errore: Uncaught TypeError: Cannot read property 'transform' of null

Devo usare d3.zoomTransform per consentire il panning e lo zoom da pulsanti esterni al grafico.

Sono un po ‘in ritardo per la festa, ma ho avuto un codice che mi è stato utile, spero che ti aiuti anche tu.

Il codice sopra di @altocumulus è abbastanza completo e funziona come un incantesimo. Tuttavia non soddisfaceva le mie esigenze poiché stavo facendo i calcoli a mano e avevo bisogno di alterare alcune proprietà di trasformazione nel modo più indolore ansible.

Questa potrebbe non essere la soluzione per tutti, ma era perfetta per me.

 function _getTokenizedTransformAttributeValue(transformStr) { var cleanedUpTransformAttrArr = transformStr.split(')', ).slice(0,-1); return cleanedUpTransformAttrArr.reduce(function(retObj, item) { var transformPair = item.split('('); retObj[transformPair[0]] = transformPair[1].split(','); return retObj; }, {}); } 

 function _getStringFromTokenizedTransformAttributeObj(transformAttributeObj) { return _.keys(transformAttributeObj).reduce(function(finalStr, key) { // wrap the transformAttributeObj[key] in array brackets to ensure we have an array // join will flatten the array first and then do the join so [[x,y]].join(',') -> "x,y" return finalStr += key + "(" + [transformAttributeObj[key]].join(',') + ")"; }, ''); } 

La cosa veramente grandiosa con la prima funzione è che posso modificare manualmente una proprietà specifica (ad es. Rotazione), e non dovermi preoccupare di come influisce su translate o qualsiasi altra cosa (ruotando attorno a un punto), mentre quando faccio affidamento sul costruito -in o anche d3.transform metodi che consolidano tutte le proprietà in un unico valore.

Perché è così bello?

Immagina un po ‘di HTML

  

Usando d3.transfrom ottengo:

In forma di object

 jr {rotate: 59.99999999999999, translate: [577.8600589984691, -37.88141544673796], scale: [1, 1], skew: 0, toString: function} 

In forma di corda

 "translate(577.8600589984691,-37.88141544673796)rotate(59.99999999999999)skewX(0)scale(1,1)" 

Il che è matematicamente corretto, ma rende difficile per me rimuovere semplicemente l’angolo di rotazione e la traduzione che è stata introdotta per ruotare questo elemento attorno ad un dato punto.

Utilizzo della funzione _getTokenizedTransformAttributeValue

In forma di object

 {translate: ["542.8228777985075", "0"], rotate: ["60", " 50.324859619140625", " 011.402383210764288"]} 

In formato stringa utilizzando la funzione _getStringFromTokenizedTransformAttributeObj

 "translate(542.8228777985075,0)rotate(60, 50.324859619140625, 011.402383210764288)" 

Il che è perfetto perché ora quando rimuovi la rotazione, il tuo elemento può tornare dove era

Certo, il codice potrebbe essere più pulito e i nomi delle funzioni più concisi, ma volevo davvero farlo in modo che altri potessero trarne beneficio.

Ho trovato un modo per ottenere qualcosa di simile usando questo:

 d3.select(this).node().getBBox(); 

questo ti darà accesso alla posizione x / y e alla larghezza / altezza Puoi vedere un esempio qui: https://bl.ocks.org/mbostock/1160929

Ho trovato una soluzione un po ‘più semplice di quella.

 selection.node().transform.baseVal[0].matrix 

In questa matrice hai le ordinate e ef che sono equivalenti a x, y. (e === x, f === y). Non c’è bisogno di implementare la tua personale funzione per questo.

baseVal è una lista di trasformazioni dell’elemento. Non puoi usarlo per l’object senza la trasformazione precedente! (la lista sarà vuota) Oppure se hai fatto molte trasformazioni all’object, l’ultima posizione sarà sotto l’ultimo elemento della lista BaseVal.