使用viewBox添加动画
我最近在CodePen上发表了一个DEMO来庆祝新的一年,然后得到了很多积极的反馈,关于我如何使用viewBox
来作为我的场景中的camera的。
所以我决定来写一篇文章来介绍一下这个动画是如何创作的~
Happy New Year !
打开礼物之后,点击小场景来放大
什么是viewBox
?
我不会讲得很详细,网上有很多关于viewBox
的文章都讲得很好。
简单来说,viewBox
是SVG中可见的内容区域。任何超出viewBox
的内容都是不可见的,依赖于你的SVG的尺寸和比例。
你可以在<svg>
标签中定义这样四个值:
<svg viewBox="min-x min-y width height">
更多内容,可以查看Sara Soueidan的理解SVG坐标系和变换:视窗,viewBox和preserveAspectRatio一文。也可以查看w3cplus上SVG板块的文章学习~
好了开始吧!
首先我创建一个简单的HTML文档,包含一个SVG。
Freepik设计的图(我进行了简化)
SVG中定义的viewBox
是实际上显示在我们屏幕上的尺寸。也就是说我们的SVG的元素都是的viewBox
中显示的。
试着调整窗口的大小(或编辑面板的大小),你会看到SVG是如何缩放的~
更新viewBox
在这个DEMO中,我绘制了一个红色的半透明矩形来展示我们将要给viewBox
应用的新值。将鼠标移动到矩形上,来更新viewBox
,看看SVG如何重新绘制。
很神奇,对吧?
我们的SVG没有变,所有在viewBox
外面的元素依旧在页面上,但是依旧看不到。
因为SVG的尺寸和比例,你可能只看到场景水平轴上的一些部分(至少在这支嵌入的pen中)
如果你不理解我是如何给viewBox
应用新值的,点击javascript面板
通过viewBox
添加动画
现在我们知道要如何更新viewBox
的值了,但是还完全算不上动画。
遗憾的是我们目前还不能通过CSS来给viewBox
添加动画,我们需要一些javascript。
我经常使用[TweenMax](//greensock.com/来创建动画,因为这是我目前自己觉得最好用的这方面的javascript插件。
这是一个简单的动画实例,viewBox
从原始尺寸变为矩形。
我们来看看如何在TweenMax中设置动画:
TweenMax.to(
svg, //我们的SVG
2, //动画的持续时间
{
attr:{//在新的frame中更新属性的值
viewBox: "220 110 370 350" //指定动画的最终值
},
repeat: -1, //不断重复我们的动画
yoyo: true, //动画会像悠悠球一样来回播放
}
);
你可以看到,让viewBox
从一帧到另一帧的补间其实非常容易。只需要这几行代码,你就可以创建很多很多的可能性。
使用viewBox
作为camera
我们来看看我的那个Happy New Year pen,这是我如何使用viewBox
来作为camera来对场景进行缩放。
我在SVG创建了可点击的区域,但是只有在hover的时候可见。我们使用它来触发点击小场景的事件。
//Select all my areas
var overlays = svg.querySelectorAll("#overlays > g");
//在每个区域添加事件监听
for (var i = 0; i < overlays.length; i++) {
overlays[i].addEventListener("click", zoomViewBox);
}
//这个变量用来检查viewBox是否已经放大了
var zoom = false;
//我创建了包含每个区域的值的对象
//每个key都对应一个区域的id
var viewBoxes = {
"overHouses": {
x: 43,
y: 290,
width: 130,
height: 67
},
"overSnowmen": {
x: 250,
[...]
};
当用户点击了任何区域,我们可以调用zoomViewBox()
函数:
function zoomViewBox(e) {
//如果用户在viewBox已经放大的时候点击区域
//或者,最初的动画还没有结束,先暂停函数的调用
if (zoom || !animationOn) {
return;
}
//To prevent other unwanted events
e.stopPropagation();
//Each area has a unique ID which
var id = this.getAttribute("id");
//这块代码和前面的实例是一样的,但是现在值不是静态的
//我把它们从viewBox对象拿出来,赋一块包含id的可点击区域
TweenMax.to(svg, 2, {
attr:{
viewBox: viewBoxes[id].x + " " + viewBoxes[id].y + " " + viewBoxes[id].width + " " + viewBoxes[id].height
},
ease: Power3.easeOut
});
//现在SVG已经放大了
zoom = true;
}
允许用户放大,我检查了SVG上的每一次点击,如果SVG是放大状态的,那我们就调用unZoom()
函数。
//监听SVG上的每一次点击
svg.addEventListener("click", unZoom);
function unZoom() {
zoom = false;//将值设置为false
//这还是同一个动画,只是现在不是初始值
TweenMax.to(svg, 2, {attr:{viewBox:"0 0 1600 900"}, ease: Power3.easeOut});
}
以上是整个JavaScript的一个大概。如果你对这块感兴趣的话,我鼓励你去看看完整的代码。
案例
这里的这个实例,默认的viewBox
后面隐藏了三个场景,在用户做出选择时候是可见的。
(点击RERUN来重置pen)
另一个来自David Bachmann Johannesson的实例你可能已经在Codepen上看过了。
感谢
希望这篇文章在viewBox
这块对你有一点帮助。
有任何问题欢迎戳我的Twitter或codepen!
本文根据@Louis Hoebregts的《Animating the viewBox》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处://codepen.io/Mamboleoo/post/animating-the-viewbox。