宅神朱學恆Blog的文章除了一向犀利大膽外,極其豪邁的全尺寸圖檔(尤其是美女正妹圖)更是一大特色。不過,圖檔實在是太大了,即便用我的1280*1024螢幕檢視,若不捲動網頁,往往只能窺得正妹照片的一小角,必須由小得可憐的可視範圍推測那一大塊膚色到底是美腿還是伴隨入鏡狗狗的後腳? 頗有瞎子摸象之趣。
【補註】後來才知道,原來有個"男子漢絕不縮圖"的典故,我又孤陋寡聞了,呵!

前幾天偶爾逛到在Greasemonkey載入jquery.js的做法,一時興趣就動手寫了這個想了很久的外掛。載入jQuery後,隨意加幾行Code,遇到大尺寸圖檔自動縮小顯示比例的Greasemonkey Script就完成了。

[2012-05-05更新]Greasemonkey 0.8+增加了@require宣告, 可以更簡便地載入jQuery。

完整Script附於文後,敬請大家指教,程式中有幾個重點補充說明一下:

在head中加掛script src=”…”載入js是很標準的做法,利用setTimeout定期檢查jQuery物件存在與否偵測js是否載入完成,這跟我另一篇文章介紹過的原理相仿。裡面用了unsafeWindow來存取網頁所在的window物件,則是本次實作練習的重大學習收獲。

resizeHugeImage()會掃瞄網頁裡所有的圖檔,針對長或寬大於800px者縮小顯示尺寸,使其長寬均不超過800為原則。由於圖檔載入完成時間可能發生在$(document).read(…)之後,此時便無法得知圖片長寬,無以為繼。因此,此處利用image的complete屬性判別圖片是否載入完成? 若否,則將檢測長寬及縮圖函數掛在load事件上,待圖片載入完成自動觸發;若圖檔已載入完成,則用先前介紹過的call()觸發檢測縮圖函數。另外,我發現某些圖需要完整顯示才看得清楚,在圖片上加上hover()紅框,並提供dblclick()恢復原尺寸的功能。

// ==UserScript==
// @name           Resize Lucifer's super big picture
// @namespace      http://www.darkthread.net
// @include        http://blogs.myoops.org/*
// ==/UserScript==
    // Add jQuery, ref http://joanpiedra.com/jquery/greasemonkey/
    var GM_JQ = document.createElement('script');
    GM_JQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js';
    GM_JQ.type = 'text/javascript';
    document.getElementsByTagName('head')[0].appendChild(GM_JQ);
 
    // Check if jQuery's loaded
    function GM_wait() {
        if(typeof unsafeWindow.jQuery == 'undefined') 
            window.setTimeout(GM_wait,100);
        else { $ = unsafeWindow.jQuery; resizeHugeImage(); }
    }
    GM_wait();
 
    // All your GM code must be inside this function
    function resizeHugeImage() {
        $("img").each(function() {
            if (this.complete) //if already loaded
                proc.call(this);
            else //hook load event
                $(this).load(proc);
        });
        function proc() {
            var img = $(this);
            var w = img.width(), h = img.height();
            var longSide = (w > h ? w : h);
            if (longSide > 800) {
                var ratio = 800.0 / longSide;
                var nw = w * ratio;
                var nh = h * ratio;
                img.data("h", h).data("w", w)
                .width(nw).height(nh)
                .css("cursor", "pointer")
                .hover(
                function() { $(this).css("border", "solid 2px red"); },
                function() { $(this).css("border", "solid 2px black"); })
                .dblclick(function() { 
                    var x = $(this);
                    x.width(x.data("w"))
                    .height(x.data("h"));
                });
                
            }
        }
    }

調整前

調整後

* Firefox使用者可以按這裡下載直接安裝!


Comments

# by Ammon

img.attr({"h":h, "w":w}) 建議改用 .data 來儲存 jQuery官方文件說明: This function is used to get stored data on an element without the risk of a circular reference. It uses jQuery.data and is new to version 1.2.3. It can be used for many reasons and jQuery UI uses it heavily.

# by Jeffrey

to Ammon, 因為是單純的數字型別,一時沒有想到改用data :P,不過閣下的建議是對的,data的功能不輸attr,且更安全,故從善如流。謝謝指教。

# by motovb

jquery 是不是有read (載完html) 跟 ready(載完所有物件) 可以使用啊?

# by Jeffrey

to motovb, 我另有一篇相關討論,請參考: http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/06/05/jquery-ready-vs-load.aspx

# by 訪客

我並不懂Script,但是我覺得你寫的這個Script很棒,至少我比較容易看懂並修改。 我想把Script改成圖片超過特定的尺寸就不要下載,請問怎樣辦呢?

# by Jeffrey

to 訪客, 圖片沒有載入完成前,無法透過DOM取得圖片的大小(除非<img> tag上有載明),因此我覺得要從Javascript的角度實踐圖檔超過一定尺寸就不下載挺困難的。

# by 小星

請問unsafeWindow是什麼?有參考網址嗎?我引用上面的Js到程式中的頁面,會顯示錯誤訊息->沒有unsafeWindow物件 請問有可能做出,等網頁中的"全部圖檔"下載完成後,再一起顯示嗎?因為我有寫隻程式用jQuery的gallery相簿效果,但可能是使用者家裡頻寛不夠,會先顯示一張一張的圖後,最後再結合起來顯示相簿效果,真是太冏了 謝謝您的回覆

# by Jeffrey

to 小星, unsafeWindow是GreaseMonkey裡的專屬物件(可參考: http://goo.gl/Tj6N),若在一般正常網頁的js中引用會出錯。至於"先顯示一張一張的圖後,最後再結合起來顯示相簿效果",我粗淺的想法是先將圖片區設成隱形(style="display:none"),顯示載入中訊息,利用$(window).load(...) http://goo.gl/4r9V 事件待所有圖檔都載入完成後再將隱藏"載入中"訊息,顯現圖片區。再不然就是要用更複雜的機製邊顯示邊載入,但那就涉及更多技巧了。

# by 路人

太感謝了! 原本想要某個網頁執行火狐不能執行 但JQuery偏偏比JavaScript比較熟 剛好誤撞這篇,看到如何載入 結果就搞定了! 我使用的是Scriptish 某個Userscript的Fit images不能用 剛好用這篇,改一下程式就解決了 站長,你真是我的大恩人 orz(給你一拜

Post a comment