Famo.us Scrollview + TouchSync - 使ScrollView / TouchSync意识到rotateZ变换

时间:2015-01-29 22:33:00

标签: javascript touch scrollview famo.us

编辑:已解决 - 请参阅新代码摘录

我有一个嵌套在ContainerSurface内的Famo.us滚动视图。 ContainerSurface在mutli-touch旋转手势上旋转,但一旦旋转,滚动视图的滚动方向就不会相对于旋转曲面及其子项的修改器保持不变。

2 个答案:

答案 0 :(得分:1)

鉴于当前的实施,这是不可能的,问题是TouchSync

要完成这样的事情,您需要编写一个自定义的RotatedTouchSync来识别"旋转。这样,当ScrollView从move事件中收到 delta 时,自定义TouchSync已将其转换为ScrollView可以理解的坐标系。

答案 1 :(得分:0)

我已经设置了一个基本示例codepen,您可以看到ScrollView如何工作,除非您创建一个自定义的TouchSync ScrollView {1}}已转换的 delta (如@Joseph Carroll所述)。

我通过使用修改后的RotatableTouchSync方法创建_handleMove来完成此修复:

function _handleMove(data) {
        var history = data.history;

        var currHistory = history[history.length - 1];
        var prevHistory = history[history.length - 2];

        var distantHistory = history[history.length - this.options.velocitySampleLength] ?
          history[history.length - this.options.velocitySampleLength] :
          history[history.length - 2];

        var distantTime = distantHistory.timestamp;
        var currTime = currHistory.timestamp;

        // Begin custom code -----------------------------------------------------------------------------
        var diffX, diffY, velDiffX, velDiffY;

        if (this.options.rotateAngle) {

            // Convert currHistory, prevHistory, distantHistory x,y points to quadrants because our formula only works when origin is 0,0
            var absCenter = [window.innerWidth/2, window.innerHeight/2];

            var currPrime = _calcCoordsByAngle([currHistory.x - absCenter[0], currHistory.y - absCenter[1]], this.options.rotateAngle);

            var prevPrime = _calcCoordsByAngle([prevHistory.x - absCenter[0], prevHistory.y - absCenter[1]], this.options.rotateAngle);

            var distPrime = _calcCoordsByAngle([distantHistory.x - absCenter[0], distantHistory.y - absCenter[1]], this.options.rotateAngle);

            // Converted coordinates back to normal points (clientX, clientY points)
            var convertedCurrX = currPrime.x + absCenter[0];
            var convertedCurrY = currPrime.y + absCenter[1];

            var convertedPrevX = prevPrime.x + absCenter[0];
            var convertedPrevY = prevPrime.y + absCenter[1];

            var convertedDistX = distPrime.x + absCenter[0];
            var convertedDistY = distPrime.y + absCenter[1];


            // Calculate diff like normal
            diffX = convertedCurrX - convertedPrevX;
            diffY = convertedCurrY - convertedPrevY;


            velDiffX = convertedCurrX - convertedDistX;
            velDiffY = convertedCurrY - convertedDistY;

        }
       // If the custom option for rotate angle isn't set, calculate as normal
        else {
            diffX = currHistory.x - prevHistory.x;
            diffY = currHistory.y - prevHistory.y;

            velDiffX = currHistory.x - distantHistory.x;
            velDiffY = currHistory.y - distantHistory.y;
        }

修改后的_handleMove会调用名为_calcCoordsByAngle的自定义方法:

/**
 *  Used to calculate a coordinate set
 *  at a given rotation
 *  See: http://math.stackexchange.com/questions/384186/calculate-new-positon-of-rectangle-corners-based-on-angle
 *  @method _calcCoordsByAngle
 *  @param {Array} oldCoords An [x,y] set of coordinates
 *  @param {number} phi The angle to move by
 *  @return {Array} The newly converted coordinates
 */
function _calcCoordsByAngle(oldCoords, phi) {
    var newCoords = {};
    newCoords.x = (oldCoords[0] * Math.cos(-phi)) - (oldCoords[1] * Math.sin(-phi));
    newCoords.y = (oldCoords[1] * Math.cos(-phi)) + (oldCoords[0] * Math.sin(-phi));

    return newCoords;
}

从那里开始,可以使用此自定义RotatableTouchSync替换自定义TouchSync上的ScrollView - 只需确保传入/设置选项' rotateAngle'任何时候Z轴旋转都会在RotatableTouchSync上。