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> <!-- 九宫格图片 --> <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; } /* 九宫格 */ .wrap{ width: 456px; height: 456px; margin: 0 auto; display: flex; flex-wrap: wrap; justify-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") //监听 更新 按钮的点击 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') } } }