js實(shí)現(xiàn)仿微博滾動(dòng)顯示信息的效果
相信大家空閑的時(shí)候都會(huì)上上微博,推特等社交網(wǎng)站,每次我登陸微博時(shí),我都會(huì)留意一下它有什么變化,小的有一些布局的變化,大的有API接口的改變等。
在首頁(yè)登陸微博時(shí),我們可以看到一欄“大家正在說(shuō)”,它滾動(dòng)顯示著當(dāng)前每個(gè)人發(fā)送的微博;剛看到這個(gè)效果覺(jué)得挺有趣的,所以我們將在接下來(lái)的文中介紹實(shí)現(xiàn)滾動(dòng)顯示微博信息的效果。
我們細(xì)細(xì)觀察了微博的“大家正在說(shuō)”,它是通過(guò)由上往下滾動(dòng)來(lái)實(shí)現(xiàn)不斷顯示微博的,而且每一天新微博都是通過(guò)淡入效果顯示的。
圖1 微博“大家正在說(shuō)”
1、定義微博插件
接下來(lái),我們將定義一個(gè)插件用來(lái)獲取某話題下的微博,這里我們將使用jQuery的擴(kuò)建功能來(lái)定于一個(gè)微博的jQuery插件
由于jQuery提供了一種機(jī)制:讓用戶給核心模塊增加自定義的方法和額外的功能;通過(guò)這種機(jī)制,jQuery允許我們創(chuàng)建自定義的插件封裝常用的方法,從而提高我們的開(kāi)發(fā)效率。
首先,我們通過(guò)定義自執(zhí)行的函數(shù)(IIFE),然后把jQuery對(duì)象作為參數(shù)傳遞給該自執(zhí)行函數(shù),通過(guò)建立“$”和jQuery的對(duì)應(yīng)關(guān)系,這樣“$”就不會(huì)在其執(zhí)行范圍內(nèi)被其他庫(kù)覆蓋了。
// Defines a jquery plugin. ; (function($) { $.fn.weiboSearch = function() { // your plugin logic }; })(jQuery);
上面,我們定義一個(gè)自執(zhí)行函數(shù)(IIFE),并且在它里面定義了一個(gè)擴(kuò)展方法weiboSearch()。
由于,微博API 2.0提供了一個(gè)接口search/topics來(lái)搜索某一話題下的微博,如果請(qǐng)求成功則返回JSON格式的數(shù)據(jù)。
圖2微博搜索接口參數(shù)
通過(guò)上圖,我們知道微博搜索接口需要提供應(yīng)用的AppKey(非OAuth授權(quán)方式)和話題關(guān)鍵字(q)。
接下來(lái),我們定義了一個(gè)字面量對(duì)象defaults,它包含微博接口的url、應(yīng)用的AppKey、話題關(guān)鍵字(q)和單頁(yè)返回的記錄條數(shù)(count)等屬性,具體定義如下:
// Defines weibo defaults type. $.fn.weiboSearch.defaults = { url: 'https://api.weibo.com/2/search/topics.json?q=', appKey: '5786724301', numWeibo: 15, term: '' };
2、發(fā)送跨源請(qǐng)求
我們可以通過(guò)發(fā)送ajax請(qǐng)求方式來(lái)調(diào)用微博搜索接口,如果請(qǐng)求成功服務(wù)器會(huì)給程序返回JSON格式數(shù)據(jù),那么我們需要把返回的數(shù)據(jù)呈現(xiàn)到頁(yè)面中。
$.getJSONP = function(s) { // Due to cross origin request, so we to use jsonp format. s.dataType = "jsonp"; $.ajax(s); // figure out what the callback fn is var $script = $(document.getElementsByTagName('head')[0].firstChild); var url = $script.attr('src') || ''; // Gets callback function var cb = (url.match(/callback=(\w+)/) || [])[1]; if (!cb) return; // bail var t = 0, cbFn = window[cb]; $script[0].onerror = function(e) { $script.remove(); handleError(s, {}, "error", e); clearTimeout(t); }; if (!s.timeout) return; window[cb] = function(json) { clearTimeout(t); cbFn(json); cbFn = null; }; // Gets time out function flag. t = setTimeout(function() { $script.remove(); handleError(s, {}, "timeout"); if (cbFn) window[cb] = function() { }; }, s.timeout); /** * Fix issue: "jQuery.handleError is not a function" */ function handleError(s, xhr, msg, e) { s.error && s.error.call(s.context, xhr, msg, e); s.global && $.event.trigger("ajaxError", [xhr, s, e || msg]); s.complete && s.complete.call(s.context, xhr, e || msg); } };
上面,我們定義了方法getJSONP(),它通過(guò)發(fā)送ajax請(qǐng)求的方式調(diào)用微博API,這時(shí)我們需要跨源請(qǐng)求數(shù)據(jù),我們可以通過(guò)JSONP格式獲取跨源數(shù)據(jù),由于它允許在服務(wù)器端集成Script tags返回至客戶端,通過(guò)Javascript callback的形式實(shí)現(xiàn)跨域訪問(wèn)。
接下來(lái),我們?cè)诜椒?.fn.weiboSearch()中定義私有方法grabWeibos(),它負(fù)責(zé)調(diào)用getJSONP()方法并且獲取返回的JSON數(shù)據(jù)顯示到頁(yè)面中。
/** * Uses ajax request to grab weibos. */ function grabWeibos() { var url = opts.url; grabFlag = false; grabbing = true; $.getJSONP({ url: url, timeout: 30000, data: { source: opts.appKey, q: opts.term, count: opts.numWeibo }, error: function(xhr, status, e) { }, complete: function() { }, success: function(json) { if (json.error) { // Can't get results displays error. return; } // iterates weibo results $.each(json.data.statuses, function(i) { // Adds data to page. }) } }); }
上面,我們定義了grabWeibos(),它調(diào)用了getJSONP()方法并且在請(qǐng)求成功后把數(shù)據(jù)顯示到頁(yè)面中。
3、JSON數(shù)據(jù)處理
現(xiàn)在,我們基本實(shí)現(xiàn)了jquery.weibo.search.js插件,用來(lái)搜索某一話題下的微博的功能,由于時(shí)間的關(guān)系我們已經(jīng)把界面設(shè)計(jì)好了,具體的HTML代碼如下:
<!-- From design--> <!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <title></title> <link rel="stylesheet" type="text/css" href="css/weibo.serach.style.css"> </head> <body> <table> <tbody> <tr> <td> <div id="weibo1" class="weibo"> </div> </td> <td> <div id="weibo2" class="weibo"> </div> </td> </tr> </tbody> </table> </body> </html>
接下來(lái),我們?cè)陧?yè)面代碼中引用jQuery庫(kù)和自定義微博話題搜索插件jquery.weibo.search.js,具體代碼如下:
<!-- Adds Javascript reference --> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript" src="js/jquery.weibo.search.js"></script>
上面,我們直接引用Google提供的jQuery庫(kù),當(dāng)然我們也把jQuery庫(kù)下載到本地,然后引入到項(xiàng)目中,接下來(lái)我們?cè)趆ead元素中添加調(diào)用微博話題搜索插件的代碼,具體代碼如下:
<!-- When document ready invokes charCount function--> <script type="text/javascript"> // Invokes webioSearch function. $(document).ready(function () { $("#weibo1").weiboSearch({ term:'情人節(jié)', direction:'down' }); $("#weibo2").weiboSearch({ term:'元宵節(jié)', direction:'up' }); }); </script>
上面,我們?cè)陧?yè)面中調(diào)用了weiboSearch()的默認(rèn)方法,并且搜索“情人節(jié)”話題下的微博。接下來(lái),我們打開(kāi)Chrome中Network選項(xiàng),查看search/topics中的請(qǐng)求包含了source、count、q和callback(回調(diào)函數(shù))參數(shù)。
圖3 Ajax請(qǐng)求
由于Chrome中的JSON數(shù)據(jù)沒(méi)有換行不便于查看,所以我們?cè)贔irefox中查看返回的JSON格式的數(shù)據(jù)。
圖4微博JSON數(shù)據(jù)
上面的JSON數(shù)據(jù)不便于查看,這里我們使用JSON viewer格式化微博數(shù)據(jù),格式化后的數(shù)據(jù)如下:
圖5格式化的JSON數(shù)據(jù)
通過(guò)上圖,我們發(fā)現(xiàn)微博數(shù)據(jù)包含在try/catch語(yǔ)句中,如果請(qǐng)求成功catch中將為空,反之,返回相應(yīng)的錯(cuò)誤提示信息。
接下來(lái),我們把微博數(shù)據(jù)提取出來(lái),然后去掉try/catch我們?cè)贘SON viewer中查看微博數(shù)據(jù)的結(jié)構(gòu)。
圖6 微博JSON數(shù)據(jù)
通過(guò)上圖,我們知道返回?cái)?shù)據(jù)是一個(gè)JSON數(shù)組,它的大小是根據(jù)我們的請(qǐng)求參數(shù)count決定的,而且微博規(guī)定每個(gè)請(qǐng)求最多返回200條微博。
接下來(lái),我們需要把數(shù)據(jù)顯示到頁(yè)面中,現(xiàn)在讓我們實(shí)現(xiàn)success方法吧!具體代碼如下:
// Gets response data from weibo api. success: function(json) { if (json.data.error) { // Can't get data displays error. failEye(json.data.error); return; } // Emptys contain with fade out effect. $cont.fadeOut('fast', function() { $cont.empty(); // iterates weibo results $.each(json.data.statuses, function(i) { if (!opts.filter.call(opts, this) || this.truncated) return; // skip this weibo, some weibos may be deleted. var $img, $text, w, tweet = opts.formatter(this, opts), $tweet = $(tweet); // Weibo data. $tweet.css(opts.css['tweet']); $img = $tweet.find('.weiboSearchProfileImg').css(opts.css['img']); $tweet.find('.weiboSearchUser').css(opts.css['user']); $tweet.find('.weiboSearchTime').css(opts.css['time']); $tweet.find('a').css(opts.css['a']); $tweet.appendTo($cont); $text = $tweet.find('.weiboSearchText').css(opts.css['text']); if (opts.avatar) { w = $img.outerWidth() + parseInt($tweet.css('paddingLeft')); $text.css('paddingLeft', w); } }) // Loads weibos with fade in effect. $cont.fadeIn('fast'); // Invokes weibo api again. if (json.data.statuses.length < 2) { if (opts.refreshSeconds) setTimeout(gradWeibos, opts.refreshSeconds * 1000); return; } }); }
在success()方法中,我們使用了jQuery的fadeIn()和fadeOut()函數(shù)實(shí)現(xiàn)微博加載時(shí)淡入和清除時(shí)淡出的效果。
接著,我們使用$.each()方法遍歷JSON數(shù)組中的每條微博信息,然后把它們添加到頁(yè)面DOM中。
圖7 微博信息
我們通過(guò)跨源請(qǐng)求調(diào)用微博search/topics接口,然后把服務(wù)器返回的JSON數(shù)據(jù)顯示到頁(yè)面中。
5、微博相對(duì)時(shí)間
現(xiàn)在,基本實(shí)現(xiàn)了jquery.weibo.search.js插件了,但我們發(fā)現(xiàn)每條微博顯示時(shí)間好像不太正常,而且還沒(méi)有實(shí)現(xiàn)滾動(dòng)(animate)和淡入(fadeIn)效果。
由于微博是使用相對(duì)時(shí)間來(lái)表示微博插件時(shí)間,當(dāng)然我們也可以顯示具體時(shí)間,接下來(lái),讓我們把微博創(chuàng)建時(shí)間(created_at)轉(zhuǎn)化為相對(duì)時(shí)間的形式,由于微博的時(shí)間格式為:“Thu Feb 14 20:33:30 +0800 2013”,所以我們定義了方法relativeTime()把微博時(shí)間轉(zhuǎn)換為相對(duì)時(shí)間。
function relativeTime(dateString) { var values = dateString.split(" "); dateString = values[1] + " " + values[2] + ", " + values[5] + " " + values[3]; var parsed_date = Date.parse(dateString); var relative_to = (arguments.length > 1) ? arguments[1] : new Date(); var delta = parseInt((relative_to.getTime() - parsed_date) / 1000); delta = delta + (relative_to.getTimezoneOffset() * 60); if (delta < 60) { return 'just now'; } else if (delta < 120) { return 'a minute ago'; } else if (delta < (60 * 60)) { return (parseInt(delta / 60)).toString() + ' minutes ago'; } else if (delta < (120 * 60)) { return 'about an hour ago'; } else if (delta < (24 * 60 * 60)) { return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago'; } else if (delta < (48 * 60 * 60)) { return '1 day ago'; } else { return (parseInt(delta / 86400)).toString() + ' days ago'; } }
上面,我們定義了方法relativeTime(),首先它通過(guò)拼接方式轉(zhuǎn)換時(shí)間格式為“Feb 14, 2013 20:33:30”,然后把dateString轉(zhuǎn)換為Date,接著獲取當(dāng)前時(shí)間減去微博時(shí)間(created_at)計(jì)算出相對(duì)時(shí)間(delta)。
圖8 relativeTime計(jì)算相對(duì)時(shí)間
5、微博動(dòng)態(tài)效果
上面,我們通過(guò)方法relativeTime()把微博的時(shí)間轉(zhuǎn)換為相對(duì)時(shí)間,接下來(lái),我們需要實(shí)現(xiàn)微博的滾動(dòng)(animate)和淡入(fadeIn)效果。
在新浪微博大廳里,我們可以看到“大家正在說(shuō)”中每條微博由上往下地滾動(dòng)著,其實(shí)要實(shí)現(xiàn)該滾動(dòng)效果我們可以使用jQuery的animate()方法,具體實(shí)現(xiàn)如下:
/** * Weibos rolling from top to bottom */ function weiboIn() { if (paused || grabbing) { setTimeout(weiboIn, 500); return; } // Gets last element. var h, $el = $cont.children(':last'), $elFirst = $cont.children(':first'); // Gets last weibo item height. h = $el.outerHeight(); // Animate: increases the first weibo item margin top to 'h'. // Then decreases the first weibo item margin top to '0'. $elFirst.animate({ marginTop: h }, opts.animInSpeed, function() { $elFirst.css({ marginTop: 0, opacity: 1 }); /*@cc_on try { el.style.removeAttribute('filter'); } // ie cleartype fix catch (smother) { } @*/ // append the last weibo item first. $el.css(opts.css['tweet']).hide().prependTo($cont); // Fade in display new item. $el.fadeIn(opts.animInSpeed); // Loop setTimeout(grabFlag ? grabWeibos : weiboIn, opts.timeout); }); }
上面,我們定義了weiboIn()方法,它實(shí)現(xiàn)微博由上往下滾動(dòng)顯示效果,我們通過(guò)animate()方法動(dòng)態(tài)地修改div元素的marginTop屬性。
接著,我們需要把滾動(dòng)到最后的微博重新插入到當(dāng)前第一條微博上,然后通過(guò)fadeIn()函數(shù)實(shí)現(xiàn)微博淡入顯示。
現(xiàn)在,我們基本實(shí)現(xiàn)了微博“大家正在說(shuō)”的向下滾動(dòng)和淡入效果了,我們先用animate()方法修改div元素的marginTop屬性,然后通過(guò)淡入方式顯示滾動(dòng)下來(lái)的微博。
也許有人會(huì)問(wèn):“如果要實(shí)現(xiàn)向上滾動(dòng)和淡出效果呢”?其實(shí),該效果和我們之前實(shí)現(xiàn)的效果恰好相反,首先需要淡出隱藏微博,然后向上滾動(dòng)。
現(xiàn)在,我們已經(jīng)有實(shí)現(xiàn)的思路了,那么接下來(lái)讓我們實(shí)現(xiàn)向上滾動(dòng)和淡出效果吧!具體實(shí)現(xiàn)如下:
/** * Weibos rolling from bottom to top. */ function weiboOut() { if (paused || grabbing) { setTimeout(weiboOut, 500); return; } // Gets last element. var h, $el = $cont.children(':first'), el = $el[0]; // Implements fade out effect. $el.animate(opts.animOut, opts.animOutSpeed, function() { // Gets first weibo item height. h = $el.outerHeight(); $el.animate({ marginTop: -h }, opts.animInSpeed, function() { $el.css({ marginTop: 0, opacity: 1 }); /*@cc_on try { el.style.removeAttribute('filter'); } // ie cleartype fix catch (smother) { } @*/ // append the last weibo item last. $el.css(opts.css['tweet']).show().appendTo($cont); setTimeout(grabFlag ? grabWeibos : weiboOut, opts.timeout); }); }); }
在weiboOut()方法中,我們通過(guò)修改$el的opacity屬性實(shí)現(xiàn)淡出效果,當(dāng)然我們也可以使用fadeOut()方法實(shí)現(xiàn)淡出,同樣我們使用方法animate()修改marginTop屬性,不同的是從-h開(kāi)始變化。
現(xiàn)在,我們已經(jīng)實(shí)現(xiàn)了淡出、淡入以及滾動(dòng)效果了,接下來(lái)我們需要給界面添加CSS樣式讓程序更加美觀。
// Weibo css style in jquery plugin. css:{ // default styling a:{ textDecoration:'none', color:'#3B5998' }, eye:{ width:'40px', height:'40px', position:'absolute', left:'-30px', top:'-20px', border:'none' }, container:{ overflow:'hidden', backgroundColor:'#eee', height:'100%' }, fail:{ background:'#6cc5c3 url(./images/error_page_small.png) no-repeat 50% 50%', height:'100%', padding:'10px' }, frame:{ border:'10px solid #C2CFF1', borderRadius:'10px', '-moz-border-radius':'10px', '-webkit-border-radius':'10px' }, tweet:{ padding:'5px 10px', clear:'left' }, img:{ 'float':'left', margin:'5px', width:'48px', height:'48px' }, loading:{ padding:'20px', textAlign:'center', color:'#888' }, text:{}, time:{ fontSize:'smaller', color:'#888' }, title:{ backgroundColor:'#C2CFF1', margin:0, padding:'0 0 5px 0', textAlign:'center', fontWeight:'bold', fontSize:'large', position:'relative' }, titleLink:{ textDecoration:'none', color:'#3B5998' }, user:{ fontWeight:'bold' } } 然后,我們weibo.serach.style.css文件中添加以下樣式,具體定義如下: div.weibo { margin: auto; width: 300px } #weibo1 { height: 300px;} #weibo2 { height: 300px; } body { background-color: white } body, div { font-family: '微軟雅黑', helvetica, verdana, arial, sans-serif } body { margin: 20px 0; padding: 0; font-size: small; color: #333 } div {display: block} /* Image rounded corner*/ .weiboSearchProfileImg{ border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; } table { margin: auto; border-collapse: separate; border-spacing: 25px; } table { border-collapse: collapse; }
圖9 程序界面
現(xiàn)在,我們已經(jīng)實(shí)現(xiàn)了微博搜索插件,搜索“情人節(jié)”和“元宵節(jié)”話題下的微博,通過(guò)該插件我們獲取了微博信息并且顯示到頁(yè)面中。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)有所幫助。
相關(guān)文章
JavaScript中Number對(duì)象的toFixed() 方法詳解
下面小編就為大家?guī)?lái)一篇JavaScript中Number對(duì)象的toFixed() 方法詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09深入解析ECMAScript?2023?中的新數(shù)組方法
ECMAScript?是一種標(biāo)準(zhǔn)化的腳本語(yǔ)言,它是?JavaScript?的規(guī)范。ECMAScript?2023?是?JavaScript?編程語(yǔ)言的更新,旨在帶來(lái)改進(jìn)并使?JavaScript?程序可預(yù)測(cè)和可維護(hù),這篇文章主要介紹了探索?ECMAScript?2023?中的新數(shù)組方法,需要的朋友可以參考下2023-12-12js style動(dòng)態(tài)設(shè)置table高度
設(shè)置table高度想必大家都會(huì),直接在table標(biāo)簽中設(shè)置下不就行了嗎?這是靜態(tài)的,如果要?jiǎng)討B(tài)設(shè)置你會(huì)嗎?下面的實(shí)例將教會(huì)大家2014-10-10JavaScript獲取css行間樣式,內(nèi)連樣式和外鏈樣式的簡(jiǎn)單方法
下面小編就為大家?guī)?lái)一篇JavaScript獲取css行間樣式,內(nèi)連樣式和外鏈樣式的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07JS實(shí)現(xiàn)批量上傳文件并顯示進(jìn)度功能
這篇文章主要介紹了JS實(shí)現(xiàn)批量上傳文件并顯示進(jìn)度功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06在Webpack中用url-loader處理圖片和字體的問(wèn)題
這篇文章主要介紹了在Webpack中用url-loader處理圖片和字體的問(wèn)題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04JavaScript中的幾個(gè)關(guān)鍵概念的理解-原型鏈的構(gòu)建
JavaScript中的prototype,標(biāo)準(zhǔn)翻譯為“原型”,表示對(duì)象的初始形態(tài)2011-05-05