Substituindo d3.transform em D3 v4

No D3.js v4, o método d3.transform foi removido, sem qualquer sugestão sobre como substituí-lo. Alguém sabe como replace a seguinte instrução D3.js v3?

d3.transform(String).translate; 

Edit 2016-10-07: Para uma abordagem mais geral, ver anexo abaixo.


De acordo com o changelog, ele desapareceu. Existe uma function em transform/decompose.js , que faz os cálculos para uso interno. Infelizmente, não é exposto para uso externo.

Dito isto, isso é feito facilmente, mesmo sem colocar qualquer D3 para usar:

 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 você extrair o d3 v4 até o npm, poderá importar o arquivo src/transform/parse diretamente e chamar parseSvg :

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

Em elementos que possuem o listener de zoom d3.js – geralmente o elemento anexado ao elemento svg – você pode usar essa chamada para obter os atributos de transformação fora da function de zoom:

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

Isso retorna os mesmos valores de quando se chama d3.event.transform dentro da própria function de evento de zoom.

Chamar d3.event.transform fora da function de evento de zoom ocorrerá: Uncaught TypeError: Cannot read property 'transform' of null

Eu tenho que usar d3.zoomTransform para permitir pan e zoom de botões fora do gráfico.

Estou um pouco atrasado para a festa, mas eu tinha um código que era benéfico para mim, espero que isso ajude você também.

O código acima por @altocumulus é bastante completo e funciona como um encanto. No entanto, ele não satisfez minhas necessidades, pois eu estava fazendo os cálculos manualmente e precisava alterar algumas propriedades da transformação da forma mais indolor possível.

Isso pode não ser a solução para todos, mas foi perfeito para mim.

 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(',') + ")"; }, ''); } 

A coisa realmente boa com a primeira function é que eu posso alterar manualmente uma propriedade específica (por exemplo, rotação) e não ter que me preocupar com o modo como ela afeta a tradução ou qualquer outra coisa (ao girar em torno de um ponto), ao passo que d3.transform methods ou em d3.transform eles consolidam todas as propriedades em um valor.

Por que isso é legal?

Imagine um pouco de HTML

  

Usando d3.transfrom eu recebo:

Em forma de object

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

Em forma de string

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

O que é correto matematicamente, mas torna difícil para mim simplesmente remover o ângulo de rotação e a tradução que tinha que ser introduzida para girar este elemento em torno de um dado ponto.

Usando minha function _getTokenizedTransformAttributeValue

Em forma de object

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

Em forma de string usando a function _getStringFromTokenizedTransformAttributeObj

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

O que é perfeito porque agora quando você remove a rotação, seu elemento pode voltar para onde estava

Concedido, o código poderia ser mais limpo e os nomes das funções mais concisos, mas eu realmente queria colocar isso lá fora, para que outros pudessem se beneficiar dele.

Eu encontrei uma maneira de conseguir algo semelhante usando isso:

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

isso lhe dará access à posição x / y e largura / altura Você pode ver um exemplo aqui: https://bl.ocks.org/mbostock/1160929

Eu encontrei uma solução um pouco mais simples do que isso.

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

Nessa matriz você tem cordinagens e são equivalentes a x, y. (e === x, f === y). Não há necessidade de implementar sua própria funtion para isso.

baseVal é uma lista de transformações do elemento. Você não pode usar isso para o object sem a prévia transformação! (a lista estará vazia) Ou, se você fez muitas tranformações no object, a última posição estará no último elemento da lista baseVal.