ShiningDan的博客

网页组件制作之图片剪切效果

网页组件制作之图片剪切效果

在该笔记中将学到列表展示中图片剪切效果的方法与展示效果

本系列的是参考慕课网 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>