网易新闻采用一镜到底(画中画)的动画形式,呈现了2017年的娱乐圈热门事件。css
网易新闻《娱乐圈画传》H5连接html
对于之内容展现为主的H5,此种形式新颖独特,浏览体验优秀,但对设计师的要求也较高。
此H5值得学习的的技术点以下:html5
经过css3的animation属性将@keyframes动画规则绑定的html元素。形如css3
<div class="people"></div>
.people {
animation: people_ani 1s steps(1,end) infinite;
background: url(images/cover_people.png) no-repeat;
position: absolute;
left: 20px;
bottom: -4px;
width: 500px;
height: 1000px;
}
@keyframes people_ani {
0%{background-position:0 0}
12.5%{background-position:-500px 0}
25%{background-position:-1000px 0}
37.5%{background-position:-1500px 0}
50%{background-position:0 -1000px}
62.5%{background-position:-500px -1000px}
75%{background-position:-1000px -1000px}
87.5%{background-position:-1500px -1000px}
100%{background-position:-2000px -1000px}
}
复制代码
这里须要注意animation的速度曲线属性使用了step()函数,而很是用的线性函数。
step()函数和线性函数的区别在于,前者是关键帧之间的直接跳跃,后者会在线性变化时加入补间动画来使动画更加连贯流畅。
关于step函数内关键字start和end的理解。start表示时间开始已执行一步,忽略第一步,end表示时间结束动画已结束,忽略最后一步。canvas
这里采用了html5中canvas的drawImage方法画图。drawImage的三种函数形式,
drawImage(image, dx, dy)
drawImage(image, dx, dy, dw, dh)
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)bash
sx, sy, sw, sh针对的是图片,dx, dy, dw, dh针对的是canvas画布区域。
sx和sy是image所要绘制的起始位置,
sw和sh是image所要绘制区域(相对image的sx和sy坐标的偏移量)的宽度和高度值。
dx和dy是image在canvas中定位的坐标值
dw和dh是image在canvas中即将绘制区域(相对dx和dy坐标的偏移量)的宽度和高度值;app
H5将屏幕外部图片不断乘以一个系数逐渐缩小至手机屏幕,再将屏幕内图片一样基于系数缩小至外图的关键位置,二者保持重叠,达到一镜到底的效果。ide
H5两个关键绘图方法以下:函数
function drawImgOversize(img, imgNextWidth, imgNextHeight, imgNextAreaWidth, imgNextAreaHeight, imgNextAreaL, imgNextAreaT, radio) {
var sx = imgNextAreaL - (imgNextAreaWidth / radio - imgNextAreaWidth) * (imgNextAreaL / (imgNextWidth - imgNextAreaWidth)),
sy = imgNextAreaT - (imgNextAreaHeight / radio - imgNextAreaHeight) * (imgNextAreaT / (imgNextHeight - imgNextAreaHeight)),
sw = imgNextAreaWidth / radio,
sh = imgNextAreaHeight / radio,
dx = 0,
dy = 0,
dw = 750,
dh = 1206;
var c = document.querySelector('#app')
var ctx = c.getContext('2d');
ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
};
function drawImgMinisize(img, imgCurWidth, imgCurHeight, imgNextWidth, imgNextHeight, imgNextAreaWidthidth, imgNextAreaHeight, imgNextAreaL, imgNextAreaT, radio) {
var sx = 0,
sy = 0,
sw = imgCurWidth,
sh = imgCurHeight,
dx = (imgNextAreaWidth / radio - imgNextAreaWidth) * (imgNextAreaL / (imgNextWidth - imgNextAreaWidth)) * radio * 750 / imgNextAreaWidth,
dy = (imgNextAreaH / radio - imgNextAreaH) * (imgNextAreaT / (imgNextHeight - imgNextAreaH)) * radio * 1206 / imgNextAreaH,
dw = 750 * radio,
dh = 1206 * radio;
var c = document.querySelector('#app')
var ctx = c.getContext('2d');
ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
};
复制代码
以上H5做者的两个方法,研究了许久,并不能清楚地理解其中的计算逻辑,故而本身重写了其中的计算方法。学习
function drawInsideImg(img, imgCurWidth, imgCurHeight, imgNextWidth, imgNextHeight, imgNextAreaW, imgNextAreaH, imgNextAreaL, imgNextAreaT, radio) {
var sx = 0,
sy = 0,
sw = imgCurWidth,
sh = imgCurHeight,
dx = (imgNextAreaL / (imgNextWidth - imgNextAreaW)) * (750 - 750 * radio),
dy = (imgNextAreaT / (imgNextHeight - imgNextAreaH)) * (1206 - 1206 * radio),
dw = 750 * radio,
dh = 1206 * radio;
this.ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)
}
function drawOutsideImg (img, imgNextWidth, imgNextHeight, imgNextAreaWidth, imgNextAreaHeight, imgNextAreaL, imgNextAreaT, radio) {
var sx = (imgNextAreaL / (imgNextWidth - imgNextAreaWidth)) * (imgNextWidth - imgNextAreaWidth / radio),
sy = (imgNextAreaT / (imgNextHeight - imgNextAreaHeight)) * (imgNextHeight - imgNextAreaHeight / radio),
sw = imgNextAreaWidth / radio,
sh = imgNextAreaHeight / radio,
dx = 0,
dy = 0,
dw = 750,
dh = 1206;
this.ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)
}
复制代码
这里有两个恒等的量做为内外图重叠渲染的桥梁,即
(imgNextAreaL / (imgNextWidth - imgNextAreaWidth))
(imgNextAreaT / (imgNextHeight - imgNextAreaHeight))
部份内容参考自https://mp.weixin.qq.com/s/xScwM7Z3I7wXYmZg7y9ajg