【发布时间】:2018-03-28 06:25:21
【问题描述】:
我正在构建一个 Croppie 的实现作为 AngularJS 指令,以便为用户提供一个 UI 来裁剪他们的个人资料图像。
我的后端是 PHP,我需要一种将 UI 选择反映在服务器端操作中的方法。
我的图像中心有一个 150 x 150 的正方形,链接的 Croppie 示例同样显示。但是,正如您所见,您可以移动和缩放图像,这意味着在 Imagick 中从中心进行裁剪并不总是有效,具体取决于用户如何围绕中心点放置图像。
我知道我可以缩放图像,然后在 Imagick 中从中心裁剪,但我如何解释图像也会被翻译的事实?
当我在我的实现中移动图像时,我得到以下数据点来解析并发送到服务器:
{transform: "translate3d(-60px, -121px, 0px) scale(1)"}
这表明,例如,图像已沿 X 和 Y 轴移动,并且尚未缩放。如何在 Imagick 中相应地移动图像的中心?
谢谢!
编辑:
我看到这些命令:Imagick::cropThumbnailImage 和 Imagick::cropImage 是否有某种方法可以将它们组合在一起,使裁剪区域在图像缩放时保持在中心,并且图像可以在 x 或 y 轴上移动?
编辑 2
好吧,我发现我需要使用 Imagick::cropImage 和 Imagick::scaleImage 的组合,但我无法确定要发送到服务器的正确数学。
我附上了一张图片,以便您了解我的意思,我已经非常接近了,但某些图片的裁剪已关闭:
我的 HTML 是这样的:
<div class="viewBox">
<img class="bigTuna">
<div class="enclosedCrop small"></div>
<div class="overlay small"></div>
</div>
您看到的图像是.bigTuna,我想使用.encloseCrop.small(即圆圈)对其进行裁剪。
我使用以下方法计算图像相对于图像比例 (.bigTuna) 的偏移量(我可以在 .encloseCrop.small 周围拖动)。 .encloseCrop.small 的偏移量为.viewBox,图片占据了整个.viewBox 一个max-width: 100%;
因为图像有 width、naturalWidth 和 getBoundingClientRect().width(以及高度的相应属性t)我不确定如何完成这个我可以发送给 Imagick X 和 Y 用于 cropImage() 参数。
这是我得到的最接近的:
var Xvalue = (angular.element(".enclosedCrop")[0].offsetLeft + ( -1 * $scope.matrixobject.x )) * ((angular.element('.bigTuna')[0].getBoundingClientRect().width/angular.element('.bigTuna')[0].width)*(angular.element('.bigTuna')[0].naturalWidth/angular.element('.bigTuna')[0].width));
var Yvalue = (angular.element(".enclosedCrop")[0].offsetTop + ( -1 * $scope.matrixobject.y )) * ((angular.element('.bigTuna')[0].getBoundingClientRect().height/angular.element('.bigTuna')[0].height)*(angular.element('.bigTuna')[0].naturalHeight/angular.element('.bigTuna')[0].height));
边界宽度除以宽度是比例因子,但我相信我也需要以某种方式考虑自然宽度。问题是您在Croppie-like 指令所在的模态中看到的图像已经被缩放,因为它不是自然尺寸。最重要的是,我正在使用 CSS 变换再次缩放这个(已经)缩放的图像。
但是当我将图像发送到 PHP 时,它不知道这一点。我只是收到自然尺寸并想知道如何裁剪它。我需要该裁剪来反映 UI 裁剪。
$scope.matrixobject.x 是图像变换的值,在这种情况下,它被平移的像素数量。我可以很好地得到所有这些值,我只是不知道使用这些值的方程实际上是正确的。
编辑 3:
我已经像这样改进了我的方程式,但是这个方程式,虽然它对我来说最有意义,但让我完全没有收获。
var Xvalue = (angular.element(".enclosedCrop")[0].offsetLeft + ( -1 * $scope.matrixobject.x )) * (angular.element('.bigTuna')[0].naturalWidth/angular.element('.bigTuna')[0].getBoundingClientRect().width);
var Yvalue = (angular.element(".enclosedCrop")[0].offsetTop + ( -1 * $scope.matrixobject.y )) * (angular.element('.bigTuna')[0].naturalHeight/angular.element('.bigTuna')[0].getBoundingClientRect().height);
该等式首先尝试从图像容器的顶部和左侧获取 150 x 150 圆 (.enclosedCrop) 的偏移量:
在高度的情况下,如下所示:
angular.element(".enclosedCrop")[0].offsetTop + ( -1 * $scope.matrixobject.y )
该等式摘录的第一部分得到 offsetTop,它将保持不变,因为 .enclosedCrop 本身在容器的中心是静止的。 $scope.matrixobject.y 是容器周围图像的变换,通过反转它,如果 .enclosedCrop 在图像周围移动,我们可以获得所需的变换。通过将此添加到偏移量中,我们可以知道图像上的裁剪位置。
但是,偏移量和变换是相对于容器中图像的大小 (max-width:100%) 这意味着它们需要缩放以反映图像的自然大小以及使用 CSS scale 属性可能发生的任何变换。
所以我将偏移量乘以这个:
* (angular.element('.bigTuna')[0].naturalHeight/angular.element('.bigTuna')[0].getBoundingClientRect().height);
自然高度除以图像的高度。重要的是,这个“图像高度”源自getBoundingClientRect(),这意味着它考虑了 CSS 缩放。
那么我的逻辑有什么问题呢?我在整个图像上都得到了裁剪,而不是在我指定的坐标中。
编辑 4:
我得到了非常接近给出的以下等式,我不太明白(来自 Croppie 的源代码)
var Xvalue = angular.element(".enclosedCrop")[0].getBoundingClientRect().left - angular.element(".bigTuna")[0].getBoundingClientRect().left + angular.element(".enclosedCrop")[0].offsetWidth + (angular.element(".enclosedCrop")[0].getBoundingClientRect().width - angular.element(".enclosedCrop")[0].offsetWidth) / 2;
var Yvalue = angular.element(".enclosedCrop")[0].getBoundingClientRect().top - angular.element(".bigTuna")[0].getBoundingClientRect().top + angular.element(".enclosedCrop")[0].offsetHeight + (angular.element(".enclosedCrop")[0].getBoundingClientRect().height - angular.element(".enclosedCrop")[0].offsetHeight) / 2;
Xvalue = parseFloat(Xvalue).toFixed(0);
Yvalue = parseFloat(Yvalue).toFixed(0);
但是它总是偏离几个像素,通常稍微向下和向右。
谁能解释一下这个方程式,以便我更好地编辑它并找出错误?
【问题讨论】:
-
作为替代方案,您可以在客户端裁剪图像并将其发送到服务器
-
我认为你应该只发送缩放后的 x、y 和图像尺寸。从服务器上的图像中读取其尺寸,然后计算所需的值。 OT:使用
<canvas>在客户端生成图像。 -
@RomanCortes 我更愿意在服务器端进行裁剪。
-
@bato3 你能解释一下你建议我将哪些数据点发送到服务器吗?
-
你需要发送 offset(x, y), size(width, height) 然后可以处理原始图像和 imagemagick
标签: php angularjs image math imagick