纯js实现头像上传预览加剪裁效果

23 篇文章 0 订阅

效果展示:

代码展示:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>头像上传预览加剪裁效果</title>
<script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js"></script>
<style>
div.uploadButton {
    border:1px solid #555;
    width:50px;
    height:20px;
    cursor:pointer;
    background:#fff;
    border-radius:4px;
    overflow:hidden;
}
div.rangeInputBox {
    margin:30px auto;
}
input[type=file] {
    display:none;
}
input[type=file]:focus {
    outline:none;
}
input[type=range].RangeInput {
    width:220px;
    height:12px;
    padding:0;
    margin:0 10px;
    vertical-align:middle;
    background:transparent;
    -webkit-appearance:none;
    -moz-appearance:none;
    appearance:none;
}
input[type=range].RangeInput:focus {
    outline:none
}
input[type=range].RangeInput::-webkit-slider-runnable-track {
    height:5px;
    cursor:pointer;
    background:#f2f5fb;
    border-radius:2px
}
input[type=range].RangeInput::-webkit-slider-thumb {
    width:12px;
    height:12px;
    margin-top:-4px;
    cursor:pointer;
    background:#d2dbe8;
    border-radius:50%;
    -webkit-appearance:none;
    appearance:none
}
input[type=range].RangeInput::-moz-range-track {
    height:5px;
    cursor:pointer;
    background:#f2f5fb;
    border-radius:2px
}
input[type=range].RangeInput::-moz-range-thumb {
    width:12px;
    height:12px;
    cursor:pointer;
    background:#d2dbe8;
    border:none;
    border-radius:50%
}
input[type=range].RangeInput::-ms-track {
    width:100%;
    height:5px;
    color:transparent;
    cursor:pointer;
    background:transparent;
    border-color:transparent
}
input[type=range].RangeInput::-ms-fill-lower,input[type=range].RangeInput::-ms-fill-upper {
    background:#f2f5fb;
    border-radius:2px
}
input[type=range].RangeInput::-ms-thumb {
    width:12px;
    height:12px;
    cursor:pointer;
    background:#d2dbe8;
    border:none;
    border-radius:50%
}
input[type=range].RangeInput::-ms-tooltip {
    display:none
}
</style>
</head>
<body>
<div>
    <div class="uploadButton">
        上传文件
        <input class="fileInput" accept="image/png,image/jpeg" type="file">
    </div>
    <div>
        <canvas class="canvas" width="240" height="240" style="cursor: move">
         Your browser not support HTML5.
    </canvas>
    </div>
    <div class="rangeInputBox">
        <input class="rangeInput" type="range" step="0.01" min="1" max="2" value="1">
    </div>
</div>

<script>
! function() {
    var canvas = document.getElementsByClassName("canvas")[0];
    var ctx = canvas.getContext("2d");

    var border = {
        width: 40 //头像边框厚度
            ,
        color: "rgba(247, 248, 250, .9)" //头像边框颜色
    }

    var minImgRect = {
        width: null,
        height: null
    }; //图像的最小高度与宽度
    var currLoc = {
        x: null,
        y: null
    }; //保存当前图片在canvas里的位置
    var imgRect = {
        width: null,
        height: null
    }; //保存当前图像的宽度与高度(缩放后)
    var midpoint = null; //保存当前图片的居中比例,拖动时清空,缩放时重新计算
    //    居中比例:以canvas中轴线为基准将图片切成两部分,左侧部分占总宽度的比例,y方向同理。

    var rangeInput = document.getElementsByClassName("rangeInput")[0]; //滑块对象
    var uploadButton = document.getElementsByClassName("uploadButton")[0]; //图像上传按钮对象
    var fileInput = uploadButton.getElementsByClassName("fileInput")[0]; //图像上传控件
    var image = new Image(); //图像文件

    //<div>元素模拟图片上传按钮
    uploadButton.onclick = function(event) {
        return fileInput.click();
    }

    //图片上传处理代码
    fileInput.addEventListener('change', function(event) {
        var file = fileInput.files[0];
        image.src = URL.createObjectURL(file);
        image.onload = function(event) {
            //缩放图片到刚好填满中框
            if (image.width < image.height) {
                minImgRect.width = canvas.width - border.width * 2;
                minImgRect.height = parseInt(minImgRect.width / image.width * image.height);
            } else {
                minImgRect.height = canvas.height - border.width * 2;
                minImgRect.width = parseInt(minImgRect.height / image.height * image.width);
            }
            //绘制初始图片
            imgRect.width = minImgRect.width;
            imgRect.height = minImgRect.height;
            drawing(centerImg({
                x: 0.5,
                y: 0.5
            }));
        };
    }, false);

    //根据居中比例及图像大小,计算放置图片的坐标
    //    参数: {x: <0-1>, y: <0-1>}
    //    结果: {x: <coordinate_X>, y: <coordinate_Y>}
    function centerImg(ratio) {
        return { // 居中时应满足如下条件,借此计算出偏移量 x 和 y
            x: canvas.width / 2 - imgRect.width * ratio.x, // 横坐标偏移(x) + 图像宽度*横向居中比例 应等于 canvas 宽度的一半(中点横坐标)
            y: canvas.height / 2 - imgRect.height * ratio.y // 纵坐标偏移(y) + 图像高度*纵向居中比例 应等于 canvas 高度的一半(中点纵坐标)
        };
    }

    //绘制图片到canvas
    function drawing(loc) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(image, loc.x, loc.y, imgRect.width, imgRect.height); //指定坐标输出图像
        ctx.strokeStyle = border.color; // \
        ctx.lineWidth = border.width; // | 绘制半透明边框 
        ctx.strokeRect(border.width / 2, border.width / 2, canvas.width - border.width, canvas.height - border.width); // /
        currLoc = {
            x: loc.x,
            y: loc.y
        };
    }

    //缩放相关代码
    rangeInput.oninput = function(event) {
        //检查缩放前是否发生过拖动(midpoint是否被清除),如果是则重新计算居中比例
        if (midpoint == null) {
            midpoint = {
                x: (canvas.width * 0.5 - currLoc.x) / imgRect.width,
                y: (canvas.height * 0.5 - currLoc.y) / imgRect.height
            }
        }

        imgRect.width = minImgRect.width * parseFloat(this.value);
        imgRect.height = minImgRect.height * parseFloat(this.value);
        loc = centerImg(midpoint);
        //检查计算出的位置是否存在脱离中框的情况
        if (loc.x > 40) {
            midpoint = null; //由于发生位移,需要情况居中比例,重新计算
            loc.x = 40;
        }
        if (loc.x + imgRect.width < canvas.width - 40) {
            midpoint = null;
            loc.x = canvas.width - 40 - imgRect.width;
        }
        if (loc.y > 40) {
            midpoint = null;
            loc.y = 40;
        }
        if (loc.y + imgRect.height < canvas.height - 40) {
            midpoint = null;
            loc.y = canvas.height - 40 - imgRect.height;
        }
        drawing(loc);
    }

    //拖动相关代码
    canvas.onmousedown = function(event) {
        var lastMouseLoc = {
            x: event.clientX,
            y: event.clientY
        };

        document.onmousemove = function dragging(event) {
            midpoint = null; //由于位置改变,居中比例需要清空,以便在缩放时重新计算。
            var mouseMove = {
                x: event.clientX - lastMouseLoc.x,
                y: event.clientY - lastMouseLoc.y
            };
            lastMouseLoc = {
                x: lastMouseLoc.x + mouseMove.x,
                y: lastMouseLoc.y + mouseMove.y
            };

            if (currLoc.x + mouseMove.x > 40) { //禁止图像向左拖出中框
                mouseMove.x = 40 - currLoc.x;
            }
            if (currLoc.x + mouseMove.x + imgRect.width < canvas.width - 40) { //禁止图像向右拖出中框
                mouseMove.x = canvas.width - 40 - currLoc.x - imgRect.width;
            }
            if (currLoc.y + mouseMove.y > 40) { //禁止图像向下拖出中框
                mouseMove.y = 40 - currLoc.y;
            }
            if (currLoc.y + mouseMove.y + imgRect.height < canvas.height - 40) { //禁止图像向上拖出中框
                mouseMove.y = canvas.height - 40 - currLoc.y - imgRect.height;
            }

            drawing({
                x: currLoc.x + mouseMove.x,
                y: currLoc.y + mouseMove.y
            });
        }

        document.onmouseup = function(event) {
            document.onmousemove = null;
        }
    };
}()
</script>

<pre style="color:red">
   感:  最近贡献一下我在教学中的小案例  希望能给你一些帮助

                                                              --王      
</pre>

</body>
</html>

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值