HTML5 Canvas obtenir la matrice de transformation?

y a-t-il un moyen d'obtenir la matrice de transformation actuelle pour une toile? Il y a un contexte.setTransform() de la fonction, mais il ne semble pas être un getTransform() équivalent à ce que je peux dire.

plus précisément, je veux obtenir l'échelle actuelle et les éléments de traduction de la matrice. Google a été très peu utile avec cela.

25
demandé sur ellisbben 2011-09-13 05:18:00
la source

3 ответов

Non, il n'existe tout simplement pas. :(

la plupart des bibliothèques canavs (comme cake.js) ont au lieu de cela mis en place leur propre classe de matrice pour garder la trace de la matrice de transformation actuelle.

le créateur du gâteau.js pensé qu'il n'y a pas moyen d'obtenir la matrice actuelle était assez ridicule pour justifier un rapport de bug à ce sujet. malheureusement, c'était en 2007 et il n'y a eu aucun effort pour inclure un getCurrentTransform dans le specs.

Edit: j'ai créé une classe de Transformation simple qui vous permettra de créer facilement votre propre getCanvas() ou garder la trace de la matrice de la toile côte à côte. c'est Ici. j'espère que ça aide!

Édition Juin 2012: La nouvelle spécification inclut un moyen d'obtenir la transformation actuelle de la matrice! context.currentTransform peut être utilisé pour obtenir ou définir la matrice de transformation. Malheureusement, aucun navigateur ne l'a encore implémenté., si Firefox n'ont spécifiques au vendeur mozCurrentTransform propriété sur son contexte. Donc, vous ne pouvez pas l'utiliser tout de suite, mais il est dans la spécification, si tôt!

28
répondu Simon Sarris 2017-04-27 21:28:09
la source

EDIT (6/27/2016): le WHATWG spec a maintenant une fonction getTransform() au lieu de currentTransform et il semble sémantiquement clair que getTransform() crée un copier de la matrice de transformation. Dirait qu'il manque encore de grands navigateurs.

MODIFIER, de nouveau:

Voici un accidenté de la mise en œuvre:

//in theory, SVGMatrix will be used by the Canvas API in the future;
//in practice, we can borrow an SVG matrix today!
var createMatrix = function() {
  var svgNamespace = "http://www.w3.org/2000/svg";
  return document.createElementNS(svgNamespace, "g").getCTM();
}

//`enhanceContext` takes a 2d canvas context and wraps its matrix-changing
//functions so that `context._matrix` should always correspond to its
//current transformation matrix.
//Call `enhanceContext` on a freshly-fetched 2d canvas context for best
//results.
var enhanceContext = function(context) {
  var m = createMatrix();
  context._matrix = m;

  //the stack of saved matrices
  context._savedMatrices = [m];

  var super_ = context.__proto__;
  context.__proto__ = ({

    //helper for manually forcing the canvas transformation matrix to
    //match the stored matrix.
    _setMatrix: function() {
      var m = this._matrix;
      super_.setTransform.call(this, m.a, m.b, m.c, m.d, m.e, m.f);
    },

    save: function() {
      this._savedMatrices.push(this._matrix);
      super_.save.call(this);
    },

    //if the stack of matrices we're managing doesn't have a saved matrix,
    //we won't even call the context's original `restore` method.
    restore: function() {
      if(this._savedMatrices.length == 0)
        return;
      super_.restore.call(this);
      this._matrix = this._savedMatrices.pop();
      this._setMatrix();
    },

    scale: function(x, y) {
      this._matrix = this._matrix.scaleNonUniform(x, y);
      super_.scale.call(this, x, y);
    },

    rotate: function(theta) {
      //canvas `rotate` uses radians, SVGMatrix uses degrees.
      this._matrix = this._matrix.rotate(theta * 180 / Math.PI);
      super_.rotate.call(this, theta);
    },

    translate: function(x, y) {
      this._matrix = this._matrix.translate(x, y);
      super_.translate.call(this, x, y);
    },

    transform: function(a, b, c, d, e, f) {
      var rhs = createMatrix();
      //2x2 scale-skew matrix
      rhs.a = a; rhs.b = b;
      rhs.c = c; rhs.d = d;

      //translation vector
      rhs.e = e; rhs.f = f;
      this._matrix = this._matrix.multiply(rhs);
      super_.transform.call(this, a, b, c, d, e, f);
    },

    //warning: `resetTransform` is not implemented in at least some browsers
    //and this is _not_ a shim.
    resetTransform: function() {
      this._matrix = createMatrix();
      super_.resetTransform.call(this);
    },

    __proto__: super_
  });

  return context;  
};

modifier: L'attribut currentTransforma été ajouté à la spec; il est signalé à être pris en charge dans Firefox et Opera. J'ai vérifié sur Firefox et l'ai trouvé vendeur-préfixé comme mozCurrentTransform. Vraisemblablement, il peut être utilisé pour obtenir et définir la matrice de transformation.

DES CHOSES PLUS ANCIENNES, ENCORE EN GRANDE PARTIE VRAIES:

si vous voulez obtenir la matrice de transformation actuelle, vous devrez en tenir compte vous-même. Une façon de faire serait d'utiliser L'héritage prototypique de Javascript pour ajouter un getMatrix() méthode et d'augmenter les méthodes qui modifient l' matrice:

var context = canvas.getContext("2d");
var super = context.__proto__;
context.__proto__ = ({

  __proto__: super, //"inherit" default behavior

  getMatrix: function() { return this.matrix; },

  scale: function(x, y) {

    //assuming the matrix manipulations are already defined...
    var newMatrix = scaleMatrix(x, y, this.getMatrix());
    this.matrix = newMatrix;
    return super.scale.call(this, x, y);
  },
  /* similar things for rotate, translate, transform, setTransform */
  /* ... */
});
context.matrix = makeDefaultMatrix();

pour bien faire les choses, vous devez suivre plusieurs matrices lorsque le save() et restore() méthodes du contexte sont utilisés.

11
répondu ellisbben 2016-06-27 23:34:48
la source

comme @ellisbben l'a mentionné à peu près la seule façon que vous pouvez faire ceci est de garder une trace vous-même. Vous pouvez trouver une solution ici. Il enveloppe le contexte dans une enveloppe et ensuite gère les parties désagréables là.

2
répondu Juho Vepsäläinen 2011-09-13 09:58:07
la source

Autres questions sur