网页组件制作之图片剪切效果
在该笔记中将学到列表展示中图片剪切效果的方法与展示效果
本系列的是参考慕课网 Ben老师的视频,仅供个人查阅使用,具体讲解推荐参考视频。
实现效果
技术关键点
CSS 中使用 clip 可以实现对图片的裁剪,如果要裁剪成矩形,则需要使用 clip:rect(top, right, bottom, left)
使用绝对定位来定位选取框的触点
对于选取框的鼠标事件:按下,松开,拖动,同时要获得鼠标在选取框中的位置,根据鼠标的坐标来改变选取框的位置
拖动的实现:拖动的实现是分为鼠标的按下,移动和松开三个动作共同完成的。按下的时候,记录此时的裁剪框的位置以及大小,在 mousemove 的时候修改裁剪框的位置以及大小。
使用 jQuery 的 css()方法,可以获得外部样式文件的样式。
代码如下:
<!DOCTYPE html>
<html>
<head>
<title>图片剪切效果</title>
<meta charset="utf-8">
<style>
body{margin: 0;padding: 0;background-color: #666;}
#photo{height: 360px;width: 460px;position: absolute; top: 100px;left: 200px;}
#photo img{height: 360px;width: 460px;}
#img-back{opacity: 0.5;position: absolute;top:0;right: 0;}
#img-clip{position: absolute;top: 0;right: 0;clip: rect(0, 200px, 200px, 0)}
#clip-win{position: absolute;border: 1px solid white;height: 200px;width: 200px;left:0px; top: 0px;}
#clip-win .win-btn{position: absolute;height: 6px;width: 6px;background-color: white;margin-left: -3px;margin-top: -3px;}
#clip-win .left-l{left: 0px;}
#clip-win .left-m{left: 100px;}
#clip-win .left-r{left: 200px;}
#clip-win .top-t{top: 0px;}
#clip-win .top-m{top: 100px;}
#clip-win .top-b{top: 200px;}
#preview{position: absolute;height: 360px;width: 460px;top: 100px;left: 680px;}
#preview-img{height: 360px;width: 460px;position: absolute;}
</style>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">
</script>
<script>
function updateClip($border) {
//更新选取区域高亮可见
document.getElementById("img-clip").style.clip = "rect(" + $border.css("top") + "," + (parseFloat($border.css("left")) + parseFloat($border.width())) + "px, " + (parseFloat($border.css("top")) + parseFloat($border.height())) + "px, " + $border.css("left") + ")";
}
function updatePreview($border) {
let top = $border.css("top"),
left = $border.css("left"),
width = $border.width(),
height = $border.height();
$("#preview-img").css({
"clip": "rect(" + top + ", " + (parseFloat(left) + width) + "px, " + (parseFloat(top) + height)+ "px, " + left +")",
"top": "-" + top,
"left": "-" + left
});
}
$(document).ready(function () {
// 设置鼠标在选取框边界点上的CSS效果
$("#clip-win div").each(function () {
$(this).css("cursor", this.id);
});
let isMouseDown = false;
let mouseDowntarget, mouseDownX, mouseDownY, btnDir, borderLeft;
updatePreview($("#clip-win"));
// 鼠标是否按着选取框边界点
$(window).bind("mousedown", function () {
let $border = $("#clip-win");
isMouseDown = true;
mouseDowntarget = event.target;
mouseDownX = event.clientX;
mouseDownY = event.clientY;
borderLeft = parseFloat($border.css("left"));
borderTop = parseFloat($border.css("top"));
borderWidth = $border.width();
borderHeight = $border.height();
}).bind("mouseup", function () {
isMouseDown = false;
}).bind("mousemove", function () {
if(isMouseDown && $(mouseDowntarget).hasClass("win-btn")){
let $t = $(mouseDowntarget);
let $border = $("#clip-win");
if($t.hasClass("left-l")){
//左边栏拉到右边栏上重合
if((borderWidth - event.clientX + mouseDownX) > 0) {
//判断左边栏是否出界
if((borderLeft + event.clientX - mouseDownX) > 0) {
$border.css("left",borderLeft + event.clientX - mouseDownX + "px");
$border.width(borderWidth - event.clientX + mouseDownX);
//修改裁剪框触点的定位
$(".left-m").each(function () {
this.style.left = (borderWidth - event.clientX + mouseDownX)/2 + "px";
});
$(".left-r").each(function () {
this.style.left = borderWidth - event.clientX + mouseDownX + "px";
})
} else {
$border.css("left","0px");
$border.width(borderWidth + borderLeft);
//修改裁剪框触点的定位
$(".left-m").each(function () {
this.style.left = (borderWidth + borderLeft)/2 + "px";
});
$(".left-r").each(function () {
this.style.left = borderWidth + borderLeft + "px";
})
}
} else {
$border.css("left", borderLeft + borderWidth + "px");
$border.width(0);
$(".left-m").each(function () {
this.style.left = "0px";
});
$(".left-r").each(function () {
this.style.left = "0px";
})
}
} else if($t.hasClass("left-r")){
//判断右边栏是否拉到左边栏重合
if((borderWidth + event.clientX - mouseDownX) > 0) {
//判断右边栏是否出界
if((borderLeft + borderWidth + event.clientX - mouseDownX) < $("#photo").width()){
$border.width(borderWidth + event.clientX - mouseDownX);
//修改裁剪框触点的定位
$(".left-m").each(function () {
this.style.left = (borderWidth + event.clientX - mouseDownX)/2 + "px";
});
$(".left-r").each(function () {
this.style.left = borderWidth + event.clientX - mouseDownX + "px";
})
} else {
let widthLimit = $("#photo").width() - borderLeft;
$border.width(widthLimit);
//修改裁剪框触点的定位
$(".left-m").each(function () {
this.style.left = (widthLimit)/2 + "px";
});
$(".left-r").each(function () {
this.style.left = widthLimit + "px";
})
}
} else {
$border.width(0);
$(".left-m").each(function () {
this.style.left = "0px";
});
$(".left-r").each(function () {
this.style.left = "0px";
})
}
}
if($t.hasClass("top-t")){
//上边栏拉到下边栏重合
if((borderHeight - event.clientY + mouseDownY) > 0) {
//判断上边栏是否出界
if((borderTop + event.clientY - mouseDownY) > 0){
$border.css("top", borderTop + event.clientY - mouseDownY + "px");
$border.height(borderHeight - event.clientY + mouseDownY);
//修改裁剪框触点的定位
$(".top-m").each(function () {
this.style.top = (borderHeight - event.clientY + mouseDownY)/2 + "px";
});
$(".top-b").each(function () {
this.style.top = borderHeight - event.clientY + mouseDownY + "px";
})
} else {
$border.css("top","0px");
$border.height(borderHeight + borderTop);
//修改裁剪框触点的定位
$(".top-m").each(function () {
this.style.top = (borderHeight + borderTop)/2 + "px";
});
$(".top-b").each(function () {
this.style.top = borderHeight + borderTop + "px";
})
}
} else {
$border.css("top", borderTop + borderHeight + "px")
$border.height(0);
$(".top-m").each(function () {
this.style.top = "0px";
});
$(".top-b").each(function () {
this.style.top = "0px";
})
}
} else if($t.hasClass("top-b")){
//判断下边栏是否拉到上边栏重合
if((borderHeight + event.clientY - mouseDownY) > 0) {
//判断右边栏是否出界
if((borderTop + borderHeight + event.clientY - mouseDownY) < $("#photo").height()){
$border.height(borderHeight + event.clientY - mouseDownY);
//修改裁剪框触点的定位
$(".top-m").each(function () {
this.style.top = (borderHeight + event.clientY - mouseDownY)/2 + "px";
});
$(".top-b").each(function () {
this.style.top = borderHeight + event.clientY - mouseDownY + "px";
})
} else {
let heightLimit = $("#photo").height() - borderTop;
$border.height(heightLimit);
//修改裁剪框触点的定位
$(".top-m").each(function () {
this.style.top = (heightLimit)/2 + "px";
});
$(".top-b").each(function () {
this.style.top = heightLimit + "px";
})
}
} else {
$border.height(0);
$(".top-m").each(function () {
this.style.top = "0px";
});
$(".top-b").each(function () {
this.style.top = "0px";
})
}
}
updateClip($border);
updatePreview($border);
}
return false;
})
});
</script>
</head>
<body>
<div id="photo">
<img id="img-back" src="http://ofjjubwp5.bkt.clouddn.com/image/jpg/13.jpg" alt="">
<img id="img-clip" src="http://ofjjubwp5.bkt.clouddn.com/image/jpg/13.jpg" alt="">
<div id="clip-win">
<div class="win-btn left-l top-t" id="nw-resize"></div>
<div class="win-btn left-l top-m" id="e-resize"></div>
<div class="win-btn left-l top-b" id="sw-resize"></div>
<div class="win-btn left-m top-t" id="n-resize"></div>
<div class="win-btn left-m top-b" id="s-resize"></div>
<div class="win-btn left-r top-t" id="ne-resize"></div>
<div class="win-btn left-r top-m" id="w-resize"></div>
<div class="win-btn left-r top-b" id="se-resize"></div>
</div>
</div>
<div id="preview">
<img src="http://ofjjubwp5.bkt.clouddn.com/image/jpg/13.jpg" id="preview-img">
</div>
</body>
</html>