【发布时间】:2019-12-19 14:58:29
【问题描述】:
背景
我目前正在开发一种裁剪工具,该工具将使图像适合它要进入的元素。我从cropperJS 得到的比率始终是 1:1,这意味着高度 == 宽度。一旦我从cropperJS获得了x,y,height,width,我将得到图像进入的元素的高度/宽度的比率,并添加图像的后位以使裁剪的图像与元素的比率相同它正在适应。
问题
我正在尝试为我的自定义裁剪器制作一个旋转工具,而我从cropperJS 获得的 X、Y 数据就像图像从未旋转过一样。我创建了一个函数来进行矩阵旋转以获取我认为工作正常的新 X、Y 数据。如果图像旋转 180 度,但如果图像旋转 270 度或 90 度,我的旋转画布工具可以正常工作。
代码
这是计算矩阵旋转的较小函数,其中 x 和 y 是未旋转的坐标,xm 和 ym 是旋转的中心点,a 是旋转角度。
function rotate(x, y, xm, ym, a) {
var cos = Math.cos,
sin = Math.sin,
a = a * Math.PI / 180, // Convert to radians
// Subtract midpoints, so that midpoint is translated to origin
// and add it in the end again
xr = (x - xm) * cos(a) - (y - ym) * sin(a) + xm,
yr = (x - xm) * sin(a) + (y - ym) * cos(a) + ym;
return [xr, yr];
}
这是进行裁剪的函数,它适用于 0 或 180 度的角度,但无法获得 90 或 270 度的正确坐标。 p>
var cropPhoto = async (imgSrc,cropData) =>{return new Promise((resolve, reject) => {
var img = new Image()
var ctx, canvas
var ratio = cropData.ratio || 1
var h = cropData.height
var w = cropData.width
var x = cropData.x
var y = cropData.y
if ( ratio > 1 ){
var h = ratio * cropData.height
y = y - ( (h - cropData.height) / 2 )
}
else if ( ratio < 1 ){
var w = (1 / ratio) * cropData.width
x = x - ( (w - cropData.width) / 2 )
}
img.style.transform = `${cropData.rotate}deg`
img.src = imgSrc
img.onload = () => {
canvas = document.createElement("canvas")
canvas.height = h
canvas.width = w
ctx = canvas.getContext('2d')
if(cropData.rotate != 0){
//nv == new values
//this only works if its 180 degrees
var nv = rotate(x,y, cropData.image.naturalWidth/2, cropData.image.naturalHeight/2, cropData.rotate)
x = nv[0] - w
y = nv[1] - h
}
ctx.drawImage(img, x, y, w, h, 0, 0, w, h)
canvas = cropData.rotate != 0 ? drawRotated(cropData.rotate) : canvas
canvas.toBlob(blob => {
try {
var urlCreator = window.URL || window.webkitURL;
resolve(urlCreator.createObjectURL(blob))
} catch (error) {
reject()
}
},"image/png",1)
}
var drawRotated = degrees => {
var newCanvas = document.createElement("canvas")
if ( [90, 270].indexOf(Math.abs(degrees)) > -1 ){
newCanvas.height = w
newCanvas.width = h
}else{
newCanvas.height = h
newCanvas.width = w
}
var ctx2 = newCanvas.getContext("2d")
if ( [90,-270].indexOf(degrees) > -1 ){
ctx2.translate( h , 0 )
}else if ( [-90,270].indexOf(degrees) > -1 ){
ctx2.translate( 0 , w )
}else if ( Math.abs(degrees) == 180 ){
ctx2.translate( w , h )
}
ctx2.rotate(degrees*Math.PI/180)
ctx2.drawImage(canvas, 0 , 0 )
return newCanvas
}
})}
imgSrc 是任何标准图像的 URL 字符串。一个cropData的例子如下:
{
height: 221
ratio: 0.48
rotate: 0
scaleX: 1
scaleY: 1
width: 221
x: 695
y: 61
}
我一直在绞尽脑汁想弄清楚为什么图像没有获得 90 度或 270 度的坐标,但就是不知道为什么。我认为这与原始图像的纵横比有关,但我不确定。
【问题讨论】:
-
你没有用 CSS 做所有这些事情有什么原因吗?
标签: javascript matrix rotation