日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

html木桶布局,木桶布局 实现

發(fā)布時(shí)間:2023/12/10 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 html木桶布局,木桶布局 实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

百度圖片

圖片來(lái)自 百度圖片

像這樣高度一樣,而寬度不同的布局方式稱(chēng)之為木桶布局。它有幾個(gè)鮮明的特點(diǎn): 每行的圖片高度一致;每行的圖片都是占滿(mǎn)的。

如何實(shí)現(xiàn)木桶布局 之 整體思路

我們需要先擁有一些素材(圖片), 并且將這些圖片橫向擺放到頁(yè)面上。假如我現(xiàn)在有100張圖片,并且編號(hào)1~100, 它們的寬高都不是固定的。現(xiàn)在我們需要將圖片都擺放到目標(biāo)頁(yè)面上。

首先,我們每行的高度是事先設(shè)定的,所以我們?cè)诎褕D片放入每一行(row)的時(shí)候,需要先調(diào)整圖片的大小(等比例放大或縮小)使得圖片的高度與行容器的高度一致 —— 即下圖中的藍(lán)色方框。

其中: 橙色方框代表圖片(假設(shè)已和藍(lán)色方框等高), 黑色數(shù)字代表圖片編號(hào)。

依次往行容器中放置等比例大小調(diào)整過(guò)的圖片,①號(hào)圖片,②號(hào)圖片,...,一直到⑤號(hào)圖片,發(fā)現(xiàn)⑤號(hào)圖片它放不下了。這時(shí)候我們就需要把這個(gè)⑤號(hào)圖片放到下一行的開(kāi)頭,并且再次調(diào)整圖片大小,使得第一行中的①號(hào)-④號(hào)圖片能夠撐滿(mǎn)第一行。該次調(diào)整主要是調(diào)整圖片的高度,使得其寬度能夠自適應(yīng)撐滿(mǎn)該行。

如果測(cè)量一下百度圖片每行的高度就會(huì)發(fā)現(xiàn): 每行高度基本相等,但有幾像素的差距。

木桶布局原理

然后重復(fù)上述步驟,直至圖片擺放完畢。

木桶布局代碼實(shí)現(xiàn) 之 具體步驟

從HTML、CSS、JS部分依次實(shí)現(xiàn)。

大概有個(gè)結(jié)構(gòu),就是先有一個(gè)固定寬度的父容器,與若干個(gè)(數(shù)量未定的)行容器來(lái)盛放每行的圖片數(shù)量,然后每行有若干個(gè)圖片容器來(lái)盛放圖片。

父子關(guān)系(父 > 子): 固定寬度的父容器 (" .ct ") > 行容器(" .img-row ") > 圖片容器(" .img-box ")

對(duì)應(yīng)上圖(木桶布局原理)為: 紅色方框 > 藍(lán)色方框 > 橙色方框

/* CSS */

/* 頁(yè)面布局容器*/

.ct {

width: 1000px;

margin: 0 auto;

}

/* 圖片容器 */

.img-box {

float: left;

}

/* 行容器 清楚子元素(圖片容器)的浮動(dòng)*/

.img-row::after {

content: "";

display: block;

clear: both;

}

JS代碼

這里采用構(gòu)造函數(shù)創(chuàng)建對(duì)象的方式來(lái)寫(xiě)這段代碼,注意按照約定構(gòu)造函數(shù)的首字母要大寫(xiě)。創(chuàng)建一個(gè)新對(duì)象,然后將構(gòu)造函數(shù)的作用域賦給新對(duì)象,調(diào)用構(gòu)造函數(shù)中的方法。

函數(shù)名聲明為 Barrel ,意為木桶。然后就要確定有哪些屬性和方法。在理解了思路步驟的前提下,可以構(gòu)思需要哪些屬性、方法以及它們的作用。

屬性:

每行圖片的高度固定: rowHeight, 行高

擁有一個(gè)固定的容器: DOM對(duì)象,一個(gè)容器 命名為 .ct。 還應(yīng)該有行容器和圖片容器,但是由于這兩個(gè)容器內(nèi)容數(shù)量不固定,所以在布局的時(shí)候再創(chuàng)建

行容器的寬度: width, 獲取ct的寬度

存放每行圖片的數(shù)組: imgArr[]。每次把加載的圖片壓入該數(shù)組,判斷該行是否超出寬度。

方法:

擁有素材圖片 : 通過(guò)getImgUrls()方法來(lái)獲取圖片鏈接,(或從數(shù)據(jù)庫(kù)中獲取圖片)。這里是通過(guò)訪問(wèn)https://placeholder.com/ 網(wǎng)站來(lái)獲取代碼,具體后述

加載圖片信息: loadImg()方法來(lái)加載圖片,以便獲取圖片信息,

渲染圖片隊(duì)列: render() 改變圖片的比例大小,計(jì)算一行可以放置多少個(gè)圖片

放置圖片位置: layout() 將改變完大小的圖片放置到頁(yè)面上,append到對(duì)應(yīng)的DOM元素節(jié)點(diǎn)上。具體關(guān)系對(duì)應(yīng)前面的父子關(guān)系即可

初步的代碼結(jié)構(gòu)就如下所示:

function Barrel(ct, imgNum, height) {

this.ct = ct; // 木桶布局容器的DOM節(jié)點(diǎn)

this.width = parseInt(window.getComputedStyle(ct, null).getPropertyValue("width")); // 行寬,由于獲取到的值是string: 1000px 所以轉(zhuǎn)化為數(shù)值 1000

this.rowHeight = height; // 行高

this.imgArr = []; // 存放每行圖片的數(shù)組

this.loadImg(imgNum);

}

Barrel.prototype = {

getImgUrls: function(){},

loadImg: function(){},

render: function(){},

layout: function(){}

}

方法實(shí)現(xiàn):

getImgUrls()方法:首先可以訪問(wèn)該網(wǎng)站 ,可以獲取到占位圖片,可以看到獲取占位圖片的格式 : http://via.placeholder.com/width x height /ffffff/00000/ , width與height分別代表圖片的寬高,fffff是圖片的背景顏色,000000是圖片的文本顏色。

隨機(jī)生成圖片的大小(寬高限定一個(gè)范圍),背景顏色與文本顏色。這里添加一個(gè)參數(shù),imgNum:確定需要圖片的數(shù)量。最后返回包含這些圖片鏈接的一個(gè)數(shù)組

getImgUrls: function(imgNum){

let imgUrls = [];

let colorArr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]; // 顏色數(shù)組[0-9, A-F],

// 該顏色數(shù)組生成與源代碼稍有不同,在我的GitHub上是用for循環(huán)生成的

for(let i = 0; i < imgNum; i++) {

let imgWidth = Math.floor(Math.random()*50+50); // 設(shè)定寬度50-100

let imgHeight = Math.floor(Math.random()*30+50); // 設(shè)定高度為30-80

let bgColor = textColor = ""; // 下面使用的是字符串拼接,每次使用都需要重新清空

for(let j=0; j < 6; j++){

bgColor += colorArr[Math.floor(Math.random()*16)];

textColor += colorArr[Math.floor(Math.random()*16)];

}

let url = "http://via.placeholder.com/" + imgWidth + "x" + imgHeight + "/" + bgColor + "/" + textColor;

imgUrls.push(url);

}

return imgUrls;

}

loadImg() 方法:用來(lái)加載圖片,圖片來(lái)源就從已有素材中尋找。即getImgUrls()

在這個(gè)方法中,需要做的就是獲取圖片信息(寬高,src等)并改變大小,高度與行高一致,寬度等比例改變。并且將信息存儲(chǔ)起來(lái),等每張圖片加載完畢后就加入渲染排列圖片的隊(duì)列中。

loadImg: function(imgNum){

let imgUrlsArr = this.getImgUrls(imgNum);

let _this = this; // 保存this指針的指向,方便調(diào)用屬性及方法

for(let i = 0; i < imgNum; i++){

let newImg = new Image(); // 新建圖片對(duì)象

newImg.src = imgUrlsArr[i]; // 加載圖片內(nèi)容

newImg.onload = function(){

// Image對(duì)象加載了src后擁有寬高屬性, imgInfo存儲(chǔ)圖片信息

let ratio = this.width / this.height;

let imgInfo = {

target: this, // 用來(lái)存放當(dāng)前目標(biāo)newImg,方便后續(xù)調(diào)用

height: _this.rowHeight,

width: ratio * _this.rowHeight, // 等比例縮放

ratio: ratio,

};

// 把加載完的圖片加入渲染隊(duì)列

_this.render(imgInfo);

}

}

},

render()方法:渲染隊(duì)列的方法,主要是判斷圖片能否放在一行上(每次把圖片加入到imgArr隊(duì)列中就可判斷長(zhǎng)度),并當(dāng)圖片符合占滿(mǎn)一行的條件時(shí),將最后一張圖片放到下一行,并記錄需要改變的圖片比例交由layout()方法更改。

render: function(imgInfo){

// 定義該行圖片寬度之和

let wholeWidth = 0;

this.imgArr.push(imgInfo);

for(let i = 0; i < this.imgArr.length; i++){

wholeWidth += this.imgArr[i].width;

}

// 如果該行加入的圖片寬度大于了該行的寬度

// 就需要彈出最后一張圖片,并更改前面的圖片大小比例

if(wholeWidth > this.width){

let lastImg = this.imgArr.pop();

wholeWidth -= lastImg.width;

// 利用面積相等原則,來(lái)計(jì)算新的高度

let newHeight = this.width * this.rowHeight / wholeWidth;

this.layout(newHeight);

// 放置完畢之前的圖片之后,清空該圖片隊(duì)列

// 并將上一行溢出的圖片 作為下一行的第一張

this.imgArr = [];

this.imgArr.push(lastImg);

}

}

layout()方法:獲得newHeight參數(shù),是圖片的新高度,改變?cè)撔袌D片的高度,使得這些圖片自適應(yīng)改變寬度之后能占滿(mǎn)該行。也就是說(shuō)這個(gè)木桶布局的高度會(huì)發(fā)生變化 與之前設(shè)定的this.rowHeight相近但不相等。

之后創(chuàng)建節(jié)點(diǎn),并把修改好的圖片依次加入到創(chuàng)建好的節(jié)點(diǎn)上,然后添加到頁(yè)面中。

layout: function(newHeight){

// 一次只放一行, 所以只生成一個(gè)imgRow

let imgRow = document.createElement("div");

imgRow.classList.add("img-row");

// 一行包含若干個(gè)圖片,所以需要若干個(gè)imgBox,并將圖片加入其中

for(let i = 0; i < this.imgArr.length; i++){

let imgBox = document.createElement("div");

imgBox.classList.add("img-box");

let img = this.imgArr[i].target;

// 改變了高度之后寬度自己會(huì)跟著改變

img.style.height = newHeight + "px"; // 注意加"px"

imgBox.appendChild(img);

imgRow.appendChild(imgBox);

}

// 先把圖片加載到圖片盒子里,然后加到圖片列中,最后加到容器中

this.ct.appendChild(imgRow);

}

最后便是兩行代碼來(lái)運(yùn)行這段程序

let ct = document.querySelector(".ct");

let barrel = new Barrel(ct, 100, 100); // 100張圖片數(shù)量, 指定每行的初始行高為100

效果預(yù)覽及代碼地址

總結(jié)

以上是生活随笔為你收集整理的html木桶布局,木桶布局 实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。