網易新聞採用一鏡到底(畫中畫)的動畫形式,呈現了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