分散的宝丽来照片 - 使用 CSS3 和 jQuery 提供图像动画






4.95/5 (66投票s)
散射的宝丽来就像你拿起一盒旧照片,把它们全部倒在桌子上,然后随机挑选。这篇文章将介绍 CSS3 和 jQuery 实现的这个概念。
目录
- 引言
- 系统要求
- 宝丽来相框盒
- 加载图片
- 创建宝丽来图片
- 生成随机位置和旋转
- 定位和旋转宝丽来图片
- 使用 CSS3 盒阴影
- 拖放宝丽来图片
- 拿起一张宝丽来图片
- 放下宝丽来图片
- 通过 JavaScript 动画过渡
- 最终思考
- 历史
引言
散射的宝丽来是我为我的朋友 Janaina Rossi Moreira 开发的一个项目的第一个部分,她是一家名为“As Bárbaras do Multeatro”的巴西戏剧公司工作。
该项目的目标是宣传公司的作品,同时为访客提供美好的视听体验,依靠多媒体、视频、图像、诗歌和回忆,以更好地捕捉公司的艺术精髓。
导航照片集的方法有很多,通常是有序的。散射的宝丽来是一种不同的方法,就像你拿起一盒旧照片,把它们全部倒在桌子上,然后随机挑选。这篇文章将介绍这种技术,希望对你有所帮助。
系统要求
为了运行本文附带的散射的宝丽来示例,您必须拥有支持 CSS3 2D 转换的浏览器
- Internet Explorer 9 或更高版本
- Firefox
- Safari
- Chrome
宝丽来相框盒
宝丽来相框盒是容纳图片的元素,也将接收一些鼠标功能所需的事件。
您的页面中必须有一个 polaroid_box div
,或者另一个可以作为图片容器的 div。
<body>
<div class="polaroid_box">
</div>
</body>
加载图片
图片加载到一个简单的字符串数组中,该数组描述了图片的 URL 路径。
$(document).ready(function () {
var images = new Array();
images[0] = 'Images/Barbaras1.jpg';
images[1] = 'Images/Barbaras2.jpg';
images[2] = 'Images/Barbaras3.jpg';
images[3] = 'Images/Barbaras4.jpg';
images[4] = 'Images/Barbaras5.jpg';
images[5] = 'Images/Barbaras6.jpg';
images[6] = 'Images/Barbaras7.jpg';
images[7] = 'Images/Barbaras8.jpg';
images[8] = 'Images/Barbaras9.jpg';
images[9] = 'Images/Barbaras10.jpg';
images[10] = 'Images/Barbaras11.jpg';
images[11] = 'Images/Barbaras12.jpg';
images[12] = 'Images/Barbaras13.jpg';
images[13] = 'Images/Barbaras14.jpg';
images[14] = 'Images/Barbaras15.jpg';
images[15] = 'Images/Barbaras16.jpg';
images[16] = 'Images/Barbaras17.jpg';
images[17] = 'Images/Barbaras18.jpg';
images[18] = 'Images/Barbaras19.jpg';
images[19] = 'Images/Barbaras20.jpg';
...
数组加载完成后,您可以调用 createPolaroids
函数来渲染给定父元素内的所有必需 DOM 元素。
...
maxZIndex = images.length;
createPolaroids($('.polaroid_box'), images);
...
创建宝丽来图片
在这里,最重要的一点显然是创建 DOM 元素,它们将为我们渲染页面上的宝丽来图片。请注意,我们将大量依赖 jQuery JavaScript 框架。这将减少大部分繁琐的工作,并确保我们避免跨浏览器问题。
function createPolaroids($parentEl, images) {
var parentWidth = $parentEl.width();
var parentHeight = $parentEl.height();
for (var i = 0; i < images.length; i++) {
var polaroidHtml =
'<div id="polaroid' + (i + 1) + '" class="polaroid">' +
' <img id="img' + (i + 1) + '" class="photo" />' +
' <img src="Images/Polaroid_2.png" class="polaroid_photo" />' +
'</div>';
$parentEl.append(polaroidHtml);
var $polaroid = $('#polaroid' + (i + 1));
var $img = $('#img' + (i + 1));
var width = $polaroid.width();
var height = $polaroid.height();
$img.attr('src', images[i]);
$polaroid.css('z-index', 1000);
}
...
生成随机位置和旋转
我们需要为每个宝丽来图片生成随机位置和旋转,否则就不能称之为“散射的”宝丽来。所以,这里我们要做的就是生成落在我们屏幕可接受边界内的数字(也就是说,图片被包含在一个框内,所以我们不希望图片超出屏幕)。
for (var i = 0; i < images.length; i++) {
var $el = $('#polaroid' + (i + 1));
var windowWidth = $(window).width();
var windowHeight = $(window).height();
var offset = (windowWidth - windowHeight) / 2;
var width = $el.width();
var height = $el.height();
var rotation = Math.random() * maxRotationAngle * 2 - maxRotationAngle;
var left = offset + Math.random() * (parentHeight - width);
var top = Math.random() * (parentHeight - height);
...
}
现在我们已经收集了宝丽来图片所需的所有数据,我们创建一个新的宝丽来类型来保存这些信息。这将有助于封装数据并提供操作宝丽来图片的方法。
for (var i = 0; i < images.length; i++) {
...
polaroids[i] = new polaroid(i + 1, $el, $parentEl, minScale,
rotation, left, top, width / 2, height / 2, i);
}
然后将信息作为构造函数提供给 polaroid
函数,该函数将在实例中保存参数。
function polaroid(id, $el, $parentEl, scale, rotation, left,
top, xTransOrigin, yTransOrigin, zIndex) {
this.id = id;
this.$el = $el;
this.$parentEl = $parentEl;
this.scale = scale;
this.rotation = rotation;
this.originalScale = scale;
this.originalRotation = rotation;
this.originalLeft = left;
this.originalTop = top;
this.originalZIndex = zIndex;
this.startRotation = rotation;
this.left = left;
this.top = top;
this.xTransOrigin = xTransOrigin
this.yTransOrigin = yTransOrigin;
this.interval = null;
this.isMoving = false;
this.zIndex = zIndex;
this.xOffset = 0;
this.yOffset = 0;
}
定位和旋转宝丽来图片
加载完宝丽来图片数据后,我们就可以调用 updateLayout
prototype 函数,它将相应地更新所需的 CSS 属性。
polaroid.prototype.updateLayout = function () {
this.$el.css('left', this.left + 'px');
this.$el.css('top', this.top + 'px');
this.$el.css('z-index', this.zIndex);
var transform =
'rotate(' + this.rotation + 'deg) scale(' + this.scale + ')';
this.$el.css({ "-webkit-transform": transform,
"-moz-transform": transform, msTransform: transform });
};
值得注意的是,上面代码片段中的最后一行提供了主要浏览器的 CSS 转换。
- -webkit-transform:Chrome 和 Safari
- -moz-transform:Firefox
- msTransform:Internet Explorer
使用 CSS3 盒阴影
CSS3 盒阴影提供了勾勒我们图片的阴影。这是一个很棒的功能,可以使我们的页面在视觉上更具吸引力。但就像世界上大多数美好的事物一样,您应该适度使用它。盒阴影可能需要大量的处理,这取决于您如何使用它。我们的 polaroid
CSS 类定义了一个盒阴影,偏移量为 (4,4),深度为 32 像素。
.polaroid
{
...
-moz-box-shadow: 4px 4px 32px #000;
-webkit-box-shadow: 4px 4px 32px #000;
box-shadow: 4px 4px 32px #000;
...
}
正如您稍后在本文中将看到的,我们在宝丽来图片动画期间会移除盒阴影,以提高性能。作为一种建议,最好完全放弃使用盒阴影,而是用静态的 .png 图片(PNG 图片支持透明度)替换它们,从而提高性能。
拖放宝丽来图片
应用程序通过将宝丽来图片实例存储在 selectedPolaroid
变量中来知道哪个宝丽来图片正在被拖动。当您单击某个宝丽来图片时,该宝丽来图片的 mousedown 事件将被触发,并且 selectedPolaroid
将被存储。
$('.polaroid').mousedown(function (event) {
var id = $(this).attr('id');
var i = id.replace('polaroid', '');
var polaroid = polaroids[i - 1];
if (polaroid.scale == minScale) {
polaroid.zIndex = maxZIndex++;
polaroid.updateLayout();
if (selectedPolaroid) {
selectedPolaroid = null;
}
else {
selectedPolaroid = polaroid;
selectedPolaroid.xOffset = event.pageX - selectedPolaroid.left;
selectedPolaroid.yOffset = event.pageY - selectedPolaroid.top;
}
}
else {
if (zoomedPolaroid.id == polaroid.id) {
polaroid.drop();
}
}
});
从这一点开始,任何鼠标移动都将由宝丽来图片盒的 mousemove
事件触发,并且选定的宝丽来图片位置将被更新。
$polaroid_box.mousemove(function (event) {
if (selectedPolaroid) {
selectedPolaroid.left = event.pageX - selectedPolaroid.xOffset;
selectedPolaroid.top = event.pageY - selectedPolaroid.yOffset;
selectedPolaroid.updateLayout();
}
});
当您释放鼠标按钮时,拖放操作将结束。此时,我们将 selectedPolaroid
变量设置为 null
。
$polaroid_box.mouseup(function (event) {
if (selectedPolaroid) {
selectedPolaroid.originalLeft = selectedPolaroid.left;
selectedPolaroid.originalTop = selectedPolaroid.top;
selectedPolaroid = null;
}
});
拿起一张宝丽来图片
在某个时候,您发现一张有趣的图片并想更近地查看它。所以您双击它。这将触发我们应用程序中的动画功能,将宝丽来图片带到前面。图片将看起来更大,并且完美地居中显示。这是通过一个动画完成的,这是此应用程序中更复杂的部分,稍后将进行详细解释。一旦图片被拿起,我们就会设置 zoomedPolaroid
变量,并等待用户放下它或双击另一张图片。
$('.polaroid').dblclick(function () {
var id = $(this).attr('id');
var i = id.replace('polaroid', '');
var polaroid = polaroids[i - 1];
if (zoomedPolaroid) {
zoomedPolaroid.zIndex = maxZIndex++;
zoomedPolaroid.updateLayout();
zoomedPolaroid.drop(null, function () {
zoomedPolaroid = null;
});
}
if (polaroid.scale == minScale) {
polaroid.originalZIndex = maxZIndex++;
polaroid.zIndex = maxZIndex + 1000;
polaroid.updateLayout();
polaroid.pull(null, function () {
zoomedPolaroid = polaroids[polaroid.id - 1];
selectedPolaroid = null;
});
} else {
polaroid.originalZIndex = maxZIndex++;
polaroid.zIndex = maxZIndex++;
polaroid.drop();
}
});
放下宝丽来图片
当用户单击放大的宝丽来图片或双击另一张宝丽来图片时,它将被放下。这将启动反向动画,宝丽来图片将离开屏幕中心,回到其先前的位置、比例和旋转角度。
通过 JavaScript 动画过渡
动画是复杂的部分。它们需要目标比例、目标旋转角度和目标位置。由于宝丽来图片可能要移到中心或返回到其先前的位置,我们通过将核心功能封装在 animate 函数中来避免代码重复。
首先,我们计算差值(一个用于角度,另一个用于比例,以及两个用于位置的差值)。然后我们计算步长(即,在每次迭代中应用于当前动画值的增量)。然后我们启动 setInterval
函数来重新定位宝丽来图片,旋转它,并更新底层 DOM 元素,直到动画达到目标值。
polaroid.prototype.animate = function (targetScale, targetRotation,
targetLeft, targetTop, beginCallback, endCallback) {
var pol = this;
if (pol.isMoving)
return;
pol.isMoving = true;
var parentWidth = this.$parentEl.width();
var parentHeight = this.$parentEl.height();
var polaroid = pol;
if (beginCallback)
beginCallback(polaroid);
var angleDelta = targetRotation - polaroid.rotation;
var scaleDelta = targetScale - polaroid.scale;
var leftDelta = targetLeft - polaroid.left;
var topDelta = targetTop - polaroid.top;
var steps = animationSteps;
var scaleStep = scaleDelta / steps;
var rotationStep = angleDelta / steps;
var leftStep = leftDelta / steps;
var topStep = topDelta / steps;
var interval;
var rotation = polaroid.rotation;
var scale = polaroid.scale;
var left = polaroid.left;
var top = polaroid.top;
var $polaroid = $('#polaroid' + pol.id);
$polaroid.css('z-index', 100);
$polaroid.css({ "-moz-box-shadow": "0 0 0 #fff" });
$polaroid.css({ "-webkit-box-shadow": "0 0 0 #fff" });
$polaroid.css({ "box-shadow": "0 0 0 #fff" });
var interval = setInterval(function () {
if (
(scaleStep > 0 && scale >= targetScale) ||
(scaleStep < 0 && scale <= targetScale)
) {
scale = targetScale;
}
$polaroid.css({ WebkitTransform: 'rotate(' + rotation +
'deg) scale(' + scale + ')' });
$polaroid.css({ '-moz-transform': 'rotate(' + rotation +
'deg) scale(' + scale + ')' });
$polaroid.css({ msTransform: 'rotate(' + rotation +
'deg) scale(' + scale + ')' });
$polaroid.css('left', left + 'px');
$polaroid.css('top', top + 'px');
if (scale == targetScale) {
$polaroid.css({ "-moz-box-shadow": "4px 4px 32px #000" });
$polaroid.css({ "-webkit-box-shadow": "4px 4px 32px #000" });
$polaroid.css({ "box-shadow": "4px 4px 32px #000" });
pol.isMoving = false;
clearInterval(interval);
rotation = targetRotation;
scale = targetScale;
left = targetLeft;
top = targetTop;
pol.rotation = targetRotation;
pol.scale = targetScale;
pol.left = targetLeft;
pol.top = targetTop;
pol.updateLayout();
if (endCallback)
endCallback(polaroid);
}
rotation += rotationStep;
scale += scaleStep;
left += leftStep;
top += topStep;
}, 5);
};
最终考虑
我希望您喜欢这篇文章和代码。我认为这里介绍的技术简单且有用。请在下面的评论部分告诉我您的想法。
历史
- 2011-08-28:初始版本。