1.原理及說明
九宮格圖片就是將一張圖片分成9份,再拼成一個完整的圖片,如圖:
原理:創建9個正方形容器,利用背景圖定位,每個容器只顯示其中的一部分,最終拼接成一張完整的圖片
實現思路:
(1)使用flex布局,讓9個子元素以 3*3 的形式擺放
(2)因為圖片有縱向和橫向兩種可能,所以要對圖片的寬高比進行判斷,以此來判斷圖片的方向,並根據圖片的方向決定背景圖定位信息。
(3)將圖片的url放入文本框中,通過按鈕點擊事件將url對應的圖片設置成容器的背景圖
(4)使用FileReader()讀取本地選中的圖片時,會花費1-2s的時間,在此時間內顯示一個蒙版遮罩,用來提示用戶“加載中...”
(5)為了美化按鈕,使用了bootstrap
2.HTML代碼
HTML代碼分為3個部分:
(1)操作區,包括文本輸入框和按鈕
(2)九宮格圖片區,用於顯示背景圖
(3)蒙版遮罩
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- 引入bootstrap -->
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="index.css">
<title>九宮格圖片</title>
</head>
<body>
<!-- 操作區 -->
<div id="imgInfo">
<input type="text" id="imgUrl" placeholder="請輸入圖片url">
<button id="fileBtn" class="btn btn-info">瀏覽本地圖庫</button>
<br>
<button id="updateUrl"class="btn btn-primary">更新九宮格圖片</button>
<button id="clearInput"class="btn btn-default">清空輸入框</button>
<br>
<input type="file" name="image" id="file" style="display: none;" accept="image/*">
<div id="paddingCtrBox">
<input type="range" max="10" min="0" id="paddingCtr" title="滑動控制間隙的大小">
</div>
</div>
<!-- 九宮格圖片 -->
<div class="wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<!-- 蒙版 -->
<div id="mask" class="hidden">
<h3 class="text-center">加載中...</h3>
</div>
</body>
<!-- 引入js文件 -->
<script src="index.js"></script>
</html>
3.css文件
(1)為了美化按鈕,引用了bootstrap中的類
(2)九宮格使用了flex布局
(3)蒙版使用了bootstrap中的類,用於顯示/隱藏蒙版
/* 按鈕容器 */
#imgInfo{
margin: 20px;
text-align: center;
}
#imgUrl{
width: 700px;
height: 30px;
line-height: 30px;
margin-bottom: 10px;
}
#imgUrl::placeholder{
color:red;
text-align: center;
}
#paddingCtrBox{
width: 150px;
margin: 10px auto;
}
/* 九宮格 */
.wrap{
width: 456px;
height: 456px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-content: space-between;
/* border: 1px solid black; */
}
.wrap > .box{
width: 150px;
height: 150px;
background-repeat: no-repeat;
/* background-color: #eee; */
}
/* 縱向 */
.wrap > .vertical{
background-size: auto 300%;
}
/* 橫向 */
.wrap > .transverse{
background-size: 300% auto;
}
/* 蒙版 */
#mask{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 99;
background-color: rgba(210, 210, 210, 0.5);
padding-top: 150px;
}
4.js文件
(1)先根據圖片的寬高比來判斷圖片的方向(縱向/橫向)
(2)監聽按鈕點擊,將文本框的url賦給容器的背景圖
(3)根據圖片的方向來設置背景圖的定位信息
(4)使用普通的按鈕來模擬文件域按鈕的點擊,並使用FileReader()存儲選中的圖片
(5)設置蒙版
//計算原圖的寬高比
function getImgProportion(url,cb){
var img = new Image()
img.src = url
img.onload = function(){
var Proportion = img.width/img.height
cb(Proportion,url)
}
}
//根據格子的大小設置背景圖的大小
function setBgc(Proportion,url){
//Proportion<1 縱向
//Proportion>1 橫向
//獲取所有格子
var box = document.getElementsByClassName('box')
//為每個容器設置背景圖的url
for(var i=0;i<box.length;i++){
box[i].style.backgroundImage = `url(${url})`
}
//判斷圖片的方向
if(Proportion<1){
//計算寬高差距
var disparity = box[0].offsetWidth*3 * (1-Proportion)
//添加縱向的類
for(var i=0;i<box.length;i++){
box[i].className = 'box vertical'
}
//左右兩側背景圖片進行橫向偏移
box[0].style.backgroundPosition = `${disparity/2}px 0`
box[1].style.backgroundPosition = '50% 0'
box[2].style.backgroundPosition = `${disparity/2 - box[0].offsetWidth*2}px 0`
box[3].style.backgroundPosition = `${disparity/2}px 50%`
box[4].style.backgroundPosition = '50% 50%'
box[5].style.backgroundPosition = `${disparity/2 - box[0].offsetWidth*2}px 50%`
box[6].style.backgroundPosition = `${disparity/2}px ${-box[0].offsetWidth*2}px`
box[7].style.backgroundPosition = `50% ${-box[0].offsetWidth*2}px`
box[8].style.backgroundPosition = `${disparity/2 - box[0].offsetWidth*2}px ${-box[0].offsetWidth*2}px`
}else{
//計算寬高差距
var disparity = box[0].offsetHeight*3*(1-1/Proportion)
//添加橫向的類
for(var i=0;i<box.length;i++){
box[i].className = 'box transverse'
}
//上下兩側背景圖片進行縱向偏移
box[0].style.backgroundPosition = `0 ${disparity/2}px`
box[1].style.backgroundPosition = `50% ${disparity/2}px`
box[2].style.backgroundPosition = `${-box[0].offsetWidth*2}px ${disparity/2}px`
box[3].style.backgroundPosition = `0 50%`
box[4].style.backgroundPosition = '50% 50%'
box[5].style.backgroundPosition = `${-box[0].offsetWidth*2}px 50%`
box[6].style.backgroundPosition = `0 ${disparity/2 - box[0].offsetWidth*2}px`
box[7].style.backgroundPosition = `50% ${disparity/2 - box[0].offsetWidth*2}px`
box[8].style.backgroundPosition = `${-box[0].offsetWidth*2}px ${disparity/2 - box[0].offsetWidth*2}px`
}
}
//九宮格的函數
function jiuGongGe(){
var imgUrl = document.querySelector('#imgUrl').value
//設置背景圖
getImgProportion(imgUrl,setBgc)
}
window.onload = function(){
//獲取元素
var updateBtn = document.querySelector('#updateUrl')
var clearBtn = document.querySelector('#clearInput')
var fileBtn = document.querySelector('#fileBtn')
var fileInput = document.querySelector('#file')
var maskBox = document.querySelector("#mask")
var paddingCtr = document.querySelector("#paddingCtr")
//監聽 更新 按鈕的點擊
updateBtn.onclick = function(){
jiuGongGe()
}
//監聽 清空 按鈕的點擊
clearBtn.onclick = function(){
document.querySelector('#imgUrl').value = ''
}
//監聽 瀏覽本地圖庫 按鈕的點擊
fileBtn.onclick = function(){
//觸發fileInput的點擊事件
fileInput.click()
}
//監聽fileInput的change事件
fileInput.onchange = function(){
//顯示遮罩(去除hidden類)
maskBox.classList.remove('hidden')
var reader = new FileReader()
reader.readAsDataURL(document.querySelector('#file').files[0])
reader.onload = function() {
//文件已讀取完畢 將結果賦值給文本框
document.querySelector('#imgUrl').value = reader.result
//去除遮罩(添加hidden類)
maskBox.classList.add('hidden')
}
}
//監聽滑塊change事件
paddingCtr.onchange = function(){
//獲取大容器
var wrap = document.querySelector("#wrap")
//設置最小值
var min = 450
//獲取當前滑塊對應的值
var value = Number(paddingCtr.value) * 2
//設置大容器的寬高
wrap.style.width = (min+value) + 'px'
wrap.style.height = (min+value) + 'px'
}
}