旋转图像不适合父容器

时间:2015-11-25 15:40:34

标签: javascript css angularjs css-transforms

我创建了一个旋转和调整大小(缩放)图像的指令。我目前正在通过操纵元素的内嵌样式来实现这一点。我正在使用css转换(rotatescale)。

我目前旋转图像的方法是将其旋转到左上角作为原点,然后我将图像移回带边距的视图。对于缩放,我还通过将原始尺寸乘以缩放因子来重新计算图像的新有效尺寸。

我有缩放和旋转工作,但非标准旋转不能很好地位于父容器内。例如,当旋转180度时,图像下面有一堆额外的空白,这使得它没有明显的原因。

指令:

function directive()  {
    return {
        restrict: 'A',
        scope: {
            options: '='
        },
        link: link
    };

    function link(scope, element, attributes) {
        element.bind('load', function()  {
            if (!scope.options.originalSize) {
                element.removeAttr('style'); //clear all previous styling

                //workaround for IE (it's dumb, and I'd rather just use this element (element[0]) data)
                var img = document.createElement('img');
                img.src = element[0].src;
                scope.options.originalSize = {
                    height: img.height,
                    width: img.width
                };
                scope.options.scaling = 1.0;
                scope.options.rotation = 0;
            }
            transformWithCss();
        });

        scope.$watch('options.rotation', transformWithCss);
        scope.$watch('options.scaling', transformWithCss);

        function transformWithCss()  {
            if (!scope.options || !scope.options.originalSize)
                return;

            var width = scope.options.originalSize.width * scope.options.scaling;
            var height = scope.options.originalSize.height * scope.options.scaling;
            var marginTop, marginLeft;

            var effectiveRotation = (scope.options.rotation % 360 + 360) % 360;
            switch (effectiveRotation) {
                case 0:
                    marginTop = 0;
                    marginLeft = 0;
                    break;
                case 90:
                    marginTop = 0;
                    marginLeft = height * scope.options.scaling;
                    break;
                case 180:
                    marginTop = height * scope.options.scaling;
                    marginLeft = width * scope.options.scaling;
                    break;
                case 270:
                    marginTop = width * scope.options.scaling;
                    marginLeft = 0;
                    break;
                default:
                    //how did we get here? throw exception?
                    alert("something went wrong with rotation");
                    break;
            }

            element.css({
                "transform": 'scale(' + scope.options.scaling + ') rotate(' + scope.options.rotation + 'deg) ',
                "width": width + 'px',
                "height": height + 'px',
                "transform-origin": '0px 0px',
                "margin-top": marginTop + 'px',
                "margin-left": marginLeft + 'px'
            });
        }

    }
}

HTML中的用法:

<div class="parent-div col-md-10 col-lg-10">
  <p>Some other content</p>
  <div class="image-holder">
    <img scaling-rotating-image="" options="ctrl.imageOptions" src="//lorempixel.com/500/300/cats/" />
  </div>
</div>

A plunker demo。注意不同颜色的边框。

为什么我的指令不能优雅地处理旋转?为什么它的父div在调整大小时会做出非常奇怪的事情?

1 个答案:

答案 0 :(得分:1)

感谢Todd's advice,我使用 position: absolute 解决了我奇怪的whitespacing问题。为了弥补这一点,我还必须重新设置父容器。这是更新后的transformWithCss功能:

function transformWithCss()  {
    if (!scope.options || !scope.options.originalSize)
        return;

    var width = scope.options.originalSize.width * scope.options.scaling;
    var height = scope.options.originalSize.height * scope.options.scaling;
    var marginTop, marginLeft;
    var parentHeight, parentWidth; //to redimension the parent container

    var effectiveRotation = (scope.options.rotation % 360 + 360) % 360;
    switch (effectiveRotation) {
        case 0:
            parentHeight = height * scope.options.scaling;
            parentWidth = width * scope.options.scaling;
            marginTop = 0;
            marginLeft = 0;
            break;
        case 90:
            parentHeight = width * scope.options.scaling;
            parentWidth = height * scope.options.scaling;
            marginTop = 0;
            marginLeft = parentWidth;
            break;
        case 180:
            parentHeight = height * scope.options.scaling;
            parentWidth = width * scope.options.scaling;
            marginTop = parentHeight;
            marginLeft = parentWidth;
            break;
        case 270:
            parentHeight = width * scope.options.scaling;
            parentWidth = height * scope.options.scaling;
            marginTop = parentHeight;
            marginLeft = 0;
            break;
        default:
            //how did we get here? throw exception?
            alert("something went wrong with rotation");
            break;
    }

    element.css({
        "position": "absolute", //absolute positions removes weird whitespace
        "transform": 'scale(' + scope.options.scaling + ') rotate(' + scope.options.rotation + 'deg) ',
        "width": width + 'px',
        "height": height + 'px',
        "transform-origin": '0px 0px',
        "margin-top": marginTop + 'px',
        "margin-left": marginLeft + 'px'
    });

    //redimension parent container
    element.parent().css({
        "height": parentHeight + 'px',
        "width": parentWidth + 'px'
    });

}

更新了工作plunker