<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

        javascript精確獲取樣式屬性(上)_javascript技巧

        來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 20:46:37
        文檔

        javascript精確獲取樣式屬性(上)_javascript技巧

        javascript精確獲取樣式屬性(上)_javascript技巧:JQuery,mootools,Ext等類庫在這部分實(shí)現(xiàn)得非常艱辛,盤根錯(cuò)節(jié)地動用一大堆方法,因此想把這部分摳出來難度很大。深入研究它們的實(shí)現(xiàn)后,根據(jù)我積累的CSS知識,終于做出一個(gè)非常簡煉的版本出來。它相當(dāng)于JQuery.cssCur吧,不過或許功能還豐富一些,按飲食業(yè)
        推薦度:
        導(dǎo)讀javascript精確獲取樣式屬性(上)_javascript技巧:JQuery,mootools,Ext等類庫在這部分實(shí)現(xiàn)得非常艱辛,盤根錯(cuò)節(jié)地動用一大堆方法,因此想把這部分摳出來難度很大。深入研究它們的實(shí)現(xiàn)后,根據(jù)我積累的CSS知識,終于做出一個(gè)非常簡煉的版本出來。它相當(dāng)于JQuery.cssCur吧,不過或許功能還豐富一些,按飲食業(yè)

        JQuery,mootools,Ext等類庫在這部分實(shí)現(xiàn)得非常艱辛,盤根錯(cuò)節(jié)地動用一大堆方法,因此想把這部分摳出來難度很大。深入研究它們的實(shí)現(xiàn)后,根據(jù)我積累的CSS知識,終于做出一個(gè)非常簡煉的版本出來。它相當(dāng)于JQuery.cssCur吧,不過或許功能還豐富一些,按飲食業(yè)話說叫“加量不加價(jià)”,我的可能還應(yīng)叫“加量還減價(jià)”……版本還處于Beta階段,由于只個(gè)工具函數(shù)就不弄成類了。
        代碼如下:
        var getStyle = function(el, style){
        if(!+"\v1"){
        style = style.replace(/\-(\w)/g, function(all, letter){
        return letter.toUpperCase();
        });
        return el.currentStyle[style];
        }else{
        return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
        }
        }

        這是函數(shù)的最原始狀態(tài),由于used value是W3C那邊的人搞出來的,因此document.defaultView.getComputedStyle 基本連動也不動就解決百分之99的問題。IE那邊的復(fù)雜了,雖然微軟搞了style,currentStyle與runtimeStyle,但始終都沒有一個(gè)與getComputedStyle相近的實(shí)現(xiàn),最相近的是currentStyle,它只能取到內(nèi)部樣式,而且我們?nèi)≈禃r(shí)要把CSS屬性轉(zhuǎn)換成駝峰風(fēng)格。為了方便,我現(xiàn)在再把它分離出來。
        代碼如下:
        var camelize = function(attr){
        return attr.replace(/\-(\w)/g, function(all, letter){
        return letter.toUpperCase();
        });
        }

        接著我們單獨(dú)解決IE的透明度問題,基本各大類庫都是這樣做的,可見這問題多么棘手,實(shí)在要感謝微軟那幫天才:
        代碼如下:
        var getIEOpacity = function(el){
        var filter;
        if(!!window.XDomainRequest){
        filter = el.style.filter.match(/progid:DXImageTransform.Microsoft.Alpha\(.?opacity=(.*).?\)/i);
        }else{
        filter = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
        }
        if(filter){
        var value = parseFloat(filter[1]);
        if (!isNaN(value)) {
        return value ? value / 100 : 0;
        }
        }
        return 1;
        }

        這時(shí)我們的函數(shù)就變成這樣:
        代碼如下:
        var getStyle = function(el, style){
        if(!+"\v1"){
        if(style == "opacity"){
        return getIEOpacity(el)
        }
        return el.currentStyle[camelize(style)];
        }else{
        return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
        }
        }

        接著下來float屬性問題。IE這邊是styleFloat,W3C是cssFloat。解決不是問題,不過每次都要轉(zhuǎn)換太麻煩了,我參照Ext的實(shí)現(xiàn)把它們緩存起來。
        代碼如下:
        var propCache = [];
        var propFloat = !+"\v1" ? 'styleFloat' : 'cssFloat';
        var camelize = function(attr){
        return attr.replace(/\-(\w)/g, function(all, letter){
        return letter.toUpperCase();
        });
        }
        var memorize = function(prop) { //意思為:check out form cache
        return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : camelize(prop));
        }
        var getIEOpacity = function(el){
        //*****************略**********************
        }
        var getStyle = function (el, style){
        if(!+"\v1"){
        if(style == "opacity"){
        return getIEOpacity(el)
        }
        return el.currentStyle[memorize(style)];
        }else{
        if(style == "float"){
        style = propFloat;
        }
        return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
        }
        }

        到最難的部分了——精確取得高度與寬度。如果用過JQuery的人都知道,John Resig是單獨(dú)處理這兩個(gè)屬性。其實(shí)何止JQuery,其他庫都為此頭痛。問題的起因是如果沒有內(nèi)聯(lián)樣式或內(nèi)部樣式顯式地設(shè)置這兩個(gè)屬性,我們在IE下是無法獲取它們精確的值,或者獲得的是百分比,空字符串,auto,inhert等讓人無可奈何的東西。另,對于國人來說,px的地位是遠(yuǎn)遠(yuǎn)高于em。總總原因,讓我們不能放棄這兩個(gè)屬性。為了取得這兩個(gè)屬性的精確值,我們就需要研究一下CSS繼承問題了。我也已撰寫相關(guān)博文《CSS的inhert與auto》來探討這問題,沒有看,請看完再回來,要不,根本是無法看下去的。
        根據(jù)CSS的分類,width與height是屬性于non-inherited property,由此可知,如果我們不為它設(shè)值,默認(rèn)為auto。這個(gè)auto是個(gè)神奇的東東,如果是塊狀元素,它的寬就相當(dāng)于100%,撐滿父元素的內(nèi)容區(qū),當(dāng)然這是在不考慮其padding,border與margin的情況下。如果是內(nèi)聯(lián)元素,由于不具備盒子模型,你給它設(shè)置寬與高是沒有意義的,就算在火狐,返回的改過轉(zhuǎn)換的精確值與你看到的情況完全不吻合,如果沒有設(shè)置,直接返回auto。為了取得以px為單位的精確值,為了屏蔽塊狀元素與內(nèi)聯(lián)元素,我們需要轉(zhuǎn)換思路,不過光盯著CSS屬性轉(zhuǎn)。這時(shí),微軟做了件好事,開發(fā)出offsetXX,clientXX與scrollXX三大家族,現(xiàn)在終于納入W3C的標(biāo)準(zhǔn)。不過早在這之前,各瀏覽器已經(jīng)跟風(fēng)實(shí)現(xiàn)了。
        在標(biāo)準(zhǔn)模式中,offsetWidth是包含padding,borderWidth與width,如果存在滾動條,它的offsetWidth也不會變,滾動條的寬度在各瀏覽器非常一致,都為17px,這時(shí)它就會把width減去17px,缺失的空間由滾動條補(bǔ)上。 offsetWidth 如果存在padding與padding,我們就要減去padding與padding 在怪癖模式下,offsetWidth等于width,而width是包含padding與borderWidth。 offsetHeight同理。 clientXX家族好理解,就是不包含borderWidth與滾動條。scrollXX家族不說了,在五大瀏覽器都不一致。因此,在標(biāo)準(zhǔn)模式中,要取得高與寬,首選clientXX家族,怪癖模式中,首先offsetXX家族。
        這時(shí)不得不說一下怪癖模式了,別以為升到IE8,設(shè)置相應(yīng)DocType就可以逃過一劫,只要你的網(wǎng)頁太多地方不按標(biāo)準(zhǔn)寫,IE也轉(zhuǎn)為兼容模式中運(yùn)作。這兼容模式是否等于怪癖模式就不得而已,因?yàn)镮E8有多達(dá)五種渲染模式,IE5怪癖模式,IE7標(biāo)準(zhǔn)模式,IE8幾乎標(biāo)準(zhǔn)模式,IE7兼容模式與支持HTML5的邊緣模式。這么多模式,你以為光靠 document.compatMode == "CSS1Compat"能撐住嗎?!撐不住的,幸好IE8在添加新模式的同時(shí),又添加了一個(gè) document.documentMode屬性,真不知是喜還是悲了。因此判斷是否運(yùn)行于怪癖模式的代碼為:
        http://www.mangguo.org/x-ua-compatible-ie8-compatible-mode/
        代碼如下:
        var isQuirk = (document.documentMode) ? (document.documentMode==5) ? true :
        false : ((document.compatMode=="CSS1Compat") ? false : true);

        于是我們有如下偽碼:
        代碼如下:
        var getWidth = function(el){
        if(isQuirk){
        return el.offsetWidth
        }else{
        return el.clientWidth - parseFloat(getStyle(el, "padding-left"))- parseFloat(getStyle(el, "padding-right"))
        }
        }

        對比一下Ext的實(shí)現(xiàn)(只摳出核心部分):
        代碼如下:
        getWidth : function(contentWidth){
        var me = this,
        dom = me.dom,
        w = MATH.max(dom.offsetWidth, dom.clientWidth) || 0;
        w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
        return w < 0 ? 0 : w;
        },

        非常危險(xiǎn)的做法,比Prototype的實(shí)現(xiàn)還差勁,因此它就不得在其他部分進(jìn)行糾正,這就是為什么它的UI體積如此龐大的緣故,從側(cè)面也突現(xiàn)JQuery實(shí)現(xiàn)手法的高超。不過JQuery的實(shí)現(xiàn)了也是相當(dāng)復(fù)雜,如果本元素?zé)o法取得精確值,就從上級元素著手,這個(gè)遍歷消耗非常嚴(yán)重。其中還借用了Dean Edwards的一個(gè)偉大的hack:
        代碼如下:
        var convertPixelValue = function(el, value){
        var style = el.style,left = style.left,rsLeft = el.runtimeStyle.left;
        el.runtimeStyle.left = el.currentStyle.left;
        style.left = value || 0;
        var px = style.pixelLeft;
        style.left = left;
        el.runtimeStyle.left = rsLeft;
        return px;
        }
        //此函數(shù)由Dean Edwards提供的,最早出處見下面鏈接
        // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
        //注意,第二參數(shù)必須是帶單位的數(shù)值,如em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc'
        //百分比好像有點(diǎn)問題
        //另,不要試圖用于IE以外的瀏覽器
        //用法:convertPixelValue($("drag4"),'10em')
        var convertPixelValue = function(el, styleVal){
        //保存原來的值到left與rsLeft
        var style = el.style,left = style.left,rsLeft = el.runtimeStyle.left;
        //下面這步是關(guān)鍵,
        //把el.currentStyle.left代入到el.runtimeStyle.left中,激活hack
        el.runtimeStyle.left = el.currentStyle.left;
        //把非px單位的數(shù)值代入style.left中,如10em
        style.left = styleVal || 0;
        //一定要用style.pixelLeft去取,要不數(shù)值是不準(zhǔn)確
        //如果我們用style.pixelLeft會得160,用style.left會得到150px
        //如果都已轉(zhuǎn)換好,但style.left是不準(zhǔn)確的。
        var px = style.pixelLeft;
        style.left = left;//還原數(shù)據(jù)
        el.runtimeStyle.left = rsLeft;//還原數(shù)據(jù)
        return px;
        }

        這個(gè)hack是用于將em、pc、pt、cm、in、ex等單位轉(zhuǎn)換為px的,當(dāng)然不包括百分比。
        再回來看我的getWidth函數(shù),主要問題是獲取padding-left與padding-right的值。在標(biāo)準(zhǔn)瀏覽器,我們用getComputedStyle可以輕而易舉地獲取經(jīng)過轉(zhuǎn)換的精確值,單位為px。在IE中,如果你給它的值為2em,它就返回2em,很懶。在《CSS的inherit與auto》一文,我也指出了,padding為non-inherited property,這就不用處理inhert這個(gè)無厘頭的值;在auto列表中,padding也不在列,減少了處理auto這個(gè)模糊值的風(fēng)險(xiǎn);加之是可度量單位,各瀏覽器都很厚道地設(shè)置默認(rèn)值為0px,換言之,我們需要的做的事是,當(dāng)值的單位不為px,我們把它轉(zhuǎn)換為px。我們把Dean Edwards的hack整合到我們的主函數(shù)getStyle中即可。如果padding-left是百分比,我們就取其父元素的width乘以百分比即可。總而言之,遍歷的層次與數(shù)算的次數(shù)都被壓縮最少。從這方面說,我在這方面的處理比JQuery優(yōu)勝得多(JQuery連border,margin都列入計(jì)算范圍,而border與margin在IE中存在模糊值,這就逼使JQuery動不動就往上計(jì)算父元素,換言之,需要重復(fù)計(jì)算其父元素的屬性五次;我最多為三次,怪異模式下只需一次)。有時(shí)在IE中取得的值,比擁有g(shù)etComputedStyle的火狐還精確(不過,好像精確過頭,自己用toFixed調(diào)整精確度)。
        代碼如下:
        var getStyle = function (el, style){
        if(!+"\v1"){
        if(style == "opacity"){
        return getIEOpacity(el)
        }
        var value = el.currentStyle[memorize(style)];
        if (/^(height|width)$/.test(style)){
        var values = (style == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
        if(isQuirk){
        return el[camelize("offset-"+style)]
        }else{
        var client = parseFloat(el[camelize("client-"+style)]),
        paddingA = parseFloat(getStyle(el, "padding-"+ values[0])),
        paddingB = parseFloat(getStyle(el, "padding-"+ values[1]));
        return (client - paddingA - paddingB)+"px";
        }
        }
        if(!/^\d+px$/.test(value)){
        //轉(zhuǎn)換可度量的值
        if(/(em|pt|mm|cm|pc|in|ex|rem|vw|vh|vm|ch|gr)$/.test(value)){
        return convertPixelValue(el,value);
        }
        //轉(zhuǎn)換百分比
        if(/%/.test(value)){
        return parseFloat(getStyle(el.parentNode,"width")) * parseFloat(value) /100 + "px"
        }
        }
        return value;//如 0px
        }else{
        if(style == "float"){
        style = propFloat;
        }
        return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
        }
        }

        說多無謂,我們測試一下吧。
        父元素
        子元素

        window.onload = function(){
        alert(getStyle(_("text"),"width"))
        alert(getStyle(_("text2"),'width'))
        alert(getStyle(_("text2"),'padding-left'))
        };

        [Ctrl+A 全選 注:如需引入外部Js需刷新才能執(zhí)行]
        發(fā)現(xiàn)在IE取得值太精確了,比火狐還準(zhǔn)確,不過我也不打算在程序內(nèi)部設(shè)置取精度的運(yùn)算,因?yàn)槲也淮_定現(xiàn)實(shí)中究竟會向上遍歷多少次。在某一父元素的padding與width取精度,很可能會嚴(yán)重影響其最終值的精度。基本上,width與height與padding的取值就到此為止,我們再來看盒子模型的兩個(gè)東西:margin與border。
        margin的auto通常為0px,但在IE6下,當(dāng)我們將其父元素的text-align設(shè)為center,它不但把文本居中,連塊級元素本身也憂患中了,這是IE6居中布局的基石。很難說這是BUG,就像IE5的怪癖模式的盒子模型那樣,很符合人通常的思維習(xí)慣,但是較難實(shí)現(xiàn),加之W3C是偏袒被微軟陰死的網(wǎng)景,于是網(wǎng)景的盒子模型成為標(biāo)準(zhǔn)了。IE6龐大的用戶基礎(chǔ)不容忽視,我們不能隨便給0px了事。我也說了,auto有個(gè)對稱性,因此好辦,我們求出其父元素的width然后減于其offsetWidth再除以2就行了。因?yàn)閛ffsetWidth是針對于offsertParent的,因此我們用時(shí)臨時(shí)把其父元素的position設(shè)為relative,讓子元素來得offsetWidth后,再將父元素的position還原。
        代碼如下:
        //轉(zhuǎn)換margin的auto
        if(/^(margin).+/.test(style) && value == "auto"){
        var father = el.parentNode;
        if(/MSIE 6/.test(navigator.userAgent) && getStyle(father,"text-align") == "center"){
        var fatherWidth = parseFloat(getStyle(father,"width")),
        _temp = getStyle(father,"position");
        father.runtimeStyle.postion = "relative";
        var offsetWidth = el.offsetWidth;
        father.runtimeStyle.postion = _temp;
        return (fatherWidth - offsetWidth)/2 + "px";
        }
        return "0px";
        }

        borderWidth的默認(rèn)值為medium,即使它為0px,但如果我們顯式地設(shè)置其寬為medium呢?!它就不為0px了。這個(gè)比較惡心,我們需要判定這值是我們自己加上的還是瀏覽器的默認(rèn)值。不過我們發(fā)現(xiàn)如果是默認(rèn)的,其border-XX-style為none。另,除了medium外,還存在兩個(gè)模糊值thin與thick。它們在瀏覽器的精確值見下表:
        IE8 ,firefox等標(biāo)準(zhǔn)瀏覽器 IE4-7
        thin 1px 2px
        medium 3px 4px
        thick 5px 6px
        代碼如下:
        //轉(zhuǎn)換border的thin medium thick
        if(/^(border).+(width)$/.test(style)){
        var s = style.replace("width","style"),
        b = {
        thin:["1px","2px"],
        medium:["3px","4px"],
        thick:["5px","6px"]
        };
        if(value == "medium" && getStyle(el,s) == "none"){
        return "0px";
        }
        return !!window.XDomainRequest ? b[value][0] : b[value][1];
        }

        再看top,left,right與bottom,想不到firefox,safari都會偷懶,會返回auto,只有opera老老實(shí)實(shí)地返回精確值。解決辦法也很簡單,因?yàn)槲④浺粋€(gè)好用的函數(shù)已被所有瀏覽器支持了。
        代碼如下:
        //轉(zhuǎn)換top|left|right|bottom的auto
        if(/(top|left|right|bottom)/.test(style) && value == "auto"){
        return el.getBoundingClientRect()[style]
        }

        嗯,文章已經(jīng)很長很長,剩下的部分下次再講。

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        javascript精確獲取樣式屬性(上)_javascript技巧

        javascript精確獲取樣式屬性(上)_javascript技巧:JQuery,mootools,Ext等類庫在這部分實(shí)現(xiàn)得非常艱辛,盤根錯(cuò)節(jié)地動用一大堆方法,因此想把這部分摳出來難度很大。深入研究它們的實(shí)現(xiàn)后,根據(jù)我積累的CSS知識,終于做出一個(gè)非常簡煉的版本出來。它相當(dāng)于JQuery.cssCur吧,不過或許功能還豐富一些,按飲食業(yè)
        推薦度:
        標(biāo)簽: 獲取 js 精確
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 中文字幕亚洲免费无线观看日本 | 亚洲啪啪AV无码片| 亚洲精品无码成人片久久不卡| 中文字幕免费在线看线人 | 亚洲美女激情视频| 最近2019中文字幕免费直播| 亚洲AV无码一区二区三区系列 | 久久国产乱子伦精品免费强| 亚洲一区二区三区在线观看精品中文 | 亚洲成人在线电影| 中国xxxxx高清免费看视频| 亚洲首页在线观看| 日韩精品无码区免费专区| 中文字幕在线日亚洲9| 在线视频免费国产成人| 特级毛片全部免费播放a一级| 亚洲av中文无码| 成人片黄网站色大片免费观看APP| 亚洲一区二区电影| 免费看少妇作爱视频| 日本激情猛烈在线看免费观看 | 久久亚洲精品成人AV| 成人片黄网站色大片免费| 特级毛片A级毛片免费播放| 亚洲综合国产一区二区三区| 嫩草在线视频www免费观看| 亚洲福利电影一区二区?| 色吊丝最新永久免费观看网站| www在线观看免费视频| 麻豆亚洲av熟女国产一区二| 免费看的一级毛片| 少妇性饥渴无码A区免费 | 亚洲Av无码专区国产乱码DVD| 精品香蕉在线观看免费| 成全高清在线观看免费| 亚洲综合久久成人69| 四虎永久成人免费影院域名| 久久精品国产大片免费观看| 亚洲AV无码一区二区三区牛牛| 亚洲免费无码在线| 一二三四免费观看在线电影|