言:
圣誕節(jié)快到了,是不是要給女朋友或者正在追求的妹子一點小驚喜呢,今天這篇博客就分享下前端代碼如何實現(xiàn)3D立體動態(tài)相冊。趕緊學(xué)會了,來制作屬于我們程序員的浪漫吧!先上效果圖,來引起下你們的興趣。
正文:
一、新建一個index.html的文件,代碼如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>純CSS實現(xiàn)鼠標(biāo)經(jīng)過3D立體動態(tài)展示圖片特效代碼</title> <link type="text/css" href="css/style.css" rel="stylesheet" /> </head> <body> <div class="box"> <ul class="minbox"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <ol class="maxbox"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ol> </div> </body> </html>
二、css樣式的代碼
@charset "utf-8"; *{ margin:0; padding:0; } body{ max-width: 100%; min-width: 100%; height: 100%; background-size: cover; background-repeat: no-repeat; background-attachment: fixed; background-size:100% 100%; position: absolute; margin-left: auto; margin-right: auto; } li{ list-style: none; } .box{ width:200px; height:200px; background-size: cover; background-repeat: no-repeat; background-attachment: fixed; background-size:100% 100%; position: absolute; margin-left: 42%; margin-top: 22%; -webkit-transform-style:preserve-3d; -webkit-transform:rotateX(13deg); -webkit-animation:move 5s linear infinite; } .minbox{ width:100px; height:100px; position: absolute; left:50px; top:30px; -webkit-transform-style:preserve-3d; } .minbox li{ width:100px; height:100px; position: absolute; left:0; top:0; } .minbox li:nth-child(1){ background: url(../img/01.png) no-repeat 0 0; -webkit-transform:translateZ(50px); } .minbox li:nth-child(2){ background: url(../img/02.png) no-repeat 0 0; -webkit-transform:rotateX(180deg) translateZ(50px); } .minbox li:nth-child(3){ background: url(../img/03.png) no-repeat 0 0; -webkit-transform:rotateX(-90deg) translateZ(50px); } .minbox li:nth-child(4){ background: url(../img/04.png) no-repeat 0 0; -webkit-transform:rotateX(90deg) translateZ(50px); } .minbox li:nth-child(5){ background: url(../img/05.png) no-repeat 0 0; -webkit-transform:rotateY(-90deg) translateZ(50px); } .minbox li:nth-child(6){ background: url(../img/06.png) no-repeat 0 0; -webkit-transform:rotateY(90deg) translateZ(50px); } .maxbox li:nth-child(1){ background: url(../img/1.png) no-repeat 0 0; -webkit-transform:translateZ(50px); } .maxbox li:nth-child(2){ background: url(../img/2.png) no-repeat 0 0; -webkit-transform:translateZ(50px); } .maxbox li:nth-child(3){ background: url(../img/3.png) no-repeat 0 0; -webkit-transform:rotateX(-90deg) translateZ(50px); } .maxbox li:nth-child(4){ background: url(../img/4.png) no-repeat 0 0; -webkit-transform:rotateX(90deg) translateZ(50px); } .maxbox li:nth-child(5){ background: url(../img/5.png) no-repeat 0 0; -webkit-transform:rotateY(-90deg) translateZ(50px); } .maxbox li:nth-child(6){ background: url(../img/6.png) no-repeat 0 0; -webkit-transform:rotateY(90deg) translateZ(50px); } .maxbox{ width: 800px; height: 400px; position: absolute; left: 0; top: -20px; -webkit-transform-style: preserve-3d; } .maxbox li{ width: 200px; height: 200px; background: #fff; border:1px solid #ccc; position: absolute; left: 0; top: 0; opacity: 0.2; -webkit-transition:all 1s ease; } .maxbox li:nth-child(1){ -webkit-transform:translateZ(100px); } .maxbox li:nth-child(2){ -webkit-transform:rotateX(180deg) translateZ(100px); } .maxbox li:nth-child(3){ -webkit-transform:rotateX(-90deg) translateZ(100px); } .maxbox li:nth-child(4){ -webkit-transform:rotateX(90deg) translateZ(100px); } .maxbox li:nth-child(5){ -webkit-transform:rotateY(-90deg) translateZ(100px); } .maxbox li:nth-child(6){ -webkit-transform:rotateY(90deg) translateZ(100px); } .box:hover ol li:nth-child(1){ -webkit-transform:translateZ(300px); width: 400px; height: 400px; opacity: 0.8; left: -100px; top: -100px; } .box:hover ol li:nth-child(2){ -webkit-transform:rotateX(180deg) translateZ(300px); width: 400px; height: 400px; opacity: 0.8; left: -100px; top: -100px; } .box:hover ol li:nth-child(3){ -webkit-transform:rotateX(-90deg) translateZ(300px); width: 400px; height: 400px; opacity: 0.8; left: -100px; top: -100px; } .box:hover ol li:nth-child(4){ -webkit-transform:rotateX(90deg) translateZ(300px); width: 400px; height: 400px; opacity: 0.8; left: -100px; top: -100px; } .box:hover ol li:nth-child(5){ -webkit-transform:rotateY(-90deg) translateZ(300px); width: 400px; height: 400px; opacity: 0.8; left: -100px; top: -100px; } .box:hover ol li:nth-child(6){ -webkit-transform:rotateY(90deg) translateZ(300px); width: 400px; height: 400px; opacity: 0.8; left: -100px; top: -100px; } @keyframes move{ 0%{ -webkit-transform: rotateX(13deg) rotateY(0deg); } 100%{ -webkit-transform:rotateX(13deg) rotateY(360deg); } }
三、文件的目錄結(jié)構(gòu),把css文件放到css文件夾里,圖片放到img文件夾里。
四、圖片尺寸不會修改的,可以選擇使用美圖秀秀網(wǎng)頁版很簡單
五、容易出現(xiàn)的問題 ,圖片展示不全或展示的方向不對
1.圖片尺寸需要修改 (解決展示不全的情況)
上圖是我的圖片文件夾里放的圖片 ,首先01-06編號命名的圖片尺寸是100x100px的大小的,1-6編號是400x400px,如果效果想展示最佳,100x100px的圖片是以頭部特寫的照片最好,因為01-06是立體照片內(nèi)部小正方體的照片,1-6編號是外部正方體的照片。
2.圖片的方向需要修改(解決頭朝下的問題)
修改的方向如上圖展示所示,比如第三張頭就應(yīng)該朝下,否則形成的效果圖像會出現(xiàn)頭是倒著的情況。
六、放一下動態(tài)效果圖
總結(jié):
生活雖然總有辛酸,但是我們不應(yīng)該減少去創(chuàng)造生活的樂趣,不斷尋找屬于自己的那份快樂,才應(yīng)該是我們生活的態(tài)度。
我自己是一名從事了多年開發(fā)的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年年初我花了一個月整理了一份最適合2019年學(xué)習(xí)的web前端學(xué)習(xí)干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關(guān)注我的頭條號并在后臺私信我:前端,即可免費獲取。
原文鏈接:https://blog.csdn.net/jdk_wangtaida/article/details/103253883
析QQ空間
登錄QQ空間
爬取第一步,分析站點,首先需要知道如何登錄QQ空間。最初想法是用requests庫配置登錄請求,模擬登錄,但是不久便放棄了這一思路,請看下圖↓
login
根據(jù)登錄按鈕綁定的監(jiān)聽事件可以追蹤到該按鈕的點擊事件如下:
login function
賬號加密是必然的,但這一堆堆的代碼真心不好解析,有耐心的勇士盡情一試!
在排除這種登錄方法后,選擇selenium模擬用戶登錄不失為省時省力的方法,而且我們只是需要通過selenium完成登錄,獲取到Cookies和后面講述的g_tk參數(shù)后,就可以停用了,所以效率并不太低。
分析空間相冊
登錄以后,頁面會跳轉(zhuǎn)至 [https://user.qzone.qq.com/{QQ_NUMBER}](javascript:;), 這時把鼠標(biāo)移到導(dǎo)航欄你會發(fā)現(xiàn),所有的導(dǎo)航欄鏈接都是javascript:; 。沒錯就是這么坑,一切都是暗箱操作。
當(dāng)然這并不難處理,使用調(diào)試工具捕獲點擊后產(chǎn)生的請求,然后過濾出正確的請求包即可。因為網(wǎng)絡(luò)包非常多,那么怎么過濾呢,猜想相冊數(shù)據(jù)的API必然會返回個列表list,嘗試過濾list然后逐個排除,最后定位到請求包。下面是通過fcg_list過濾后的數(shù)據(jù)包,列表信息以jsonp格式返回,稍作處理即可當(dāng)做json格式來讀取(后面有講)。
album list
從Headers和Response可以分別獲取到兩組重要信息:
先看請求包:
# url https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3 # args g_tk: 477819917 callback: shine0_Callback t: 691481346 hostUin: 123456789 uin: 123456789 appid: 4 inCharset: utf-8 outCharset: utf-8 source: qzone plat: qzone format: jsonp notice: 0 filter: 1 handset: 4 pageNumModeSort: 40 pageNumModeClass: 15 needUserInfo: 1 idcNum: 4 callbackFun: shine0 _: 1551788226819
其中hostUin, uin都是QQ號,g_tk是必須的且每次重新登錄都會更新(后面有講如何獲取),其它有些參數(shù)不是必須的,我嘗試后整理出如下請求參數(shù):
query = { 'g_tk': self.g_tk, 'hostUin': self.username, 'uin': self.username, 'appid': 4, 'inCharset': 'utf-8', 'outCharset': 'utf-8', 'source': 'qzone', 'plat': 'qzone', 'format': 'jsonp' }
接下來看jsonp格式的跨域響應(yīng)包:
shine0_Callback({ "code":0, "subcode":0, "message":"", "default":0, "data": { "albumListModeSort" : [ { "allowAccess" : 1, "anonymity" : 0, "bitmap" : "10000000", "classid" : 106, "comment" : 11, "createtime" : 1402661881, "desc" : "", "handset" : 0, "id" : "V13LmPKk0JLNRY", "lastuploadtime" : 1402662103, "modifytime" : 1408271987, "name" : "畢業(yè)季", "order" : 0, "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA", "priv" : 1, "pypriv" : 1, "total" : 4, "viewtype" : 0 },
shine0_Callback是請求包的callbackFun參數(shù)決定的,如果沒這個參數(shù),響應(yīng)包會以_Callback作為默認(rèn)名,當(dāng)然這都不重要。所有相冊信息以json格式存入albumListModeSort中,上面僅截取了一個相冊的信息。
相冊信息中,name代表相冊名稱,id作為唯一標(biāo)識可用于請求該相冊內(nèi)的照片信息,而pre僅僅是一個預(yù)覽縮略圖的鏈接,無關(guān)緊要。
分析單個相冊
與獲取相冊信息類似,進(jìn)入某一相冊,使用cgi_list過濾數(shù)據(jù)包,找到該相冊的照片信息
photo list
同樣的道理,根據(jù)數(shù)據(jù)包可以獲取照片列表信息的請求包和響應(yīng)信息,先看請求:
# url https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo # args g_tk: 477819917 callback: shine0_Callback t: 952444063 mode: 0 idcNum: 4 hostUin: 123456789 topicId: V13LmPKk0JLNRY noTopic: 0 uin: 123456789 pageStart: 0 pageNum: 30 skipCmtCount: 0 singleurl: 1 batchId: notice: 0 appid: 4 inCharset: utf-8 outCharset: utf-8 source: qzone plat: qzone outstyle: json format: jsonp json_esc: 1 question: answer: callbackFun: shine0 _: 1551790719497
其中有幾個關(guān)鍵參數(shù):
為了一次性獲取所有照片,可以將pageStart設(shè)為0,pageNum設(shè)為所有相冊所含照片的最大值。
同樣可以對上面的參數(shù)進(jìn)行簡化,在相冊列表請求參數(shù)的基礎(chǔ)上添加topicId,pageStart和pageNum三個參數(shù)即可。
下面來看返回的照片列表信息:
shine0_Callback({ "code":0, "subcode":0, "message":"", "default":0, "data": { "limit" : 0, "photoList" : [ { "batchId" : "1402662093402000", "browser" : 0, "cameratype" : " ", "cp_flag" : false, "cp_x" : 455, "cp_y" : 388, "desc" : "", "exif" : { "exposureCompensation" : "", "exposureMode" : "", "exposureProgram" : "", "exposureTime" : "", "flash" : "", "fnumber" : "", "focalLength" : "", "iso" : "", "lensModel" : "", "make" : "", "meteringMode" : "", "model" : "", "originalTime" : "" }, "forum" : 0, "frameno" : 0, "height" : 621, "id" : 0, "is_video" : false, "is_weixin_mode" : 0, "ismultiup" : 0, "lloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!", "modifytime" : 1402661792, "name" : "QQ圖片20140612104616", "origin" : 0, "origin_upload" : 0, "origin_url" : "", "owner" : "123456789", "ownername" : "123456789", "photocubage" : 91602, "phototype" : 1, "picmark_flag" : 0, "picrefer" : 1, "platformId" : 0, "platformSubId" : 0, "poiName" : "", "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/a\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!", "raw" : "http:\/\/r.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/r\/dIY29GUbJgAA", "raw_upload" : 1, "rawshoottime" : 0, "shoottime" : 0, "shorturl" : "", "sloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!", "tag" : "", "uploadtime" : "2014-06-13 20:21:33", "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/b\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!", "width" : 932, "yurl" : 0 }, // ... ] "t" : "952444063", "topic" : { "bitmap" : "10000000", "browser" : 0, "classid" : 106, "comment" : 1, "cover_id" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!", "createtime" : 1402661881, "desc" : "", "handset" : 0, "id" : "V13LmPKk0JLNRY", "is_share_album" : 0, "lastuploadtime" : 1402662103, "modifytime" : 1408271987, "name" : "畢業(yè)季", "ownerName" : "707922098", "ownerUin" : "707922098", "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA", "priv" : 1, "pypriv" : 1, "share_album_owner" : 0, "total" : 4, "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/b\/dIY29GUbJgAA", "viewtype" : 0 }, "totalInAlbum" : 4, "totalInPage" : 4 }
返回的照片信息都存于photoList, 上面同樣只截取了一張照片的信息,后面一部分返回的是當(dāng)前相冊的一些基本信息。totalInAlbum, totalInPage存儲了當(dāng)前相冊總共包含的照片數(shù)及本次返回的照片數(shù)。而我們需要下載的圖片鏈接則是url!
OK, 到此,所有請求和響應(yīng)數(shù)據(jù)都分析清楚了,接下來便是coding的時候了。
確定爬取方案
創(chuàng)建qqzone類
class qqzone(object): """QQ空間相冊爬蟲""" def __init__(self, user): self.username = user['username'] self.password = user['password']
模擬登錄
from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.common.exceptions import WebDriverExceptio # ... def _login_and_get_args(self): """登錄QQ,獲取Cookies和g_tk""" opt = webdriver.ChromeOptions() opt.set_headless() driver = webdriver.Chrome(chrome_options=opt) driver.get('https://i.qq.com/') # time.sleep(2) logging.info('User {} login...'.format(self.username)) driver.switch_to.frame('login_frame') driver.find_element_by_id('switcher_plogin').click() driver.find_element_by_id('u').clear() driver.find_element_by_id('u').send_keys(self.username) driver.find_element_by_id('p').clear() driver.find_element_by_id('p').send_keys(self.password) driver.find_element_by_id('login_button').click() time.sleep(1) driver.get('https://user.qzone.qq.com/{}'.format(self.username))
此處需要注意的是:
獲取 Cookies
使用selenium獲取Cookies非常方便
self.cookies = driver.get_cookies()
獲取 g_tk
獲取g_tk最開始可以說是本爬蟲最大的難點,因為從網(wǎng)頁中根本找不到直接寫明的數(shù)值,只有各種函數(shù)調(diào)用。為此我全局搜索,發(fā)現(xiàn)好多地方都有其獲取方式。
g_tk
最后選擇了其中一處,通過selenium執(zhí)行腳本的功能成功獲取到了g_tk!
self.g_tk = driver.execute_script('return QZONE.FP.getACSRFToken()')
到此,selenium的使命就完成了,剩下的將通過requests來完成。
初始化 request.Session
接下來需要逐步生成請求然后獲取數(shù)據(jù)。但是為方便起見,這里使用會話的方式請求數(shù)據(jù),配置好cookie和headers,省的每次請求都設(shè)置一遍。
def _init_session(self): self.session = requests.Session() for cookie in self.cookies: self.session.cookies.set(cookie['name'], cookie['value']) self.session.headers = { 'Referer': 'https://qzs.qq.com/qzone/photo/v7/page/photo.html?init=photo.v7/module/albumList/index&navBar=1', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36' }
請求相冊信息
獲取相冊信息,需要先封裝好請求參數(shù),然后通過session.get爬取數(shù)據(jù),再通過正則匹配以json格式讀取jsonp數(shù)據(jù),最后解析所需的name和id。
def _get_ablum_list(self): """獲取相冊的列表信息""" album_url = '{}{}'.format( 'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3?', self._get_query_for_request()) logging.info('Getting ablum list id...') resp = self.session.get(album_url) data = self._load_callback_data(resp) album_list = {} for item in data['data']['albumListModeSort']: album_list[item['name']] = item['id'] return album_list
其中的參數(shù)組合來自下面的函數(shù)_get_query_for_request函數(shù)。
def _get_query_for_request(self, topicId=None, pageStart=0, pageNum=100): """獲取請求相冊信息或照片信息所需的參數(shù) Args: topicId: 每個相冊對應(yīng)的唯一標(biāo)識符 pageStart: 請求某個相冊的照片列表信息所需的起始頁碼 pageNum: 單次請求某個相冊的照片數(shù)量 Returns: 一個組合好所有請求參數(shù)的字符串 """ query = { 'g_tk': self.g_tk, 'hostUin': self.username, 'uin': self.username, 'appid': 4, 'inCharset': 'utf-8', 'outCharset': 'utf-8', 'source': 'qzone', 'plat': 'qzone', 'format': 'jsonp' } if topicId: query['topicId'] = topicId query['pageStart'] = pageStart query['pageNum'] = pageNum return '&'.join('{}={}'.format(key, val) for key, val in query.items())
其中的jsonp解析函數(shù)如下,主體部分就是一個正則匹配,非常簡單。
def _load_callback_data(self, resp): """以json格式解析返回的jsonp數(shù)據(jù)""" try: resp.encoding = 'utf-8' data = loads(re.search(r'.*?\(({.*}).*?\).*', resp.text, re.S)[1]) return data except ValueError: logging.error('Invalid input')
解析并下載照片
獲取相冊列表后,逐個請求照片列表信息,進(jìn)而逐一下載
def _get_photo(self, album_name, album_id): """獲取單個相冊的照片列表信息,并下載該相冊所有照片""" photo_list_url = '{}{}'.format( 'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo?', self._get_query_for_request(topicId=album_id)) logging.info('Getting photo list for album {}...'.format(album_name)) resp = self.session.get(photo_list_url) data = self._load_callback_data(resp) if data['data']['totalInPage'] == 0: return None file_dir = self.get_path(album_name) for item in data['data']['photoList']: path = '{}/{}.jpg'.format(file_dir, item['name']) logging.info('Downloading {}-{}'.format(album_name, item['name'])) self._download_image(item['url'], path)
下載圖片也是通過request,記得設(shè)置超時時間。
def _download_image(self, url, path): """下載單張照片""" try: resp = self.session.get(url, timeout=15) if resp.status_code == 200: open(path, 'wb').write(resp.content) except requests.exceptions.Timeout: logging.warning('get {} timeout'.format(url)) except requests.exceptions.ConnectionError as e: logging.error(e.__str__) finally: pass
爬取測試
capturing
downloaded photos
寫在最后
助CSS所提供的animation動畫屬性及2D、3D變換屬性,我們可以擺脫對JavaScript的依賴,設(shè)計開發(fā)各類效果優(yōu)秀的前端動態(tài)效果,在之前文章和視頻中我們也介紹了不少基于CSS與JavaScript技術(shù)實現(xiàn)的各類動畫及頁面元素設(shè)計效果。本文主要介紹使用CSS技術(shù)實現(xiàn)精美的3D旋轉(zhuǎn)相冊效果。主要實現(xiàn)效果動畫展示如下:
純CSS技術(shù)實現(xiàn)旋轉(zhuǎn)相冊效果展示
本例開發(fā)主要涉及使用技術(shù)包括animation動畫屬性、keyframes關(guān)鍵幀、transform變形等相關(guān)知識及方法、技術(shù)。部分核心技術(shù)說明如下:
1、CSS自定義屬性(變量)
在使用CSS進(jìn)行樣式定義時,可以使用自定義屬性,即變量。從變量而言考慮的話,會涉及到變量的定義、賦值與使用等。自定義屬性的聲明使用--表示。其賦值與style樣式其他屬性類似可通過:(冒號)進(jìn)行賦值。在使用該自定義屬性時需要用var()函數(shù)對屬性名進(jìn)行包裹。如在自定義變量需要進(jìn)行數(shù)學(xué)運算時需要使用calc()方法。自定義屬性實例如下:
:root{--fontSize:2em;}
p{font-size:var(--fontSize);}
CSS自定義屬性使用實例如上所示,我們定義了一個fontSize變量,在P元素選擇器中使用了該定義的變量,即設(shè)置P段落字體size為2em。
2、3D變換屬性與方法
實現(xiàn)3D效果需要使用3D變換相關(guān)屬性與方法,其主要屬性方法包括transform-origin(旋轉(zhuǎn)原點)、transform-style(旋轉(zhuǎn)類型2D/3D)、perspective(透視點)等屬性,主要方法包括translate位移、scale放縮、rotate旋轉(zhuǎn)與skew扭曲等。使用實例代碼如下:
position: absolute;//定位
transform-origin: center;//中心點
transform-style: preserve-3d;//類型
transform:
translateZ(400px) rotateY(60deg);
//沿Z軸移動400px,沿Y軸旋轉(zhuǎn)60度
3、flex布局
本例需要使用flex布局用于實現(xiàn)將頁面元素在頁面中位置進(jìn)行定位與布局設(shè)置,主要設(shè)置水平與垂直居中效果,實例代碼如下:
display: flex;
justify-content: center;
align-items: center;
在明確以上基本技術(shù)點之后,我們就可以收集素材完整3D旋轉(zhuǎn)相冊的設(shè)計與制作。首先第一步就是素材的采集,本例所需圖片如下所示:
3D旋轉(zhuǎn)相冊圖片素材
在完成素材搜集基礎(chǔ)上就可以使用CSS頁面布局技術(shù)等,實現(xiàn)頁面的布局,通過旋轉(zhuǎn)變換,將10張圖片進(jìn)行不同角度的分布。其中頁面布局代碼如下:
頁面布局代碼
完成頁面元素設(shè)置之后,就要考慮頁面布局問題,本例需要實現(xiàn)旋轉(zhuǎn)因此需要將每一個圖片所對應(yīng)元素進(jìn)行旋轉(zhuǎn)等變換設(shè)置。部分代碼如下:
CSS樣式設(shè)置
核心CSS樣式設(shè)置如上圖所示,其中我們定義了動畫animate,因此需要使用keyframes對其關(guān)鍵幀進(jìn)行定義,關(guān)鍵幀定義如下:
動畫關(guān)鍵幀定義
通過關(guān)鍵幀定義之后,整個gallery層就會繞著y軸進(jìn)行旋轉(zhuǎn)最終實現(xiàn)動態(tài)旋轉(zhuǎn)效果。本例靜態(tài)展示如下圖所示:
3D旋轉(zhuǎn)相冊靜態(tài)效果展示
以上給出了3D旋轉(zhuǎn)相冊設(shè)計及實現(xiàn)過程核心知識點及實現(xiàn)思路過程、核心代碼說明。如需完整代碼請關(guān)注并私信。
本頭條號長期關(guān)注編程資訊分享;編程課程、素材、代碼分享及編程培訓(xùn)。如果您對以上方面有興趣或代碼錯誤、建議與意見,可在評論區(qū)回復(fù)。更多程序設(shè)計相關(guān)教程及實例分享,期待大家關(guān)注與閱讀!
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。