之前寫了一個關於圖片旋轉拉伸的實現,最近正好用到這個小功能,看了一下,發現之前寫的方法有一些復雜,自己在之前的基礎上簡化了一下,記錄下方法
效果圖


平移部分的代碼沒啥變化,主要是旋轉的方法
這里主要寫一下旋轉方法的實現
這里的旋轉,放大縮小都是以圖片的中心點計算
1.先計算出圖片的中心點A
2.鼠標按下的地方計為B
3.移動停止的地方計為C
旋轉的角度就是這3點,B-A-C cosA
知道這3點坐標,就可以求出角度
1.先算出三條邊的長度
2.利用兩點坐標求直線公式算出AB,AC,BC線段的長度

var lengthAB = Math.sqrt(Math.pow(pointA.X - pointB.X, 2) + Math.pow(pointA.Y - pointB.Y, 2)), lengthAC = Math.sqrt(Math.pow(pointA.X - pointC.X, 2) + Math.pow(pointA.Y - pointC.Y, 2)), lengthBC = Math.sqrt(Math.pow(pointB.X - pointC.X, 2) + Math.pow(pointB.Y - pointC.Y, 2));
3.已知三角形的三邊長,求cos值的公式:cos A=(b²+c²-a²)/2bc
var cosA = (Math.pow(lengthAB, 2) + Math.pow(lengthAC, 2) - Math.pow(lengthBC, 2)) / (2 * lengthAB * lengthAC); // 余弦定理求出旋轉角
4.在根據公式,轉換成度數
var angle = Math.acos(cosA) * 180 / Math.PI
角度算出后,使用css3的rotate屬性設置
這里需要注意,第一次按下旋轉可以使用這個方法,但是第二次鼠標按下旋轉的度數是在第一次旋轉之后的基礎上,因此需要加上上一次已經旋轉的角度
這里是把旋轉的角度先存起來
$('.img-box').attr({rotate: allA})
下一次鼠標按下時取出
var rotate = $('.img-box').attr('rotate')
旋轉時,如果rotate有值就相加
if (rotate) {
allA += Number(rotate)
}
旋轉角度設置:
$('.img-box').css('transform', 'rotate('+allA+'deg)')


縮放的實現
圖片的縮放有些不一樣,它是需要在原圖的距離上計算縮放比例,如圖

完整代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <style> html, body { margin: 0; font-size: 14px; } .container { /* padding: 20px; border: 1px solid sienna; */ position: relative; width: 1000px; height: 800px; background-color: burlywood; } .box { position: absolute; left: 200px; top: 100px; width: 400px; height: 300px; color: #fff; /* background-color: rosybrown; */ } .img-box { position: absolute; width: 100%; height: 100%; background-color: sandybrown; } .flat { position: absolute; right: -20px; top: -20px; width: 40px; height: 40px; background-color: seagreen; z-index: 3; line-height: 40px; text-align: center; cursor: default; } .rotate { position: absolute; width: 40px; height: 40px; background-color: royalblue; z-index: 3; cursor: se-resize; line-height: 40px; text-align: center; } .rotate:nth-child(2) { right: -20px; bottom: -20px; } .rotate:nth-child(3) { left: -20px; bottom: -20px; } .rotate:nth-child(4) { left: -20px; top: -20px; } .img { width: 100%; height: 100%; cursor: move; } .header { height: 50px; } </style> <body> <div class="header"> <h1>圖形編輯</h1> </div> <div class="container"> <div class="box"> <div class="img-box"> <div class="flat">翻轉</div> <div class="rotate">旋轉</div> <div class="rotate">旋轉</div> <div class="rotate">旋轉</div> <img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1141259048,554497535&fm=26&gp=0.jpg" alt="" class="img"> </div> </div> </div> </body> <script src="./jquery-3.1.1.min.js"></script> <script> var flat = -1 // 鏡像翻轉 $(".flat").click(function() { $(".img").css("transform", "scaleX("+flat+")") flat = -flat }) var pointA = { // 元素中心點 元素1/2自身寬高 + 元素的定位 X: $('.box').width() / 2 + $('.box').offset().left, Y: $('.box').height() / 2 + $('.box').offset().top }; console.log(pointA, $('.box').position()) var pointB = {}; var pointC = {}; // A,B,C分別代表中心點,起始點,結束點坐標 // 這里通過鼠標的移動獲取起始點和結束點 var typeMouse = false; var moveMouse = false; var sa = 1 // 初始拉伸比例 var count = 0 // 元素跟隨鼠標移動旋轉拉伸 $(".rotate").on('mousedown', function (e) { e.preventDefault() e.stopPropagation() typeMouse = true; //獲取起始點坐標 pointB.X = e.pageX; pointB.Y = e.pageY; console.log('pointA', pointA, 'pointB', pointB) // 計算出初始拉伸比例 if (count < 1) { var scalX1 = pointB.X - pointA.X var scalY1 = pointB.Y - pointA.Y sa = Math.sqrt(scalX1 * scalX1 + scalY1 * scalY1) count++ } // 取出當前選轉的角度 var rotate = $('.img-box').attr('rotate') // console.log(rotate, scale) $('.container').on('mousemove', function (e) { e.preventDefault() e.stopPropagation() if (typeMouse) { pointC.X = e.pageX; pointC.Y = e.pageY; // 獲取結束點坐標 // console.log(pointC) // 計算每次移動元素的半徑變化,用作拉伸 var scalX = pointC.X - pointA.X var scalY = pointC.Y - pointA.Y // 計算出旋轉角度 var AB = {}; var AC = {}; AB.X = (pointB.X - pointA.X); AB.Y = (pointB.Y - pointA.Y); AC.X = (pointC.X - pointA.X); AC.Y = (pointC.Y - pointA.Y); // 分別求出AB,AC的向量坐標表示 var direct = (AB.X * AC.Y) - (AB.Y * AC.X); // AB與AC叉乘求出逆時針還是順時針旋轉 var lengthAB = Math.sqrt(Math.pow(pointA.X - pointB.X, 2) + Math.pow(pointA.Y - pointB.Y, 2)), lengthAC = Math.sqrt(Math.pow(pointA.X - pointC.X, 2) + Math.pow(pointA.Y - pointC.Y, 2)), lengthBC = Math.sqrt(Math.pow(pointB.X - pointC.X, 2) + Math.pow(pointB.Y - pointC.Y, 2)); var cosA = (Math.pow(lengthAB, 2) + Math.pow(lengthAC, 2) - Math.pow(lengthBC, 2)) / (2 * lengthAB * lengthAC); // 余弦定理求出旋轉角 var angleA = Math.round(Math.acos(cosA) * 180 / Math.PI); var allA = 0 if (direct < 0) { allA = -angleA; //叉乘結果為負表示逆時針旋轉, 逆時針旋轉減度數 } else { allA = angleA; //叉乘結果為正表示順時針旋轉,順時針旋轉加度數 } // 如果上一次按下旋轉已經有度數,需要加上上一次的度數 if (rotate) { allA += Number(rotate) } // console.log(allA, rotate) // 計算出拉伸比例 var ss = Math.sqrt(scalX * scalX + scalY * scalY) var sc = ss / sa // console.log(sc) $('.img-box').css('transform', 'rotate('+allA+'deg) scale('+sc+')') $('.img-box').attr({rotate: allA}) } }); }); // 元素移動 $('.img').on('mousedown', function (e) { e.preventDefault() e.stopPropagation() moveMouse = true var dis = { X: e.pageX - $('.box').position().left, Y: e.pageY - $('.box').position().top } $('.container').on('mousemove', function (event) { event.preventDefault() event.stopPropagation() if (moveMouse) { var end = {} end.X = event.pageX - dis.X end.Y = event.pageY - dis.Y $('.box').css({ 'left': end.X, 'top': end.Y }) pointA = { // 移動后,重新計算元素中心點 元素1/2自身寬高 + 元素的定位 X: $('.box').width() / 2 + $('.box').offset().left, Y: $('.box').height() / 2 + $('.box').offset().top }; // console.log(pointA, mPointB) } }) }) $(document).on('mouseup', function (e) { typeMouse = false; moveMouse = false }); </script> </html>
這里說一下,這個方法是用在自己的項目,沒有經過多種場景的測試.主要是提供一種思路,如果你放在項目中有出現問題,可以留言探討