Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Reported metrics should take into account CSS transformations #100

Open
paulyoung opened this Issue · 3 comments

1 participant

@paulyoung
Owner

For example, in the following screenshot the green box has its top, bottom, left, and right properties set to that of the red box, however it's not positioned that way since the rotation isn't accounted for.

screen shot 2014-07-16 at 22 27 48

@paulyoung
Owner

I changed my implementation so don't actually need this right now, but wanted to document what I have for future reference.

Using the code below I was able to set the size and position of the green rectangle to be that of the red rectangle when rotated.

screen shot 2014-07-17 at 02 41 19

From this I was also able to determine the size and position of a non-rotated rectangle that would fit inside of the red rectangle.

<body>
  <script>
    document.body.addEventListener('solved', function() {
      // Update reported metrics for z-rotation
      (function (vars) {
        var translateCoordinates = function(x, y, originX, originY, rotation) {
          var converted = rotation * (Math.PI / 180);

          return {
            x: originX + (x - originX) * Math.cos(converted) + (y - originY) * Math.sin(converted),
            y: originY - (x - originX) * Math.sin(converted) + (y - originY) * Math.cos(converted)
          };
        };

        var suggestIfNeeded = function(id, property, value) {
          var key, roundedVarValue, roundedValue;
          key = '$' + id + '[' + property + ']';
          roundedVarValue =  (Math.round(parseFloat(vars[key]) * 100) / 100);
          roundedValue =  (Math.round(parseFloat(value) * 100) / 100);

          if (roundedVarValue !== roundedValue) {
            var suggest = window.GSS.engines.root.commander.suggest;
            suggest('suggest', key, ['number', value]);
          }
        };

        for (key in vars) {
          var propertyName, property;
          propertyName = 'rotate-z';
          property = '[' + propertyName + ']';

          if (key.slice(property.length * -1) === property) {
            var id, element;
            id = key.replace('$', '').replace(property, '');
            element = document.getElementById(id);

            var x, y, width, height, rotateZ;
            x = vars["$"+id+"[x]"];
            y = vars["$"+id+"[y]"];
            width = vars["$"+id+"[width]"];
            height = vars["$"+id+"[height]"];
            rotateZ = vars["$"+id+"[rotate-z]"];

            var right, bottom;
            right = x + width;
            bottom = y + height;

            var centerX, centerY;
            centerX = x + (width / 2);
            centerY = y + (height / 2);

            // Assumes rotatation around center point
            var topLeft, topRight, bottomRight, bottomLeft;
            topLeft = translateCoordinates(x, y, centerX, centerY, rotateZ);
            topRight = translateCoordinates(right, y, centerX, centerY, rotateZ);
            bottomRight = translateCoordinates(right, bottom, centerX, centerY, rotateZ);
            bottomLeft = translateCoordinates(x, bottom, centerX, centerY, rotateZ);

            var xCoordinates, yCoordinates;
            xCoordinates = [topLeft.x, topRight.x, bottomRight.x, bottomLeft.x];
            yCoordinates = [topLeft.y, topRight.y, bottomRight.y, bottomLeft.y];

            var minX, maxX, minY, maxY;
            minX = Math.min.apply(this, xCoordinates);
            maxX = Math.max.apply(this, xCoordinates);
            minY = Math.min.apply(this, yCoordinates);
            maxY = Math.max.apply(this, yCoordinates);

            var rotatedTopLeft, rotatedTopRight, rotatedBottomRight, rotatedBottomLeft;
            rotatedTopLeft = { x: minX, y: minY };
            rotatedTopRight = { x: maxX, y: minY };
            rotatedBottomRight = { x: maxX, y: maxY };
            rotatedBottomLeft = { x: minX, y: maxY };

            // x, y, width, height
            var rotatedX, rotatedY, rotatedWidth, rotatedHeight;
            rotatedX = rotatedTopLeft.x;
            rotatedY = rotatedTopLeft.y
            rotatedWidth = rotatedTopRight.x - rotatedTopLeft.x;
            rotatedHeight = rotatedBottomLeft.y - rotatedTopLeft.y;

            suggestIfNeeded(id, 'rotated-left', rotatedX);
            suggestIfNeeded(id, 'rotated-top', rotatedY);
            suggestIfNeeded(id, 'rotated-width', rotatedWidth);
            suggestIfNeeded(id, 'rotated-height', rotatedHeight);

            // Coordinates
            var rotatedLeftX, rotatedLeftY, rotatedTopX, rotatedTopY,
            rotatedRightX, rotatedRightY, rotatedBottomX, rotatedBottomY;

            var sortedXCoordinates, sortedYCoordinates;
            sortedXCoordinates = xCoordinates.sort();
            sortedYCoordinates = yCoordinates.sort();

            rotatedLeftX = minX;
            rotatedLeftY = sortedYCoordinates[1];

            rotatedTopX = sortedXCoordinates[2];
            rotatedTopY = minY;

            rotatedRightX = maxX;
            rotatedRightY = sortedYCoordinates[2];

            rotatedBottomX = sortedXCoordinates[1];
            rotatedBottomY = maxY;

            suggestIfNeeded(id, 'rotated-left-x', rotatedLeftX);
            suggestIfNeeded(id, 'rotated-left-y', rotatedLeftY);
            suggestIfNeeded(id, 'rotated-top-x', rotatedTopX);
            suggestIfNeeded(id, 'rotated-top-y', rotatedTopY);
            suggestIfNeeded(id, 'rotated-right-x', rotatedRightX);
            suggestIfNeeded(id, 'rotated-right-y', rotatedRightY);
            suggestIfNeeded(id, 'rotated-bottom-x', rotatedBottomX);
            suggestIfNeeded(id, 'rotated-bottom-y', rotatedBottomY);
          }
        }
      })(window.GSS.vars);
    });
  </script>
</body>
@paulyoung
Owner

Similar calculations for skewY:

<body>
   <script>
    document.body.addEventListener('solved', function() {
      // Provide metrics for vertical skewing
      (function (vars) {
        var suggestIfNeeded = function(id, property, value) {
          var key, roundedVarValue, roundedValue;
          key = '$' + id + '[' + property + ']';
          roundedVarValue =  (Math.round(parseFloat(vars[key]) * 100) / 100);
          roundedValue =  (Math.round(parseFloat(value) * 100) / 100);

          if (roundedVarValue !== roundedValue) {
            var suggest = window.GSS.engines.root.commander.suggest;
            suggest('suggest', key, ['number', value]);
          }
        };

        for (key in vars) {
          var propertyName, property;
          propertyName = 'skew-y';
          property = '[' + propertyName + ']';

          if (key.slice(property.length * -1) === property) {
            var id, element;
            id = key.replace('$', '').replace(property, '');
            element = document.getElementById(id);

            var y, width, height, skewY;
            y = vars["$"+id+"[y]"];
            width = vars["$"+id+"[width]"];
            height = vars["$"+id+"[height]"];
            skewY = vars["$"+id+"[skew-y]"];

            var degrees, delta;
            degrees = Math.abs(skewY) * (Math.PI / 180);
            delta = Math.tan(degrees) * width;

            // Assumes origin is center point
            var skewedTop, skewedHeight, skewedBottom;
            skewedTop = y - (delta / 2);
            skewedHeight = height + delta;
            skewedBottom = skewedTop + skewedHeight;

            suggestIfNeeded(id, 'skewed-top', skewedTop);
            suggestIfNeeded(id, 'skewed-height', skewedHeight);
            suggestIfNeeded(id, 'skewed-bottom', skewedBottom);
          }
        }
      })(window.GSS.vars);
    });
  </script>
</body>
@paulyoung
Owner

getBoundingClientRect seems like it would handle this nicely for any combination of transformations if supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.