之前写了一个关于图片旋转拉伸的实现,最近正好用到这个小功能,看了一下,发现之前写的方法有一些复杂,自己在之前的基础上简化了一下,记录下方法
实现方法一:
效果图
平移部分的代码没啥变化,主要是旋转的方法
这里主要写一下旋转方法的实现
这里的旋转,放大缩小都是以图片的中心点计算
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
角度算出后,使用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>
这里说一下,这个方法是用在自己的项目,没有经过多种场景的测试.主要是提供一种思路,如果你放在项目中有出现问题,可以留言探讨