揭秘腾讯burberry活动页面中的特效

4月24日,Burberry亚太地区规模最大的旗舰店在上海开幕。Burberry突破性地运用了诸多创新的数字营销模式,借助与腾讯的合作,为更多未能到场的用户创造了一个“平行的体验”,也正式开启了Burberry的创新数字营销之旅。

腾讯的营销页面: 

其中多次用到了类似于云雾褪去的效果,如下图。

我对这种神奇的特效产生的极大的兴趣,于是通过chrome的审查元素里面Resources找到下面这张图片(由于图片是白色的png,为了让大家看清楚我将背景调成了黑色)。

于是效果的实现方式就显而易见了,是利用css3的-webkit-mask来实现的。

####Step1.为背景加上蒙板

<body>
    <div class="stage">
        <div class="sprite1"></div>
    </div>
</body>
.stage{
    width: 320px;
    height: 480px;
    position: absolute;
    left: 50%;
    top: 50%;
    margin-top:-240px;
    margin-left:-160px;
    background: url(‘./img/bg.jpg‘) no-repeat;
    background-size: auto 100%;
}
.stage .sprite1{
    width: 100%;
    height: 100%;
    background: url(‘./img/bg2.jpg‘) no-repeat;
    background-size: auto 100%;
    -webkit-mask:url(‘./img/Touch1.png‘) no-repeat;
    -webkit-mask-size: 100% 100%;
}

这里为了在桌面浏览器中观看方便,将画面大小调整成了320*480并居中。在sprite1中添加background的同时也增加了蒙板。

-webkit-mask:url(‘./img/Touch1.png‘) no-repeat;
-webkit-mask-size: 100% 100%;

我们这里将蒙板的大小设置为100%来观察蒙板的效果。图中画圈圈的地方就是sprite1透过蒙板展示出来的部分。

我们看到这个蒙板Touch1.png应该是一个序列帧组成的图片,我们只需要将其一帧帧的显示出来就可以实现动画了。
点击查看历史代码

Step2.序列帧动画

.stage .sprite1{
    ......
    -webkit-mask-size: 400% 300%;
    -webkit-mask-position: 0% 0%;
}

Touch1.png是序列帧的整合图片,其中一排有4帧一共有3排,所以我们将-webkit-mask-size设为400% 300%。将-webkit-mask-postion设为0% 0%表示从第一帧开始。做动画时只需要依次修改-webkit-mask-position的x与y值,每次将x增加25%(100/每排的帧数4)直到75%,y增加33.33%(100/每牌的帧数3)直到66.66%。我们需要将每一帧的position状态在不同的时间赋给sprite1,这只需要用setTimeout就可以了。

我们新建一个spriteClip类,并传入(dom,w,h,time)四个参数,其中dom用来定位sprite1这个元素,w为一排有几帧,h为一共有几行,time为每一帧之间的间隔。

function spriteClip(dom,w,h,time){
    if(dom){
        this.dom = dom;
        this.w = w ||0;
        this.h = h ||0;
        this.time = time || 0;
    }else{
        return false;
    }
}

新建run方法。遍历w与h算出时间与位置,用setTimeout设置好延时执行

spriteClip.prototype.run = function(){
    for(var w=0;w<this.w;w++){
        for(var h =0;h<this.h;h++){
            //这里使用闭包以免w,h值随循环改变。
            (function(w,h,self){
                //计算时间
                var time = (h*self.time*self.w+w*self.time);
                setTimeout(function(){
                    //计算位置
                    self.dom.style.webkitMaskPosition = (100/(self.w-1))*w+‘% ‘+(100/(self.h-1))*h+‘%‘;
                },time);
            })(w,h,this);
        }
    }
}

新建并运行spriteClip。

var sprite1 = document.querySelector(‘.sprite1‘);
var sp1 = new spriteClip(sprite1,4,3,50);
sp1.run();

运行代码:

点击查看历史代码

Step3.添加动画控制

有了sprite1后,再添加3个sprite,将所有的动画按照顺序播放来形成完整的转场。为了实现按照顺序的播放,我们需要为动画添加播放控制。即在播放动画完成后给dom触发一个finish事件,dom接到完成事件后执行下一个动画。同时添加showhide用来控制动画的显示/隐藏。

function spriteClip(dom,w,h,time){
    if(dom){
        ......
        //记录dom初始的display状态
        this.display = this.dom.style.display;
        //记录动画是否播放过
        this.played = false;
    }else{
        return false;
    }
}
spriteClip.prototype.run = function(){
    //如果动画已经播放过则不做任何动画
    if(this.played)
        return false;
    //标记为已播放完成
    this.played = true;
    //让dom显示
    this.show();
    for(var w=0;w<this.w;w++){
        for(var h =0;h<this.h;h++){
            (function(w,h,self){
                var time = (h*self.time*self.w+w*self.time);
                setTimeout(function(){
                    ......
                    if(w >= self.w-1 && h>=self.h-1){
                        //动画结束
                        var event = document.createEvent(‘HTMLEvents‘);
                        event.initEvent(‘finish‘, true, true);
                        event.eventType = ‘message‘;
                        event.content =  ‘finish‘;
                        //触发finish事件
                        self.dom.dispatchEvent(event);
                    }
                },time);
            })(w,h,this);
        }
    }
}
//隐藏dom
spriteClip.prototype.hide = function(){
    this.dom.style.display = ‘none‘;
}
//显示dom
spriteClip.prototype.show = function(){
    this.dom.style.display = this.display;
}
//接收finish时间并用callback函数处理
spriteClip.prototype.finish = function(callback){
    this.dom.addEventListener(‘finish‘,callback);
}
var sprite1 = document.querySelector(‘.sprite1‘);
var sp1 = new spriteClip(sprite1,4,3,50);
//在做动画之前让sprite隐藏
sp1.hide();
document.addEventListener(‘touchend‘,function(){
    //手指抬起后运行动画
    sp1.run();
});
document.addEventListener(‘click‘,function(){
    //点击后运行动画
    sp1.run();
});
sp1.finish(function(){
    //动画完成
    console.log(‘finish‘);
});

下面添加剩下的3个sprite。

......
.stage .sprite2{
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0px;
    top: 0px;
    background: url(‘./img/bg2.jpg‘) no-repeat;
    background-size: auto 100%;
    -webkit-mask:url(‘./img/Touch2.png‘) no-repeat;
    -webkit-mask-size: 400% 300%;
    -webkit-mask-position: 0% 0%;
}
.stage .sprite3{
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0px;
    top: 0px;
    background: url(‘./img/bg2.jpg‘) no-repeat;
    background-size: auto 100%;
    -webkit-mask:url(‘./img/Touch3.png‘) no-repeat;
    -webkit-mask-size: 400% 300%;
    -webkit-mask-position: 0% 0%;
}
.stage .sprite4{
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0px;
    top: 0px;
    background: url(‘./img/bg2.jpg‘) no-repeat;
    background-size: auto 100%;
    -webkit-mask:url(‘./img/Touch4.png‘) no-repeat;
    /* Touch4是4*5 */
    -webkit-mask-size: 400% 500%;
    -webkit-mask-position: 0% 0%;
}
......
<div class="stage">
    <div class="sprite1"></div>
    <div class="sprite2"></div>
    <div class="sprite3"></div>
    <div class="sprite4"></div>
</div>
.....
//新建4个sprite
var sprite1 = document.querySelector(‘.sprite1‘);
var sprite2 = document.querySelector(‘.sprite2‘);
var sprite3 = document.querySelector(‘.sprite3‘);
var sprite4 = document.querySelector(‘.sprite4‘);
var sp1 = new spriteClip(sprite1,4,3,80);
var sp2 = new spriteClip(sprite2,4,3,80);
var sp3 = new spriteClip(sprite3,4,3,80);
var sp4 = new spriteClip(sprite4,4,5,80);
sp1.hide();
sp2.hide();
sp3.hide();
sp4.hide();
document.addEventListener(‘touchend‘,function(){
    sp1.run();
});
document.addEventListener(‘click‘,function(){
    sp1.run();
});
sp1.finish(function(){
    //sprite1结束后运行sprite2
    sp2.run();
});
sp2.finish(function(){
    //sprite2结束后运行sprite3
    sp3.run();
});
sp3.finish(function(){
    //sprite3结束后运行sprite4
    sp4.run();
})
......

运行代码:

查看所有代码请去Github

如有问题或者建议请微博@UED天机。我会及时回复,也可以提供其他特效一起讨论其实现方法。

揭秘腾讯burberry活动页面中的特效,布布扣,bubuko.com

时间: 2024-08-06 11:55:30

揭秘腾讯burberry活动页面中的特效的相关文章

活动页面优惠券样式

上周五在大前端中看到一种写优惠券的样式.在本地测试了一把,个人觉得还不错.现在很多活动页面中都会有优惠券,以后可以在页面中试一下...... HTML代码: <div class="stamp stamp01"> <div class="par"> <p>XXXXXX折扣店</p> <sub class="sign">¥</sub> <span>50.00<

揭秘腾讯大数据冰山一角

一.人群画像 1.什么是人群画像大数据? 人群画像通过收集用户的行为特征.年龄特征.用户场景.地域特征.目标动机等一系列海量真实数据,建立用户模型,抽出典型目标用户针对性分析. 2.人群画像大数据有什么作用? 现有的人群画像大多只是用来进行营销活动,通过已有建立人群画像,发掘潜在用户资源,然后对这类特定群体进行针对性营销.除此之外,在人群画像基础上进行产品经营状况分析也是常用的一种手段.但是,人群画像在工程实践中似乎一直没有得到太好的应用. 二.腾讯大数据--天御系统 1.什么是天御系统? 天御

客户端发现_观影团活动页面开发与客户端新版跳转测试页面开发项目总结

   这一周过的是我理想的实习状态,手头有项目则忙项目,没项目则提高基础技能.那么下面来看看这周做的活动页面效果吧. 项目介绍 (一).观影团活动页面的开发 本项目页面的开发基本都是用之前用过的技术,不同之处在于乐帝之前的开发处于懵懂状态,现在回头看还是有些许的提高,对页面每一行代码都知道来龙去脉,弹出窗.对齐.居中布局都从本周阅读<前端开发修炼之道>有了更深层次的认识.css对齐与居中布局都不是单独属性完成的,而是有关联及触发的,而之前写页面不理解的恰恰是属性间的触发关系. 这里拿弹出窗的构

揭秘腾讯阿里百度的薪酬待遇 简直就是人生目标

揭秘腾讯阿里百度的薪酬待遇 简直就是人生目标 2014-12-28 12:40:39 来源:IT之家作者:IT之家 三大互联网巨头公司,百度腾讯跟阿里如何划分级别?薪资待遇又有多少?除非身居其位,否则很难探知,但是等你到那个位置知道了,却又不能说,至少不能在公开场合谈论.接下来就为大家揭秘,百度.阿里与腾讯内部的级别划分跟薪资待遇.这是一个群众喜闻乐见却又讳莫如深的话题. 各个公司头衔名字都不一样,级别的数目也不一样;有些扁平,有些很多level慢慢升;有些薪水范围严格跟级别挂钩,有些薪水跟级别

HTML页面中常见的一些小方法

在<Head>标签中加 <meta http-equiv="pragma " content="no-cache"> <meta http-equiv="Cache-Control " content="no-cache,must-revalidate"> <meta http-equiv="expires " content="Wed,26 Feb 19

cefsharp wpf wpf加载svg 在同一个页面中打开链接

安装 PM> Install-Package CefSharp.Wpf 解决方案->属性->配置属性->活动解决方案平台-新建-x64 在需要使用的窗体上引用xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf" 重新生成解决方案 引用 <cefSharp:ChromiumWebBrowser Name="browser" Grid.Row="0&qu

使用jQuery的data方法来为页面中的某个元素存储数据,(获取焦点,清除默认值)

使用data方法可以避免在DOM中存储数据,有些前端开发er喜欢使用HTML的属性来存储数据: 使用”alt”属性来作为参数名存储数据其实对于HTML来说是不符合语义的. 我们可以使用jQuery的data方法来为页面中的某个元素存储数据: html部分: 1 <form id="testform"> 2 <input type="text" class="clear" value="Always cleared&qu

表单提交时如何将错误信息传递到页面中,并且保存原来提交数据

曾经何时,你还有我或许都在困惑,如何方便的将验证不通过的表单信息再返回到前台页面,例如我注册一个账号,辛辛苦苦填写了N多项,一个格式验证没有通过,一切都需要充填,虽然Ajax可以解决这个问题,但是我们总不能把所有表单提交都弄成ajax,更何况有若干人就是没事把javascript给禁止了.哎哎,好了解决方案来了,下面以用户登录为例,说说我的解决方案. 服务器端用nodejs实现: login.html 简单的提交表单 <form action="" id="loginF

在Exchange 2013 OWA登录页面中修改密码

透过OWA登录界面改密码对于使用Exchange的用户来说是一个很有有用的功能. 因为如果用户不在公司域环境中,当密码已经到期登录不了OWA,就没有办法通过OWA中的[选项]来改密码,当开启这项功能后,管理员和用户都可以很方便的处理密码到期的case. 早在Exchange2010的时候,我们需要通过修改CAS服务器的注册表项来实现这个功能.现在的Exchange2013已经内置了该功能,使用前只需要确认该功能属性的状态就可以了. 在最新的Exchange2013 SP1和CU5版本中,此功能在