使用 CropperJS 旋转配件 canvas
Rotating a fitting canvas with CropperJS
背景
我目前正在开发一种裁剪工具,可以使图像适合它要插入的元素。我从 cropperJS 得到的比率总是 1:1,这意味着高度 == 宽度。一旦我从 cropperJS 获得了 x,y,height,width,我就会得到图像要进入的元素的 height/width 比率,并添加图像的后位以使裁剪后的图像与它适合的元素。
问题
我正在尝试为我的自定义裁剪器制作一个旋转工具,而我从 cropperJS 获得的 X、Y 数据就好像图像从未旋转过一样。我创建了一个函数来进行矩阵旋转以获得我认为工作正常的新 X、Y 数据。如果图像旋转 180 度,我旋转 canvas 的工具可以正常工作,但如果旋转 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 度的正确坐标度。
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 度的坐标,但就是想不通。我相信这与原始图像的纵横比有关,但我不确定。
您可能只想使用库的输出并以这种方式获取 canvas 数据。在这种情况下,我结婚了一点 CSS 并得到了你想要的。
cropper.getCroppedCanvas().toBlob()
这也为您提供了库的全部灵活性,因此(如图所示)您可以旋转任何角度并执行库允许您执行的任何其他操作。
背景
我目前正在开发一种裁剪工具,可以使图像适合它要插入的元素。我从 cropperJS 得到的比率总是 1:1,这意味着高度 == 宽度。一旦我从 cropperJS 获得了 x,y,height,width,我就会得到图像要进入的元素的 height/width 比率,并添加图像的后位以使裁剪后的图像与它适合的元素。
问题
我正在尝试为我的自定义裁剪器制作一个旋转工具,而我从 cropperJS 获得的 X、Y 数据就好像图像从未旋转过一样。我创建了一个函数来进行矩阵旋转以获得我认为工作正常的新 X、Y 数据。如果图像旋转 180 度,我旋转 canvas 的工具可以正常工作,但如果旋转 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 度的正确坐标度。
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 度的坐标,但就是想不通。我相信这与原始图像的纵横比有关,但我不确定。
您可能只想使用库的输出并以这种方式获取 canvas 数据。在这种情况下,我结婚了一点 CSS 并得到了你想要的。
cropper.getCroppedCanvas().toBlob()
这也为您提供了库的全部灵活性,因此(如图所示)您可以旋转任何角度并执行库允许您执行的任何其他操作。