<div id="container"> <div id="btnDiv"> <button id="btn1">截圖</button> <button id="btn2">確認截圖</button> <button id="btn3">打開</button> </div> <div id="imgDiv"></div> <div id="clipImgDiv"></div> </div>
CSS代碼基本經過javaScript添加前端
<style> body { background-color: black; } </style>
let originWidth; // 圖片原始寬度 let originHeight; // 圖片原始高度 let container = document.getElementById('container'); let imgDiv = document.getElementById('imgDiv'); // 存放mycanvas let btnDiv = document.getElementById('btnDiv'); let clipImgDiv = document.getElementById('clipImgDiv'); // 顯示裁剪所獲的圖片 let btn1 = document.getElementById('btn1'); // 截圖按鈕 let btn2 = document.getElementById('btn2'); // 確認截圖按鈕 let btn3 = document.getElementById('btn3'); // 打開文件按鈕 var oRelDiv = document.createElement("div"); // 截圖框 var scaleX = 1;// 圖片寬度縮放比例(當前實際/原始) var scaleY = 1; // 圖片高度縮放比例(當前實際/原始) //拖拽與拉伸方法 //拖拽拉伸所需參數 let params = { left: 0, top: 0, width: 0, height: 0, currentX: 0, currentY: 0, flag: false, kind: "drag" }; // CSS樣式修改 container.style.display = 'flex'; container.style.flexDirection = 'column'; btnDiv.style.marginBottom = '20px'; btnDiv.style.height = '30px'; imgDiv.style.marginBottom = '20px'; // 建立canvas,用於顯示被裁剪圖片 var myCanvas = document.createElement('canvas'); myCanvas.setAttribute('id', 'myCanvas'); myCanvas.style.display = 'block'; /*myCanvas.style.position = 'absolute';*/ myCanvas.width = 600; myCanvas.height = 600; myCanvas.style.border = "1px solid #d3d3d3"; myCanvas.innerText = '您的瀏覽器不支持 HTML5 canvas 標籤。'; myCanvas.style.zIndex = 'auto'; var ctx = myCanvas.getContext('2d'); // 被裁剪圖片 var img = new Image(); img.src = './images/IMG_1550.jpg'; img.setAttribute('id', 'img'); img.width = 600; img.height = 600; img.onload = function () { console.log('onload()執行...'); ctx.drawImage(img, 0, 0, 600, 600); originWidth = img.naturalWidth; originHeight = img.naturalHeight; console.log('圖片原始寬度=', originWidth); console.log('圖片原始高度=', originHeight); }; // 裁剪獲得的圖片 let clipImg = new Image(); clipImg.src = ''; clipImg.style.height = '100px'; clipImg.style.width = '100px'; clipImg.alt = '裁剪得到圖片...'; // input用於打開文件 let fileInput = document.createElement('input'); fileInput.setAttribute('multiple', 'multiple'); fileInput.setAttribute('type', 'file'); fileInput.setAttribute('id', 'fileInput'); /*btnDiv.appendChild(fileInput);*/ imgDiv.appendChild(myCanvas); /*clipImgDiv.appendChild(clipImg);*/
// 生成本地圖片URL地址 let getObjectURL = function (file) { let url = null; if (window.createObjectURL !== undefined) { // basic url = window.createObjectURL(file); } else if (window.webkitURL !== undefined) { // webkit or chrome url = window.webkitURL.createObjectURL(file); } else if (window.URL !== undefined) { // mozilla(firefox) url = window.URL.createObjectURL(file); } return url; }; // 獲取指定元素DOM const ID = function (id) { return document.getElementById(id); }; //獲取相關CSS屬性方法 let getCss = function (o, key) { return o.currentStyle ? o.currentStyle[key] : document.defaultView.getComputedStyle(o, false)[key]; };
可伸縮截圖框實現思路:java
截圖框由8各控制截圖框大小、位置小div組成,鼠標在選中截圖框後在拖動鼠標的過程當中會根據鼠標位置對截圖框進行實時繪製
// 打開本地圖片 fileInput.addEventListener('change', function () { console.log('change()執行...'); img.src = getObjectURL(this.files[0]); }); btn3.addEventListener("click", function () { fileInput.click(); });
截圖選框的繪製、拖動、大小調整web
btn1.addEventListener("click", function () { var clickFlag = false; // 獲取canvas中圖片實際大小 var iCurWidth = img.width; var iCurHeight = img.height; console.log('圖片當前實際寬度=', iCurWidth); console.log('圖片當前實際高度=', iCurHeight); // 可調整截圖框 oRelDiv.innerHTML = ''; oRelDiv.style.position = "absolute"; oRelDiv.style.width = iCurWidth + "px"; oRelDiv.style.height = iCurHeight + "px"; oRelDiv.style.top = myCanvas.offsetTop + 'px'; console.log('oRelDiv.style.top = ', oRelDiv.style.top); oRelDiv.id = "cropContainer"; var iOrigWidth = originWidth; var iOrigHeight = originHeight; scaleX = iCurWidth / iOrigWidth; // 圖片寬度縮放比例(當前實際/原始) scaleY = iCurHeight / iOrigHeight; // 圖片高度縮放比例(當前實際/原始) console.log('圖片橫向(寬度)縮放比=', scaleX); console.log('圖片縱向(高度)縮放比=', scaleY); // 將oRelDiv插入到myCanvas前 myCanvas.parentNode.insertBefore(oRelDiv, myCanvas); //初始化座標與剪裁高寬 var cropW = 80; //截圖框默認寬度 var cropH = 80; //截圖框默認高度 /*console.log('myCanvas.offsetLeft=', myCanvas.offsetLeft); console.log('myCanvas.offsetTop=', myCanvas.offsetTop);*/ var posX = myCanvas.width / 2 - cropW / 2; // 截圖框左上角x座標 var posY = myCanvas.height / 2 - cropH / 2; // 截圖框左上角y座標 /*console.log('posX=',posX); console.log('posY=',posY);*/ oRelDiv.innerHTML = '<div id="zxxCropBox" style="height:' + cropH + 'px; width:' + cropW + 'px; position:absolute; left:' + posX + 'px; top:' + posY + 'px; border:1px solid black;">' + '<div id="zxxDragBg" style="height:100%; background:white; opacity:0.3; filter:alpha(opacity=30); cursor:move"></div>' + '<div id="dragLeftTop" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; left:-3px; top:-3px; cursor:nw-resize;"></div>' + '<div id="dragLeftBot" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; left:-3px; bottom:-3px; cursor:sw-resize;"></div>' + '<div id="dragRightTop" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; right:-3px; top:-3px; cursor:ne-resize;"></div>' + '<div id="dragRightBot" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; right:-3px; bottom:-3px; cursor:se-resize;"></div>' + '<div id="dragTopCenter" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; top:-3px; left:50%; margin-left:-3px; cursor:n-resize;"></div>' + '<div id="dragBotCenter" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; bottom:-3px; left:50%; margin-left:-3px; cursor:s-resize;"></div>' + '<div id="dragRightCenter" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; right:-3px; top:50%; margin-top:-3px; cursor:e-resize;"></div> ' + '<div id="dragLeftCenter" style="position:absolute; width:4px; height:4px; border:1px solid #000; background:white; overflow:hidden; left:-3px; top:50%; margin-top:-3px; cursor:w-resize;"></div>' + '</div>' + '<input type="text" id="cropPosX" value="' + posX / scaleX + '" style="position:relative; top: -26px; width: 30px"/>' + '<input type="text" id="cropPosY" value="' + posY / scaleY + '" style="position:relative; top: -26px; width: 30px"/>' + '<input type="text" id="cropImageWidth" value="' + cropW / scaleX + '" style="position:relative; top: -26px; width: 30px"/>' + '<input type="text" id="cropImageHeight" value="' + cropH / scaleY + '" style="position:relative; top: -26px; width: 30px"/>'; var startDrag = function (point, target, kind) { //point是拉伸點,target是被拉伸的目標,其高度及位置會發生改變 //此處的target與上面拖拽的target是同一目標,故其params.left,params.top能夠共用,也必須共用 //初始化寬高 params.width = getCss(target, "width"); params.height = getCss(target, "height"); //初始化座標 if (getCss(target, "left") !== "auto") { params.left = getCss(target, "left"); } if (getCss(target, "top") !== "auto") { params.top = getCss(target, "top"); } //target是移動對象 point.onmousedown = function (event) { params.kind = kind; params.flag = true; clickFlag = true; if (!event) { event = window.event; } var e = event; params.currentX = e.clientX; //鼠標按下時座標x軸 params.currentY = e.clientY; //鼠標按下時座標y軸 /*console.log('params.currentX=', params.currentX); console.log('params.currentY=', params.currentY);*/ //防止IE文字選中,有助於拖拽平滑 point.onselectstart = function () { return false; }; document.onmousemove = function (event) { let e = event ? event : window.event; clickFlag = false; if (params.flag) { var nowX = e.clientX; // 鼠標移動時x座標 var nowY = e.clientY; // 鼠標移動時y座標 var disX = nowX - params.currentX; // 鼠標x方向移動距離 var disY = nowY - params.currentY; // 鼠標y方向移動距離 if (params.kind === "n") { //上拉伸 //高度增長或減少,位置上下移動 target.style.top = parseInt(params.top) + disY + "px"; target.style.height = parseInt(params.height) - disY + "px"; } else if (params.kind === "w") { //左拉伸 target.style.left = parseInt(params.left) + disX + "px"; target.style.width = parseInt(params.width) - disX + "px"; } else if (params.kind === "e") { //右拉伸 target.style.width = parseInt(params.width) + disX + "px"; } else if (params.kind === "s") { //下拉伸 target.style.height = parseInt(params.height) + disY + "px"; } else if (params.kind === "nw") { //左上拉伸 target.style.left = parseInt(params.left) + disX + "px"; target.style.width = parseInt(params.width) - disX + "px"; target.style.top = parseInt(params.top) + disY + "px"; target.style.height = parseInt(params.height) - disY + "px"; } else if (params.kind === "ne") { //右上拉伸 target.style.top = parseInt(params.top) + disY + "px"; target.style.height = parseInt(params.height) - disY + "px"; target.style.width = parseInt(params.width) + disX + "px"; } else if (params.kind === "sw") { //左下拉伸 target.style.left = parseInt(params.left) + disX + "px"; target.style.width = parseInt(params.width) - disX + "px"; target.style.height = parseInt(params.height) + disY + "px"; } else if (params.kind === "se") { //右下拉伸 target.style.width = parseInt(params.width) + disX + "px"; target.style.height = parseInt(params.height) + disY + "px"; } else { //移動 target.style.left = parseInt(params.left) + disX + "px"; target.style.top = parseInt(params.top) + disY + "px"; } } document.onmouseup = function () { params.flag = false; if (getCss(target, "left") !== "auto") { params.left = getCss(target, "left"); } if (getCss(target, "top") !== "auto") { params.top = getCss(target, "top"); } params.width = getCss(target, "width"); params.height = getCss(target, "height"); /*console.log('params.width=', params.width); console.log('params.height', params.width);*/ //給隱藏文本框賦值 posX = parseInt(target.style.left); posY = parseInt(target.style.top); cropW = parseInt(target.style.width); cropH = parseInt(target.style.height); if (posX < 0) { posX = 0; } if (posY < 0) { posY = 0; } if ((posX + cropW) > iCurWidth) { cropW = iCurWidth - posX; } if ((posY + cropH) > iCurHeight) { cropH = iCurHeight - posY; } //賦值 ID("cropPosX").value = posX; ID("cropPosY").value = posY; ID("cropImageWidth").value = parseInt(ID("zxxCropBox").style.width); ID("cropImageHeight").value = parseInt(ID("zxxCropBox").style.height); /*console.log('posX=',posX); console.log('posY=',posY);*/ }; } }; }; //綁定拖拽 startDrag(ID("zxxDragBg"), ID("zxxCropBox"), "drag"); //綁定拉伸 startDrag(ID("dragLeftTop"), ID("zxxCropBox"), "nw"); startDrag(ID("dragLeftBot"), ID("zxxCropBox"), "sw"); startDrag(ID("dragRightTop"), ID("zxxCropBox"), "ne"); startDrag(ID("dragRightBot"), ID("zxxCropBox"), "se"); startDrag(ID("dragTopCenter"), ID("zxxCropBox"), "n"); startDrag(ID("dragBotCenter"), ID("zxxCropBox"), "s"); startDrag(ID("dragRightCenter"), ID("zxxCropBox"), "e"); startDrag(ID("dragLeftCenter"), ID("zxxCropBox"), "w"); //圖片不能被選中,目的在於使拖拽順滑 ID("myCanvas").onselectstart = function () { return false; }; img.onselectstart = function () { return false; }; });
function cropImage(img, cropPosX, cropPosY, width, height) { /*var cropContainer = ID("cropContainer"); cropContainer.parentNode.removeChild(cropContainer);*/ /*ctx.clearRect(0, 0, myCanvas.width, myCanvas.height);*/ //sx,sy 是相對於圖片的座標。巨坑 var newCanvas = document.createElement('canvas'); newCanvas.setAttribute('id', 'newCanvas'); newCanvas.width = width * scaleX; newCanvas.height = height * scaleY; newCanvas.style.border = "1px solid #d3d3d3"; var newCtx = newCanvas.getContext('2d'); clipImgDiv.appendChild(newCanvas); newCtx.drawImage(img, cropPosX, cropPosY, width, height, 0, 0, width * scaleX, height * scaleY); // canvas轉化爲圖片 var newImage = new Image(); newImage.src = newCanvas.toDataURL("image/png"); newImage.style.marginLeft = '5px'; clipImgDiv.appendChild(newImage); oRelDiv.innerHTML = ''; }
// 確認截圖 btn2.addEventListener("click", function () { console.log("clipend......"); var x = document.getElementById("cropPosX").value; var y = document.getElementById("cropPosY").value; var w = document.getElementById("cropImageWidth").value; var h = document.getElementById("cropImageHeight").value; console.log('cropImage(img,', x, ',', y, ',', parseInt(w), ',', parseInt(h), ')'); cropImage(img, x / scaleX, y / scaleY, parseInt(w) / scaleX, parseInt(h) / scaleY); });
參考文章:https://blog.csdn.net/qq_3870...chrome
我是Cloudy,年輕的前端攻城獅一枚,愛專研,愛技術,愛分享。
我的筆記,整理不易,感謝閱讀、點贊和收藏。
文章有任何問題歡迎你們指出,也歡迎你們一塊兒交流前端各類問題!