我們大概都知道css可以用來作平面旋轉、扭曲、放大縮小、平移,,,并且用起來幾乎都得心應手,
但目前來說,3D效果的“高級”影片似乎更受歡迎一些,而且我們也確實需要,
這不,前兩天筆者就在專案中給“翻轉影片”增加了一個3D效果,看起來賊爽:

這個影片實作所用到的3D盒子模型是現在3D模型中最常用的一個 —— 不過我們先拿其中兩個面分析:
- 首先,要實作這個功能,我們從外往里看:把文字所在部分看作一個盒子的話,前后兩個橫線并不屬于這個盒子才對,那么,很自然就想到了——
::after和::before偽元素; - 其次,兩個文字分別在兩個div上,那么就需要有一個可以附帶
overflow: hidden的盒子 —— 不能加到上面的盒子中,因為after和before不屬于div! - 最后是兩個元素的翻轉效果:我們需要知道的是,為了性能考慮,我們最好是對整個盒子進行翻轉,而不是對兩個文字div附加影片
事實上,transform影片中的屬性表示的含義更多的是“過渡多少”而不是“過渡到哪里”!
那么,這個層級關系就很明了了:
<!--偽元素裝飾盒子-->
<div class="pic_border">
<!--overflow-hidden盒子-->
<div class="pic_box">
<!--transition過渡盒子-->
<div class="pic_item">
<div class="pic_text">music</div>
<div class="pic_back">此時此刻,非我莫屬</div>
</div>
</div>
</div>
按照上面所說,我們很容易為它添加對應的CSS:
.pic_border{
position: relative;
}
.pic_border::before{
content: '';
position: absolute;
top: 50%;
left: 0;
width: 43vw;
height: 1px;
background-color: red;
}
.pic_border::after{
content: '';
position: absolute;
top: 50%;
right: 0;
width: 43vw;
height: 1px;
background-color: red;
}
@media screen and (max-width: 1100px) {
.pic_border::before,.pic_border::after{
width: 20vw;
}
}
.pic_box{
display: inline-block;
height: 70px;
margin-left: calc(50% - 70px);
overflow: hidden;
perspective: 2000px;
cursor: pointer;
user-select: none;
}
.pic_item{
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: all .7s ease;
}
.pic_text,.pic_back{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.pic_text{
transform: rotateX(0deg) translateZ(-21.9px);
}
.pic_back{
transform: rotateX(90deg) translateZ(-15px);
}
.pic_box:hover .pic_item{
transform: rotateX(-90deg);
}
.pic_box:active .pic_item{
transform: rotateX(-90deg);
}
需要注意的是:3D效果是一定要有Z軸參與的! 不然會顯得很“尷尬”

有了簡單的上下翻滾,我們還可以實作“跟隨滑鼠上下左右翻滾”影片,就是所謂的“滑鼠從哪里進入盒子,盒子就往哪個方向翻轉” —— 有兩種實作方式:
- 在最外層盒子中加四個方向的i或span標簽,用來判斷滑鼠從哪里進入,JS控制盒子做對應的rotateX/Y;
- 借助數學庫與“matrix”:
<div class="block" id="block">
<div class="face front"></div>
<div class="face back"></div>
<div class="face up"></div>
<div class="face down"></div>
<div class="face left"></div>
<div class="face right"></div>
</div>
.block {
position: absolute;
transform-style: preserve-3d;
width: 100px;
height: 100px;
transform-origin: 50px 50px;
}
.front {
background: fuchsia;
}
.back {
transform: translate3d(0, 0, 100px) rotateY(180deg);
background: red;
}
.left {
transform-origin: 100% 50% 0px;
transform: rotateY(90deg);
background: aqua;
}
.right {
transform-origin: 0% 50% 0px;
transform: rotateY(-90deg);
background: blueviolet;
}
.up {
transform-origin: 50% 0% 0px;
transform: rotateX(90deg);
background: darkorange;
}
.down {
transform-origin: 50% 100% 0px;
transform: rotateX(-90deg);
background: darkviolet;
}
為了便于觀察,我們為讓魔方格子旋轉起來:
滑鼠滑動分為左、右、上、下滑動,每種滑動對應一種方向的格子旋轉,
- 從右往左:繞 Y 軸旋轉 θ 角
- 從左往右:繞 Y 軸旋轉 -θ 角
- 從上往下:繞 X 軸旋轉 θ 角
- 從下往上:繞 X 軸旋轉 -θ 度
當然旋轉需要有一個參照點,默認盒子中心,我們可以借助庫函式將生成的矩陣轉化為 CSS 中 transform 的 matrix3d 屬性值,
var currentQ = {x:0, y:0, z:0, w:1};
var lastQ = {x:0, y:0, z:0, w:1};
var currentMatrix = matrix.identity();
var l = Math.sqrt(dx * dx + dy * dy);
if(l <= 0) return;
var x = dx / l, y = dy / l;
var axis = {x: x, y: y, z: 0};
var q = matrix.fromAxisAndAngle(axis, l);
currentQ = matrix.multiplyQuaternions(q, lastQ);
currentMatrix = matrix.makeRotationFromQuaternion(currentQ);
通過上述方式我們計算出了當前旋轉矩陣 currentMatrix,接下來,我們使用上面介紹的矩陣轉化成對應 css 的函式,生成對應的 transform 屬性:
// 將矩陣轉化為transform matrix 屬性值,
function matrix2css(m){
var style = 'matrix(';
if(m.length == 16){
style = 'matrix3d('
}
for(let i =0; i< m.length; i++){
style += m[i];
if(i !== m.length - 1){
style += ','
}else{
style +=')'
}
}
return style;
}
var style = matrix2css(currentMatrix);
最后將生成的樣式應用到魔方格子上:
document.querySelector('#block').style.transform = style;
這樣就實作了一個美妙的影片盒子!
幀影片在canvas中的應用
除去CSS-transform和animation在專案中的大放異彩,canvas+CSS的影片方式也得到了很多人的支持!而canvas中實作影片的最好方式不是離屏技術、不是canvas影片庫,而是幀影片!
我們通常通過requestAnimFrame控制一張圖片上的顯示區域的位置從而達到“偽影片”!
比如:

//呼叫方js部分內容
var starPic=new Image()
starPic.src="上面圖片地址"
var lastTime,deltaTime;
var stardog=new starObj()
stardog.init()
lastTime=Date.now()
gameloop()
function gameloop(){
window.requestAnimFrame(gameloop)
var now=Date.now()
deltaTime=now-lastTime
lastTime=now
drawStars()
}
//真正控制影片的js檔案
var satrObj=function(){
this.x;
this.y;
this.picNo;
this.timer;
}
starObj.prototype.init=function(){
this.x=Math.random()*630+100; //630:圖片寬度
this.y=Math.random()*70+150; //70:圖片高度
this.picNo=0;
this.timer=0;
}
starObj.prototype.update=function(){
this.timer+=deltaTime;
if(this.timer>50){
this.picNo+=1;
this.picNo%=7;
this.timer=0;
}
}
starObj.prototype.draw=function(){
ctx.drawImage(starPic,0,0,this.picNo*70,70,this.x,this.y,70,70)
}
function drawStars(){
stardog.update();
stardog.draw();
}

毫無疑問的是:這種方式對UI和前端的結合開始有了要求,
(筆者前段時間研究支付寶春節活動發現:里面采用的也是“前端引入影片檔案”的方式!)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/57777.html
標籤:其他
上一篇:CSS基礎知識(高級技術)
