使用CSS和JavaScript为图像创建随机Ken Burns效果

Of late AskMen.com has featured some interesting and innovative web design techniques. One of the most notable is a “Ken Burns” technique employed on header images: a subtle combination of zoom and pan that is both engaging and unpredictable, choosing random locations in the image to slowly focus on over time.

最近, AskMen.com推出了一些有趣且创新的网页设计技术。 最引人注目的一项是在标头图像上使用的“肯恩·伯恩斯”技术:缩放和平移的巧妙组合,既吸引人又不可预测,选择图像中的随机位置以随着时间的流逝慢慢聚焦。

A few of my students have been asking how they might achieve this in their own work. While I haven’t looked at the code on the AskMen site, I’m happy to share how I would pull it off, using a little JavaScript to generate a random CSS animation.

我的一些学生一直在问他们如何在自己的工作中实现这一目标。 虽然我还没有看在AskMen网站的代码,我很乐意分享会怎么把它关闭,使用一个小JavaScript生成随机CSS动画

First, we need to set up the image:

首先,我们需要设置图像:

<figure id="burnsbox">
	<img src="janelle-monae.jpg" alt="Photograph of Janelle Monae in concert, shot in silhouette against a blue light">
</figure>

The CSS use a variation of the technique I’ve covered recently: a relatively-positioned box containing absolutely-positioned responsive content.

CSS使用了我最近介绍的技术的一种变体:一个相对放置的盒子,其中包含绝对放置的响应内容。

figure#burnsbox {
	overflow: hidden;
	position: relative;
	padding-top: 60%;
}
figure#burnsbox img {
	position: absolute; 
	top: 0; left:-5%;
	width: 110%;
	height: 110%;
}

Note that the image is made slightly larger that its container, overlapping by 5% on each side:

Illustration showing an image larger than its container

请注意,将图像制作成比其容器稍大一点,每边重叠5%:

This overlap (shown in orange) is hidden by the overflow: hidden on the container (shown as a black border). The padding-bottom on the figure element preserves the correct height by using a value that matches the aspect ratio of the image.

重叠部分(显示为橙色)被overflow: hidden在容器上(显示为黑色边框)。 通过使用与图像的长宽比匹配的值, figure元素上的padding-bottom保留正确的高度。

设定期望 (Setting Expectations)

To make the effect work we need to do several things:

为了使效果发挥作用,我们需要做几件事:

  • Generate a random vector and scale for the image with JavaScript. These measurements must be within limits that won’t reveal the edges of the image.

    使用JavaScript生成随机向量并缩放图像。 这些测量值必须在不会泄漏图像边缘的范围内。
  • Create a CSS keyframe animation that utilizes these values.

    创建一个利用这些值CSS关键帧动画。
  • Determine if the animation and transforms require vendor prefixes.

    确定动画和变换是否需要供应商前缀。
  • Write the animation into the page’s existing embedded stylesheet.

    将动画写入页面的现有嵌入式样式表。

For this example, let’s assume the following:

对于此示例,我们假设以下内容:

  • The final scale of the image will be 1.1 to 1.4× its original size.

    图像的最终比例为原始尺寸的1.1到1.4倍。
  • The animation will always take 12 seconds to complete

    动画将始终需要12秒才能完成
  • The image can move no less than than 5% of its current width and height in any direction, but no more than 10%.

    图像在任何方向上的移动幅度不得小于其当前宽度和高度的5%,但不得超过10%。

创建随机CSS动画 (Creating A Random CSS Animation)

Under those conditions, generating the initial random numbers is easy:

在这些条件下,生成初始随机数很容易:

function randomizer(min,max) {
	randomresult = Math.random() * (max - min) + min;
	return randomresult;
}
var maxscale = 1.4,
minscale = 1.1,
minMov = 5,
maxMov = 10,
scalar = randomizer(minscale,maxscale).toFixed(2),
moveX = randomizer(minMov,maxMov).toFixed(2);
moveX = Math.random() < 0.5 ? -Math.abs(moveX) : Math.abs(moveX);
var moveY = randomizer(minMov,maxMov).toFixed(2);
moveY = Math.random() < 0.5 ? -Math.abs(moveY) : Math.abs(moveY);

I’ve used toFixed just to avoid the unnecessary complication of trying to scale to a number like 1.269274802; the line of code after the determination of the value of moveX and moveY randomly switches the result between positive and negative.

我用toFixed只是为了避免试图规模一批像1.269274802不必要的并发症; 确定moveXmoveY的值后的代码行会在正负之间随机切换结果。

Next, we need to look for an existing embedded style sheet in the document:

接下来,我们需要在文档中查找现有的嵌入式样式表:

var lastSheet = document.styleSheets[document.styleSheets.length - 1];

Since we don’t want to write out the animation code more than once, we’ll need to determine if the browser requires prefixes. In this case, I’ll use the CSSOM:

由于我们不想多次写出动画代码,因此需要确定浏览器是否需要前缀。 在这种情况下,我将使用CSSOM

var prefix = "";
if (CSSRule.WEBKIT_KEYFRAMES_RULE) {
	prefix = "-webkit-";
}
else if (CSSRule.MOZ_KEYFRAMES_RULE) { 
	prefix = "-moz-"; 
}

Finally, we need to create the animation sequence, which will pan and zoom the image for 80% of the animation time, holding it at both the start and beginning for 10% of the total duration. The animation will be added to the existing stylesheet using insertRule, placing it at the very start of the CSS (i.e. index position 0).

最后,我们需要创建动画序列,该动画序列将在80%的动画时间中平移和缩放图像,并在开始和开始时都将其保持为总持续时间的10%。 动画将使用insertRule添加到现有样式表中,并将其放置在CSS的最开始(即索引位置0 )。

lastSheet.insertRule("@"+prefix+"keyframes zoomzoom {" + 
"10% { " + prefix + "transform: scale(1); } " + 
"90% { " + prefix + "transform: scale(" + scalar +" ) translate(" + moveX +"%," +  moveY + "%); } " +
"100% { " + prefix + "transform: scale(" + scalar + ") translate(" + moveX +"%," +  moveY +"%); } }", 0);

(I’ve added more concatenation than absolutely necessary to break up the lines for increased readability).

(为了增加可读性,我添加了比绝对必要更多的串联来断开行)。

If the script was used in an up-to-date version of Firefox, the randomized result might look something like this:

如果脚本是在最新版本的Firefox中使用的,则随机结果可能类似于以下内容:

keyframes zoomzoom {
	10% {
		transform: scale(1);
		}
	90% {
		transform: scale(1.34) translate(7.21%, 5.89%);
		}
	100% {
		transform: scale(1.34) translate(7.21%, 5.89%);
		}
}

The final step is to control the image with the generated keyframe animation sequence. We could do that with more JavaScript, or just by adding the declarations to the existing styles:

最后一步是使用生成的关键帧动画序列控制图像。 我们可以使用更多JavaScript或仅向现有样式添加声明来做到这一点:

figure#burnsbox img {
	position: absolute;
	top: 0; left:-5%; 
	width: 110%;
	height: 110%;
	animation: zoomzoom 12s linear alternate infinite;
}

An alternative and slightly safer approach is to create the new stylesheet only when the page has completed loading, pushing the appropriate element towards the newly-formed animation. The rest of the code remains unchanged:

另一种更安全的方法是仅在页面完成加载后才创建新样式表,将适当的元素推向新形成的动画。 其余代码保持不变:

window.onload = function(){
	sheet = document.createElement('style');
	document.head.appendChild(sheet);
	var anim = "@"+prefix+"keyframes burnseffect { 
		10% { " + prefix + "transform: scale(1); }
		90% { " + prefix + "transform: scale(" + scalar +" ) translate(" + moveX +"%," +  moveY + "%); }
		100% { " + prefix + "transform: scale(" + scalar + ") translate(" + moveX +"%," +  moveY +"%); } 
		}";
		sheet.appendChild(document.createTextNode(anim));
		document.head.appendChild(sheet);
		var monae = document.querySelector("figure#burnsbox img");
		monae.style.webkitAnimationName = 'burnseffect';
		monae.style.mozAnimationName = 'burnseffect';
		monae.style.animationName = 'burnseffect';
}

Of course you can also control any other aspect of CSS animation with JavaScript, including duration and behaviour, all of which I will cover in future blog articles.

当然,您还可以使用JavaScript控制CSS动画的任何其他方面,包括持续时间和行为,所有这些我将在以后的博客文章中介绍。

The result is what you can see above: a randomized, repeating pan-and-zoom sequence for the photograph of Janelle Monáe in concert, taken by Nastassia Davis and licensed under Creative Commons.

结果就是您在上面看到的结果:一张由Nastassia Davis拍摄并获得Creative Commons许可的,重复播放的JanelleMonáe音乐会照片的随机重复全景显示。

翻译自: https://thenewcode.com/761/Create-A-Random-Ken-Burns-Effect-For-Images-With-CSS-amp-JavaScript

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ken Burns effect效果自动移动来显示完整图片。你可以自定义移动路径,如:从左到有、从上到下、从左下角到右上角、从右上角到左下角等等,并且这些路径可以组合使用项目地址:https://github.com/AlbertGrobas/MovingImageView 效果图:如何使用创建图片<net.grobas.view.MovingImageView             android:id="@ id/image"             android:layout_width="match_parent"             android:layout_height="250dp"             android:clickable="true"             android: 添加移动监听image = (MovingImageView) findViewById(R.id.image); image.getMovingAnimator().addListener(new Animator.AnimatorListener() {             @Override             public void onAnimationStart(Animator animation) {                 Log.i("Sample MovingImageView", "Start");             }             @Override             public void onAnimationEnd(Animator animation) {                 Log.i("Sample MovingImageView", "End");             }             @Override             public void onAnimationCancel(Animator animation) {                 Log.i("Sample MovingImageView", "Cancel");             }             @Override             public void onAnimationRepeat(Animator animation) {                 Log.i("Sample MovingImageView", "Repeat");             }         });3. 停止和重新开始image.getMovingAnimator().pause();//停止 image.getMovingAnimator().resume();//重新开始注意:这俩个功能只能在Android 4.4以上使用。4. 设置自定义移动路径image.getMovingAnimator().addCustomMovement().addDiagonalMoveToDownRight().addHorizontalMoveToLeft().addDiagonalMoveToUpRight()                     .addVerticalMoveToDown().addHorizontalMoveToLeft().addVerticalMoveToUp().start();DiagonalMoveToDownRight:从左上角到右下角HorizontalMoveToLeft:从右到左DiagonalMoveToUpRight:从左下角到右上角清除自定义路径:image.getMovingAnimator().clearCustomMovement();

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值