将比例和旋转应用于特定点 - Javascript

时间:2015-05-13 16:21:37

标签: javascript math rotation transform scale

我们在缩放和旋转相对于另一个div的点时遇到了一些麻烦。基本上我们有2层,一层带有图像(svg),另一层带有放置在图像上的图标。

我们已经能够根据图像的旋转(和位置)旋转图标,比例为1。 我们已经能够根据图像的比例(和位置)缩放图标,旋转为零。

但是很快就会缩放和旋转,事情会变得混乱......

这是翻译一个点(绝对)以匹配图像矩阵的代码:

self.getViewportCoordinatesFromPoint = function(pointX, pointY) {

        var centerVal = {
            x: gestureValues.centerVal.x(),//scaled centerX
            y: gestureValues.centerVal.y(),//scaled centerY
            normalX: gestureValues.centerVal.normalX(),//original center
            normalY: gestureValues.centerVal.normalY()//original center
        };

        var output = {
            x:pointX,
            y:pointY
        };

        //Image rotation angle
        var angle = gestureValues.mapRotation * Math.PI / 180.0;

        //Scale no rotate
        var scaledPoint = {};

        var normX = (centerVal.normalX - output.x); //center of map to X axis
        var ratioX = normX / centerVal.normalX; //percentage of the distance compared to center point.
        var scaleX = centerVal.x * ratioX; //Scaled value of x from the center of scaled map
        scaledPoint.x = centerVal.normalX - scaleX; // subtract the original map width from scaled value

        var normY = (centerVal.normalY - output.y);
        var ratioY = normY / centerVal.normalY;
        var scaleY = centerVal.y * ratioY;
        scaledPoint.y = centerVal.normalY - scaleY;

        output = scaledPoint;

        var rotatedPoint = {};
        rotatedPoint.x = Math.cos(angle) * (output.x - centerVal.x) - Math.sin(angle) * (output.y - centerVal.y) + (centerVal.x);
        rotatedPoint.y = Math.sin(angle) * (output.x - centerVal.x) + Math.cos(angle) * (output.y - centerVal.y) + (centerVal.y);

        output = rotatedPoint;

        //Add gesture values
        output.x = ((output.x + gestureValues.mapXY[0]));
        output.y = ((output.y + gestureValues.mapXY[1]));

        return output;
    };

非常感谢任何帮助!

提前致谢!

1 个答案:

答案 0 :(得分:2)

好的,看看这个小提琴中的第32到65行。诀窍是计算距离中心*的距离,然后将其应用于旋转计算!

https://jsfiddle.net/DanielSim/sus9kgfh/

outputElement = document.getElementById('output');
rotationElement = document.getElementById('rotation');
rotationElement.oninput = function () {
    rotation = parseInt(rotationElement.value, 10);
};
scaleElement = document.getElementById('scale');
scaleElement.oninput = function () {
    scale = parseInt(scaleElement.value, 10) / 100;
};


feature = {
    x: 20,
    y: 20,
    width: 10,
    height: 10,
    el: document.getElementById('feature')
};

map = {
    x: 50,
    y: 30,
    width: 300,
    height: 300,
    el: document.getElementById('map')
};

rotation = 0;
scale = 1;


// Logic for correcting the coordinates of a point accounting for scale and rotation
adjustedTransform = function (_x, _y) {    
    var x = _x + map.x;
    var y = _y + map.y;

    var viewportMapCentre = {
        x: map.width/2 + map.x,
        y: map.height/2 + map.y
    }

    var differenceFromCentre = {
        x: x - viewportMapCentre.x,
        y: y - viewportMapCentre.y
    };

    var differenceFromCentreAtScale = {
        x: differenceFromCentre.x * scale,
        y: differenceFromCentre.y * scale
    };

    var rotatedPoint = {};
    var angle = rotation * Math.PI / 180.0;
    rotatedPoint.x = Math.cos(angle) * (differenceFromCentreAtScale.x) - Math.sin(angle) * (differenceFromCentreAtScale.y) + (viewportMapCentre.x);
    rotatedPoint.y = Math.sin(angle) * (differenceFromCentreAtScale.x) + Math.cos(angle) * (differenceFromCentreAtScale.y) + (viewportMapCentre.y);
    x = rotatedPoint.x;
    y = rotatedPoint.y;

    var coords = {
        x:x,
        y:y
    };

    return coords;
}


// Runs on each frame:
frame = 0;
step = function () {
    //Apply standard transform to map
    map.el.style.webkitTransform = generateTransform(map.x, map.y, scale, rotation);
    //Apply adjusted transform to feature
    featurePosition = adjustedTransform(feature.x, feature.y);
    feature.el.style.webkitTransform = generateTransform(featurePosition.x, featurePosition.y, 1, 0);
    generateTextOutput();
    frame++;
};

displayLoop = function () {
    step();
    window.requestAnimationFrame(displayLoop);
};


generateTransform = function (x, y, scale, ry) {
    return 'translate3d(' + x + 'px, ' + y + 'px, 0) scale3d(' + scale + ', ' + scale + ', ' + 1 + ') rotate3d(0, 0, 1,' + ry + 'deg)';
};

generateTextOutput = function () {
    output = "";
    output += "\nFrame: " + frame;
    output += "\nRotation: " + rotation;
    output += "\nScale: " + scale;
    output += ("\nFeature Coords: " + featurePosition.x + ", " + featurePosition.y);
    outputElement.innerText = output;
};

displayLoop();