JavaScript >> Javascript 文檔 >  >> Tags >> CSS

使用 jQuery 製作 Google 的聖誕塗鴉

這個假期,谷歌再次用他們所謂的動畫標誌或塗鴉來提升那些訪問他們主頁的人的聖誕氣氛。現在,假期在我們身後,我們可以充分利用那家豪華餐廳的卡路里,並努力在接下來的一周保持體形。因此,讓我們嘗試在 jQuery 和一些 CSS 的幫助下重新創建 Google 的動畫徽標!

HTML

首先,標記。由於大部分 HTML 是由 jQuery 生成的,我們只需要指定一個 holder div。這是我們頁面的樣子:

index.html

<!DOCTYPE html>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Making Google's Christmas Doodle with jQuery | Tutorialzine Demo</title>

<link rel="stylesheet" type="text/css" href="css/styles.css" />

</head>
<body>

<div id="page"></div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script src="js/script.js"></script>

</body>
</html>

樣式集位於頂部,腳本文件位於底部。 #page div 將保存生成的塗鴉標記。您可以在下面的片段中看到生成的示例:

<a href="#" class="pic" style="top: 100px; left: 30px; width: 60px; height: 100px;
margin-top: 0px; margin-left: 0px; z-index: 0;">
    <img style="display:block;left:-10px;top:-30px;" src="img/1.jpg" />
</a>
<!-- More items -->

top、left、width 和 height 屬性在 document.ready 事件中傳遞給 jQuery。它們作為樣式屬性包含在生成的圖片錨點中。 a 元素還包含圖像,該圖像被 oveflow:hidden 部分隱藏 .當我們將光標移到 .pic 上方時,它會展開並顯示圖像的其餘部分。這聽起來很簡單,但這種方法有一些起初並不明顯的注意事項:

  • 我們不能以通常的方式綁定事件。當圖像擴展時,它會覆蓋相鄰的圖片並使其無法訪問,這將是一個很大的不便。如果以 Google 的規模來考慮,這將意味著很多人不開心;
  • 在動畫期間,圖片必須固定在一個地方。這意味著我們必須在錨點動畫的每一步更新它的偏移量(通過使用邊距屬性)。這需要以完美同步的方式同時為兩個不同的元素製作動畫,否則圖像會抖動。

CSS

CSS 代碼很少,因為我們只需要設置 #page 的樣式 div 和 .pic 錨點。

css/styles.css

#page{
    width:680px;
    height:300px;
    margin:60px auto 80px;
    position:relative;
}

.pic{
    position:absolute;
    overflow:hidden;
    border:4px solid #99280e;
    text-decoration:none;
    z-index:0;
}

.pic img{
    position:absolute;
    border:none;
}

.pic:nth-child(2n+1){
    border-color:#6A2B1C;
}

.pic:nth-child(3n+2){
    border-width:5px;
}

我正在使用 nth-child CSS3 選擇器用於定位特定元素並應用更暗和更厚的邊框。由於這主要用於演示目的,因此該腳本在不支持 CSS3 的舊瀏覽器中仍然可以正常運行。

jQuery

為了使代碼更好地組織(並且更短),我們將為擴展圖像創建一個 JavaScript 類,並為每個圖像創建一個該類的對象,同時將寬度、高度、來源和其他屬性作為參數傳遞。

讓我們從類定義開始:

js/script.js - 第 1 部分

  function pic(options){

        // All the properties of the options object
        // are copied to the current pic:

        $.extend(this,options);

        // Creating the markup of the pic,
        // and storing it in the elem property:

        this.elem = $('<a>',{
            className: 'pic',
            href: this.href,
            css : {
                top : this.top,
                left : this.left,
                width: this.width,
                height: this.height
            }
        });

        var borderWidth = 5;

        // The bottom and right properties are not passed
        // as arguments, so we need to calculate them.

        this.bottom = this.top+this.height+2*borderWidth;
        this.right = this.left+this.width+2*borderWidth;

        this.image = $('<img>',{
            css:{
                left : -this.img.offsetLeft,
                top : -this.img.offsetTop
            }
        });

        var self = this;

        // Appending the image to the body so we can get
        // its dimensions. After we do this, we remove it
        // and append it to the markup stored in this.elem:

        this.image.hide().appendTo('body').load(function(){

            self.img.width = self.image.width();
            self.img.height = self.image.height();
            self.elem.append(self.image.show());

        }).attr('src',this.img.src);

    }

上面的 pic 函數是我們類的構造函數。正如您稍後將看到的,我們將為頁面上的每個可擴展圖像創建一個此類的新對象。調用時,它會創建您在第一步中看到的標記,並將其存儲在 this.elem 屬性作為 jQuery 對象。這意味著我們可以將 elem 屬性用作常規 jQuery 對象,以及庫提供給我們的所有方法。

js/script.js - 第 2 部分

// The prototype holds the class methods,
    // that are common for all objects.

    pic.prototype = {
        open    : function(){
            if(this.opened){
                return false;
            }

            this.opened = true;

            // Firing our own expand method with a percentage of 100:
            this.expand(100);
        },
        close   : function(){
            if(!this.opened && !this.focused){
                return false;
            }

            this.opened = this.focused = false;
            this.expand(0);
        },
        focus   : function(){
            if(this.focused || this.opened){
                return false;
            }

            this.focused = true;

            //Expanding to 30%:
            this.expand(30);
        },

        near    : function(x,y){
            // Checking whether the passed x and y coordinates are near the current image:
            return (x > this.left-15 && x < this.right+15 && y > this.top-15 && y < this.bottom+15);
        },

        over    : function(x,y){
            // The same, but returning true only when directly above the image:
            return (x > this.left && x < this.right && y > this.top && y < this.bottom);
        },

        expand : function(animPercent){
            if(!this.animateObj){
                this.animateObj = {count:0};
            }

            // We use jQuery's animate method to
            // change the count property of the object:

            $(this.animateObj).stop().animate({
                count:animPercent
            },{
                duration:150,

                // The step funciton is executed on every animation frame.
                // With jQuery's proxy we pass the "this" of the function:
                step:$.proxy(this.stepAnimation,this)
            });
        },

        stepAnimation : function(p,fx){

            // P holds the current value of the count property,
            // between 0 and 100. Below we are turning it into percentage.

            p = p/100;

            // Changing the size and position of the image holder:

            this.elem.css({
                width : (this.img.width - this.width)*p + this.width ,
                height : (this.img.height - this.height)*p + this.height,
                marginTop : -this.img.offsetTop*p,
                marginLeft: -this.img.offsetLeft*p,
                zIndex: 100*p
            });

            // Moving the image so it appears as if fixed:

            this.image.css({
                marginLeft : p*this.img.offsetLeft,
                marginTop : p*this.img.offsetTop
            });
        }
    };

原型屬性包含所有圖片對象使用的通用方法。 打開 , 關閉 專注 expand 的包裝器 方法,也在原型中定義。該方法以百分比為唯一參數,將圖片放大到指定的大小(100%對應完整顯示的圖片大小)。

仔細看看 jQuery 的 animate 第 52 行的方法。我們不是在 DOM 元素上調用它,而是使用它來增加 count 普通 JavaScript 對象的屬性,同時在 step 中自己執行動畫 功能降低。這樣我們就讓 jQuery 來處理時間、緩動、排隊和停止動畫,並且只告訴我們何時更新圖片的 CSS 屬性。這解決了一次為多個元素設置動畫的問題。

如開頭所述,我們無法將事件綁定到可擴展圖片。為此,我們有兩個更有趣的方法 - near 結束 .這些獲取鼠標指針的 x/y 坐標並返回一個布爾表達式,指示鼠標是否在當前圖像附近/上方。您將在下面看到它是如何使用的。

js/script.js - 第 3 部分

$(document).ready(function(){

        var page    = $('#page');

        // Creating the expanding images:

        var picArr = [
            new pic({
                top : 100, left : 30, width : 60,height : 100, href:'#',
                img : { src : 'img/1.jpg', offsetTop : 50, offsetLeft: 10}
            }),
            new pic({
                top : 55, left : 107, width : 70,height : 115, href:'#',
                img : { src : 'img/2.jpg', offsetTop : 30, offsetLeft: 46}
            }),

            /* More pics here */

        ];

        // Appending the images to the #page div:

        $.each(picArr,function(){
            page.append(this.elem);
        });

        // Setting up an event listener for the window.load event.
        // window.load is executed after all the images have been loaded.

        $(window).load(function(){

            page.mousemove(function(e){

                var left = (e.pageX - page.offset().left),
                    top = (e.pageY - page.offset().top),
                    pic = null;

                // On each mouse movement, loop through the pics
                // and check whether the cursor is above any of them.

                for(var i = 0;i < picArr.length;i++){
                    pic = picArr[i];

                    if(pic.near(left,top)){

                        if(pic.over(left,top)){
                            pic.open();
                        }
                        else pic.focus();
                    }
                    else pic.close();
                }

            }).mouseleave(function(){

                // When the mose leaves the #page div,
                // foce a close on all the images.

                for(var i = 0;i < picArr.length;i++){
                    picArr[i].close();
                }

            });
        });
    });

在上面的代碼中,我們填充了 picArr 帶有 pic 對象的數組,然後我們將它們附加到 #page 分區。稍後,在 window.load 事件,我們為 mousemove 事件綁定一個監聽器,並檢查當前鼠標位置是否在任何圖像上方。如果距離圖像小於 15 像素,我們聚焦它,如果它在它的正上方,我們運行 open 方法顯示完整圖像。

我們類似於 Google 的聖誕節標誌已經完成!

總結

您可以在動態標題、產品演示、導覽或幻燈片中使用此腳本。通過在 script.js 中創建圖片對象時傳遞不同的參數,您將能夠自定義腳本的幾乎每個方面。由於它會自動檢測圖像的大小,因此您可以輕鬆更改它們而不會出現問題。

差不多就是這樣。現在我們又加快了速度,我們都可以度過一個富有成效的一周,然後在即將到來的下一個假期中脫軌。


Tutorial JavaScript 教程
  1. 為什麼遞歸不起作用?我正在嘗試顯示 n 到 1 個系列

  2. 尋求開發者喜愛的 SaaS 項目管理工具!

  3. 與 Ben Galbraith 合作的殺手級 Web 開發工具

  4. 可觀察對象的查詢:瘋狂而簡單!

  5. React 最佳實踐和模式以減少代碼 - 第 3 部分

  6. Next.js 12 中的 React 服務器組件

  7. 2005:DOM 年

  1. JavaScript every() 方法

  2. 必須知道:編程的基本工程原理

  3. 使用 CodeLobster 加速 jQuery 開發

  4. 個人網站評論

  5. 如何擺脫教程的厄運

  6. Wes Bos 講述他是如何學會編程的

  7. 如何用數字變魔術

  1. 自定位 React 組件

  2. 通過構建計數器應用程序學習 JavaScript 基礎知識

  3. 查看以從 SpaceX API 中提取火箭數據🍋

  4. 解決方案:最小努力的路徑