Я создал директиву для поворота и изменения размера (масштабирования) изображения. В настоящее время я выполняю это, манипулируя встроенным стилем элемента. Я использую css transforms (rotate
и scale
).
Мой текущий подход к вращению изображения заключается в том, чтобы повернуть его в верхнем левом углу в качестве источника, а затем переместить изображение обратно в поле с полями. Для масштабирования я также пересчитываю новые эффективные размеры изображения, умножая исходные размеры на коэффициент масштабирования.
У меня есть масштабирование и вращение, но нестандартные вращения не помещаются в родительский контейнер. Например, при повороте на 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 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>
Демоверсия плункера. Обратите внимание на разные цветные границы.
Почему моя директива не обрабатывает вращение грациозно? Почему его родительский div делает действительно странные вещи при изменении размера?
Благодаря совету Тодда я решил свои странные проблемы с пробелами, используя position: absolute
. Чтобы компенсировать это, мне также пришлось переназначить родительский контейнер. Здесь обновленная функция 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'
});
}
Обновлен рабочий плункер.