Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matrix scale/translate from point

I'm attempting to scale an image and have it translate correctly from an origin point (basically a pinch to zoom). I'm trying to find a solution that doesn't involve changing transform-origin, because it will complicate finding the left/top edges of the picture, which I'm using for more than just this problem.

This is more of a math problem. I'm having trouble coming up with an equation to determine how much to translate the image, based on an origin. The current equation I have worked out does not scale from a point correctly. In regards to the demo, the image should blow up from the mouse pointer when scrolling with the mouse.

I'm not looking for a workaround, or an alternative design. As stated before, I can't modify the transform-origin property.

Demo: https://jsfiddle.net/dook/ort0efjd/

Matrix transform function

function transform() {
  var matrix = [dim.new_scale, 0, 0, dim.new_scale, dim.new_x, dim.new_y].join(",");

  image_center.css({
    "transform": "matrix(" + matrix + ") translate3d(0, 0, 0)",
    "-webkit-transform": "matrix(" + matrix + ") translate3d(0, 0, 0)",
    "-moz-transform": "matrix(" + matrix + ") translate3d(0, 0, 0)",
  });
}

Mousewheel event

// Determine mousewheel pointer in relation to picture origin
var offset = image_center.offset();
var originX = ev.originalEvent.pageX - offset.left;
var originY = ev.originalEvent.pageY - offset.top;

// truncated --- new_scale is modified

// Translate based on pointer origin -- This is where I need help
dim.new_x = originX + dim.height * (dim.new_scale - 1);
dim.new_y = originY + dim.height * (dim.new_scale - 1);

// truncated -- Keep image within constraints

transform(); // Applies everything in dim to CSS transform matrix
like image 760
dook Avatar asked Jan 11 '16 03:01

dook


People also ask

How do you translate a 2x2 matrix?

A translation cannot be represented by a 2x2 matrix. To see why this is so we must realise that a 2x2 matrix is actually generating a linear combination of its inputs, i.e.: In such a combination, there is no way to represent a term which is independent of both x and y.

How do you translate a 2D matrix?

You can translate a point in 2D by adding translation coordinate (tx, ty) to the original coordinate X,Y to get the new coordinate X′,Y′. The pair (tx, ty) is called the translation vector or shift vector. The above equations can also be represented using the column vectors.


1 Answers

One simple approach is to create an off-screen object and center it's transform-origin. Apply the scaling to this object.

Then copy the Matrix transformation from the off-screen element to the on screen element and you should have the correct scale.

Here are some image prototypes to copy the matrix:

HTMLImageElement.prototype.getMatrix = function() {
    var st = window.getComputedStyle(this, null);
    return st.getPropertyValue("-webkit-transform") ||
        st.getPropertyValue("-moz-transform") ||
        st.getPropertyValue("-ms-transform") ||
        st.getPropertyValue("-o-transform") ||
        st.getPropertyValue("transform") ||
        'none';
};

HTMLImageElement.prototype.setMatrix = function(matrix) {
    this.style.webkitTransform = 
    this.style.msTransform = 
    this.style.MozTransform = 
    this.style.OTransform = 
    this.style.transform = 
         matrix;
  return this;
};

getMatrix returns a matrix string. setMatrix takes a matrix string.

targetImage.setMatrix(sourceImage.getMatrix())

were targetImage is the displayed image and sourceImage is the off-screen image

like image 134
tnt-rox Avatar answered Sep 20 '22 14:09

tnt-rox