需求描述
最近有用户在使用luckySheet时,希望能够任意角度旋转图片,就像wps那样,wps如下图
在网上只找到在canvas中进行旋转的库,没找到直接操作图片dom的库,决定直接写。
实现思路
1、点击时记录图片坐标
点击图片时加一个按钮button,用于控制旋转。点击这个按钮时,记录图片的中点在视图中的坐标pos,代码如下:
$("#rotateImg").off("mousedown.rotate").on("mousedown.rotate", function(e) {
if(!checkProtectionAuthorityNormal(Store.currentSheetIndex, "editObjects",false)){
return;
}
e.stopPropagation()
//开始旋转的标志
globalThis._isStartRotate = true
// 获取点击初始时的坐标
// const rotateDom = document.querySelector('#rotateImg')
const rotateDom = document.querySelector('#luckysheet-modal-dialog-activeImage')
let rect = rotateDom.getBoundingClientRect()
const devX = parseInt($(rotateDom).css('width'))/2
const devY = parseInt($(rotateDom).css('height'))/2
console.log(Number.parseInt(rect.top + devY),Number.parseInt(rect.left + devX));
globalThis.initPos = {y: Number.parseInt(rect.top + devY),x:Number.parseInt(rect.left + devX)}
})
2、移动时计算角度,然后修改rotate属性
在鼠标移动时,需要拿到鼠标的位置(x2,y2),通过这个位置和“图片中点(x1,y1)”能构成一条直线,求出这条直线与y轴正方向的夹角a,就是rotate的值,示意图如下:
3、如何计算夹角
在第一象限中,先计算出直线与x轴正方向的反正切值,然后将其转为角度,这个角度的余角就是夹角a的角度值,最后再针对不同象限做一些处理就行。计算角度的代码如下:
function calculateAngle(x1,y1,x2,y2) {
// 计算直线的斜率
const slope = (y2 - y1) / (x2 - x1)
// 计算直线与x轴的夹角的弧度值(需要转为角度)
const angleRadians = Math.atan(slope);//反正切
// 将弧度转换为度
const angleDegrees = angleRadians * (180 / Math.PI);
//比如在第二象限时,angleDegrees会大于90度,需要求绝对值,
const angleBetween = Math.abs(90 - angleDegrees);// 求直线与y轴正方向的夹角
// 进行坐标系转化
return x2 >= x1 ? 180 - angleBetween : 360 - angleBetween
}
luckySheet中鼠标移动时的代码如下:
$(document).off("mousemove.rotate").on("mousemove.rotate",function (event) {
if(!checkProtectionAuthorityNormal(Store.currentSheetIndex, "editObjects",false)){
return;
}
if(globalThis._isStartRotate){
const endX = event.clientX
const endY = event.clientY
// 示例:使用起点(1, 2)和终点(3, 4)
const angle = calculateAngle(globalThis.initPos.x, globalThis.initPos.y, endX, endY);
$('#luckysheet-modal-dialog-activeImage').css('transform',`rotate(${angle}deg)`)
// 旋转的时候需要改img对应的对象数据
let imgItem = _this.images[_this.currentImgId];
imgItem.default.rotate = angle
}
})
最后的效果END
针对luckySheet的代码还有一些细节的处理,这里不介绍,最后的效果如下: