今天練習一個小demo, 從本地讀取圖片, 然後實現類似淘寶放大鏡的效果, 再加兩個需求 1 .可以調節縮放比例,預設放大兩倍 2 . 圖片寬高自適應, 不固定寬高 話不多說先看效果: 原理:1, 右側放大區域的大小等於左側半透明滑塊大小乘以縮放倍數 2, 右側放大區域圖片的原始尺寸要和 左側圖片一 ...
今天練習一個小demo, 從本地讀取圖片,
然後實現類似淘寶放大鏡的效果,
再加兩個需求
1 .可以調節縮放比例,預設放大兩倍
2 . 圖片寬高自適應, 不固定寬高
話不多說先看效果:
原理:1, 右側放大區域的大小等於左側半透明滑塊大小乘以縮放倍數
2, 右側放大區域圖片的原始尺寸要和
左側圖片一樣,不能隨右側的寬高變化
3, 計算滑塊位置
上代碼: 基本每行都有註釋
HTML:
<!--放大鏡--> <div class="preview"> <div class="preview-header"> <!--選擇本地圖片--> <div class="choose-image"> <lable for="fileInput">選擇圖片</lable> <input type="file" id="fileInput"> </div> <!--調整縮放倍數--> <div class="scale"> <lable for="scaleNum">設置放大倍數</lable> <input type="number" id="scaleNum" value="2"> </div> </div> <!--預覽區域--> <div class="preview-content"> <!--原圖--> <div class="origin"> <img src="" alt="" id="origin-image"> <!--滑塊--> <div class="scale-section"></div> </div> <!--放大後的圖片--> <div class="target"> <img src="" alt="" id="target-image"> </div> </div> </div>
CSS:
/*圖片放大鏡*/ /*頭部*/ .preview-header{ display: flex; padding: 10px; } /*預覽區域*/ .preview-content{ display: none; align-items: flex-start; } /*原始圖片*/ .preview-content .origin{ max-width: 350px; margin: 30px 0px 0px 10px; position: relative; box-shadow:3px 3px 10px 0 #111111; /*給圖片施加陰影效果 */ -webkit-box-shadow: 3px 3px 10px 0 #111111; /*相容性處理*/ -moz-box-shadow: 3px 3px 10px 0 #111111; overflow: hidden; } .preview-content .origin img{ width: 100%; } /*滑塊*/ .origin .scale-section{ display: none; /*初始隱藏*/ position:absolute; top:0; left:0; width:175px; height:175px; background:#000; opacity: 0.3; cursor:move; /*改變滑鼠的形狀*/ } /*右側放大區域的寬高是和滑塊成比例的*/ .preview-content .target{ display: none;/*初始隱藏*/ width: 350px; height: 350px; margin: 30px 0px 0px 30px; position: relative; box-shadow:3px 3px 10px 0 #111111; /*給圖片施加陰影效果 */ -webkit-box-shadow: 3px 3px 10px 0 #111111; /*相容性處理*/ -moz-box-shadow: 3px 3px 10px 0 #111111; overflow: hidden; } /*放大後的圖片*/ .target img{ position: absolute; top: 0; left: 0; transform-origin: top left; }
JS:
// 獲取dom // 原始圖片 const originImage = document.getElementById('origin-image'), // 左側圖片區域 origin = document.getElementsByClassName('origin')[0], // 放大後的圖片 targetImage = document.getElementById('target-image'), // 放大圖片區域 target = document.getElementsByClassName('target')[0], // 整個圖片區域 previewContent = document.getElementsByClassName('preview-content')[0], // 滑塊 scaleSection = document.getElementsByClassName('scale-section')[0], // 文件選擇框 fileInput = document.getElementById('fileInput'), // 放大倍數框 scaleNum = document.getElementById('scaleNum'); // 放大的倍數 let scale = scaleNum.value; // 左側圖片的寬高 let originWidth,originHeight; // 註冊事件 // 選擇文件 fileInput.addEventListener('change',chooseImage,false); // 改變倍數 scaleNum.addEventListener('change',scaleChange,false); // 滑鼠在左側區域移動移動 origin.addEventListener('mousemove',(e) => { // 事件相容 const event = e || window.event; // 計算滑塊以及右邊放大圖片的位置 calculatePosition(event.clientX, event.clientY); scaleSection.style.display = 'block'; target.style.display = 'block'; }, false); // 滑鼠離開左側圖片區域 origin.addEventListener('mouseleave',() => { scaleSection.style.display = 'none'; target.style.display = 'none'; }, false); // 選擇要縮放的圖片 function chooseImage(e) { // 使用file Reader獲取URL // 不懂fileReader的可以參考我之前寫的本地圖片預覽 if (e.target.files[0].type.indexOf('image') === -1) { alert('請選擇圖片'); return } const reader = new FileReader(); reader.onload = () => { // promise是為了等圖片載入完畢取寬高 const P1 = () => { return new Promise((resolve, reject) => { originImage.onload = () => { resolve(originImage); }; originImage.src = reader.result; }) }; const P2 = () => { return new Promise((resolve, reject) => { targetImage.onload = () => { resolve(targetImage); }; targetImage.src = reader.result; }) }; // 獲取左側原圖的大小, // 初始化放大區域的圖片大小 Promise.all([P1(), P2()]).then((data) => { originWidth = data[0].width; originHeight = data[0].height; data[1].style.width = originWidth * scale + 'px'; data[1].style.height = originHeight * scale + 'px'; }); previewContent.style.display = 'flex'; }; reader.readAsDataURL(e.target.files[0]); } function calculatePosition(x,y) { // 設置邊界 const minTop = 0, minLeft = 0, maxTop = origin.offsetHeight - scaleSection.offsetHeight, maxLeft = origin.offsetWidth - scaleSection.offsetWidth; // 計算滑塊的位置 const sectionX = x - origin.offsetLeft - scaleSection.offsetWidth/2; const sectionY = y - origin.offsetTop - scaleSection.offsetHeight/2; // 滑塊的真實位置 // 用於計算右側放大圖片的位置 let realTop = sectionY, realLeft = sectionX; // 左右邊界 if (sectionX < minLeft) { scaleSection.style.left = minLeft + 'px'; realLeft = minLeft; } else if (sectionX >= maxLeft) { scaleSection.style.left = maxLeft + 'px'; realLeft = maxLeft; } else { scaleSection.style.left = sectionX + 'px'; } // 上下邊界 if (sectionY <= minTop) { scaleSection.style.top = minTop + 'px'; realTop = minTop; } else if (sectionY >= maxTop) { scaleSection.style.top = maxTop + 'px'; realTop = maxTop; } else { scaleSection.style.top = sectionY + 'px'; } // 計算右側放大圖片的位置 // 滑塊移動多少, 右側圖片就向反方向移動scale的倍數 targetImage.style.top = -realTop*scale + 'px'; targetImage.style.left = -realLeft*scale + 'px'; } // 縮放比例改變 function scaleChange(e) { scale = e.target.value; targetImage.style.width = originWidth * scale + 'px'; targetImage.style.height = originHeight * scale + 'px'; target.style.width = 175 * scale + 'px'; target.style.height = 175 * scale + 'px'; }
還是那句話,新手自己多動手寫寫,
不然容易一看就會,一寫就懵逼,
感謝觀看!!!