box和flexbox_Flexbox和JavaScript的现代砌体

box和flexbox

For some time I have been attempting to recreate “masonry” effects in , where images are arranged like bricks in a wall. My previous attempt was moderately successful, but it ran ragged and lacked the dynamism I wanted.

一段时间以来,我一直在尝试在重新创建“砌体”效果,在其中图像像砖头一样排列在墙上。 我以前的尝试取得了一定程度的成功,但它参差不齐,并且缺乏我想要的动力。

Then, after working on the recent “Random Images With Flexbox and JavaScript” article, I had an epiphany: why not use JavaScript to read the image’s aspect ratios, and use that to determine the correct flex value for each element?

然后,在处理了最近的“ 使用Flexbox和JavaScript的随机图像 ”文章之后,我顿悟了:为什么不使用JavaScript读取图像的长宽比,并使用它来确定每个元素的正确flex值?

This solution allows designers to load images of any dimension and aspect ratio into a container element, apply a class, and have a seamless image masonry effect generated automatically on the page using modern web standards, with no plugins or frameworks required.

该解决方案允许设计人员将任何尺寸和纵横比的图像加载到容器元素中,应用一个类,并使用现代Web标准在页面上自动生成无缝的图像砌体效果,而无需插件或框架。

加载挑战 (The Loading Challenge)

Photograph of a butterfly on a purple flower
Photograph of a butterfly
The script automatically rescales images of different sizes and aspect ratios to fit perfectly together
脚本会自动重新缩放不同大小和纵横比的图像,以完美融合在一起

The first challenge is that an image must be completely loaded onto a page before JavaScript can determine anything about it: just having the <img> tag present is not enough. Historically, there are three main ways of dealing with this:

第一个挑战是,在JavaScript可以确定图像之前,必须将图像完全加载到页面上:仅显示<img>标签是不够的。 从历史上看,有三种主要的处理方法:

  1. Try to detect that every element is loaded before running any more JavaScript.

    在运行更多JavaScript之前,请尝试检测是否已加载每个元素。
  2. Load the images using JavaScript itself.

    使用JavaScript本身加载图像。
  3. Abandon JavaScript entirely, and determine the height and width of the images server-side using PHP or a similar technology.

    完全放弃JavaScript,并使用PHP或类似技术确定服务器端图像的高度和宽度。

For the purposes of illustration I’ll use the first two techniques, although it should be noted that the second runs counter to the principles of progressive enhancement.

为了说明的目的,我将使用前两种技术,不过应注意,第二种技术与渐进增强原理背道而驰。

I’ll start with an empty <div>. The images to be inserted inside the <div> will have <figure> elements wrapped around them, so I’ll set up the styles for the expected DOM content:

我将从一个空的<div> 。 要插入<div>内的图像将在其周围包裹<figure>元素,因此我将为预期的DOM内容设置样式:

* { 
	box-sizing: border-box; 
}
.quantize {
	display: flex;
	flex-flow: row wrap;
	font-size: 0;
	width: 80%;
	margin: 0 auto; 
}
.quantize figure {
	margin: 0; 
}
.quantize figure img {
	width: 100%;
	height: auto; 
}

Then the first part of the JavaScript:

然后是JavaScript的第一部分:

var container = document.getElementsByClassName('quantize')[0];
var butterflies = [ "orange-butterfly.jpg", "butterfly-on-yellow-flower.jpg", "butterfly-on-petal.jpg", "albino-butterfly.jpg", "blue-butterfly.jpg"];
function preloadImage(filename){
	var img=new Image();
	img.onload = function(){
		img.aspectRatio = img.naturalWidth / img.naturalHeight;
		var fig = document.createElement('figure');
		fig.appendChild(img);
		container.appendChild(fig);
	};
img.src= filename;
img.alt = "";
}
function loadImages() {
	for (var i = 0; i < butterflies.length; ++i) { 
		var filename = butterflies[i];
		preloadImage(filename);
		}
	}

The first two lines of code identify the element into which the images will be inserted, and lists the images I want to load as an array. The preloadImage function will be fed the filenames from the array and create new image elements in the DOM from that information. Within that lies an onload method for each image, which creates a new property representing the ratio between the image’s natural width and height. With this information added to the image, the function wraps the image in a <figure> element and adds it inside the container. Note that the order is important: img.onload must be placed before the image source is assigned.

前两行代码标识要插入图像的元素,并以数组的形式列出要加载的图像。 preloadImage函数将从数组中获取文件名,并根据该信息在DOM中创建新的图像元素。 其中包含每个图像的onload方法,该方法创建一个新属性,该属性表示图像的自然宽度和高度之间的比率。 将这些信息添加到图像后,该函数将图像包装在<figure>元素中,并将其添加到容器内。 请注意,顺序很重要:必须在分配图像源之前放置img.onload

Next, we need a function that sorts the images by their aspect ratios, i.e. the number that was calculated earlier. I’ve created a fitFlex function to do just that:

接下来,我们需要一个函数来按图像的长宽比(即较早计算出的数字)对图像进行排序。 我创建了一个fitFlex函数来做到这一点:

function fitFlex() {
	var flexGroup = container.querySelectorAll("figure");
	var flexArray = Array.prototype.slice.call(flexGroup, 0);
	flexArray.sort(function (a, b) { 
		imageAspectRatioA = a.firstElementChild.aspectRatio;
		imageAspectRatioB = b.firstElementChild.aspectRatio;
		if (imageAspectRatioA < imageAspectRatioB) { return 1; }  
		if (imageAspectRatioA > imageAspectRatioB) { return -1; }
		return 0;
	});
	var widest = flexArray[0].firstElementChild.aspectRatio;
	var smallestWidth = "300";
	flexArray.forEach(function(box) { 
		var flex = 1 / (widest / box.firstElementChild.aspectRatio);
		if (flex == 0) { flex = 1; }
		boxWidth = smallestWidth * flex;
		box.style.cssText = "flex: "+flex+"; min-width: "+boxWidth+"px;
		}); 
}

In brief, this code grabs all the created <figure> elements and places them into an array, sorting them so that the figure with the widest image appears first. (Note that this does not change the order in which the images actually appear on the page).

简而言之,这段代码将捕获所有创建的<figure>元素,并将它们放置在数组中,并对它们进行排序,以便首先显示具有最宽图像的图形。 (请注意,这不会更改图像实际在页面上显示的顺序)。

This element will be given a flex value of 1 and the min-width decided in the code, with every other image provided with a flex value and min-width relative to that. For example, the generated code for the first image in the series looks like this:

该元素的flex值为1并且在代码中确定了min-width ,其他每张图片均提供了flex值和相对于它的min-width 。 例如,为系列中的第一张图像生成的代码如下所示:

<figure style="flex: 0.938 1 0px; min-width: 281.425px;"><img src="orange-butterfly.jpg" alt></figure>

The result means that every image, no matter what its height and width, will fit neatly into a grid, once the two functions are called:

结果意味着,一旦调用了以下两个函数,则无论图像的高度和宽度如何,每个图像都可以整齐地放入网格中:

loadImages();
window.addEventListener("load", function() {
	fitFlex();
});

I’m very pleased with the result (although it does have layout problems in Firefox at small viewport sizes) and intend to publish the script on GitHub with more options in the very near future.

我对结果感到非常满意(尽管在视口尺寸较小的Firefox中确实存在布局问题),并打算在不久的将来在GitHub上发布具有更多选项的脚本。

翻译自: https://thenewcode.com/929/Modern-Masonry-with-Flexbox-and-JavaScript

box和flexbox

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值