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

玩轉 CSS3:旋轉報紙

想像一下發生在 1930 年代的警匪劇。在一連串銀行搶劫案之後,一名年輕的偵探被告知了他的生命案。他接受了挑戰,經過數月的艱苦工作和危及生命的情況,他設法將壞人繩之以法。

接下來是那個時期電影製作人使用的經典裝置 - 報紙閃爍並朝著鏡頭旋轉,讚美我們主角的英雄壯舉。

因此,讓我們玩得開心,並使用新版本 Firefox、Chrome 和 Safari 的 CSS3 動畫功能構建這個經典場景,並在此過程中挑選有用的技術。

理念

使用 JavaScript,我們將加載報紙的切片版本(切片獨立編碼為 PNG 或 JPG 以用於較小的文件大小),並將它們組合在單個畫布元素中。我們還將從 Google WebFonts 加載自定義字體,用於將文章標題寫入畫布。

我們還定義了一個簡單的 CSS3 關鍵幀動畫,它使用了 scale() 等變換 和 rotate() 為畫布元素設置動畫。將畫布附加到頁面會觸發動畫,這意味著我們不需要為效果本身編寫一行 JavaScript。

目前,Firefox、Safari 和 Chrome 都支持 CSS3 關鍵幀動畫,因此如果您使用的是這些瀏覽器的最新版本,您將能夠享受演示。

以下是促成上述決定的一些次要因素:

  • 編碼為 PNG 的報紙圖片超過 250kb。將其切片成獨立編碼的切片可節省 200kb,因為中心部分確實需要透明度並且編碼為 JPEG;
  • 旋轉一堆 DOM 元素比單個畫布元素慢。此外,瀏覽器中的旋轉文本通常看起來不太好,因為字母可能會失去其抗鋸齒功能(請參見此處的一個簡單實驗;它在 Firefox 中最為明顯)。將文本和報紙背景繪製到 canvas element 解決了這兩個問題;

HTML

頁面的標記很少——一切都是使用 jQuery 完成的,所以我們只需要包含我們的 JS 源文件和样式表。

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Spinning Newspaper Effect | Tutorialzine Demo</title>

        <!-- Our CSS stylesheet file -->
        <link rel="stylesheet" href="assets/css/styles.css" />

        <!-- Embedding the Anton font from Google Webfonts -->
        <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Anton&v2" />

        <!--[if lt IE 9]>
          <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>

    <body>

        <h3 id="fin">That is all</h3>

        <!--
            This div uses the "Anton" font,
            preloading it for the canvas element
        -->
        <div id="fontPreload">.</div>

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

    </body>
</html>

在 head 部分,我們包含我們的 styles.css 文件(下面討論)和一個樣式表,它嵌入了來自 Google WebFonts 的 Anton 字體。在文件末尾附近,我們包含了 1.6.2 版的 jQuery 庫 和我們的 script.js (後面會詳細討論)。

代碼中最重要的一段標記也是最不起眼的。 #fontPreload div 對於此示例至關重要。它所做的是使用嵌入式 Anton 網頁字體。這是必需的,以便瀏覽器在將字體用於畫布之前正確初始化字體。沒有它,我們就會盯著一張空白的報紙封面。

jQuery

由於我們使用的是自定義 Web 字體,因此我們需要確保在使用該字體生成報紙標題之前已加載該字體。這就是我們將回調綁定到 $(window).load() 的原因 事件,在所有內容加載後調用:

assets/js/script.js

$(window).load(function(){

    var imgPath = "assets/img/";

    // Define 6 paper covers:

    var papers = [
        {
            line1:"The financial",
            line2:"chrisis is a hoax!",
            subtitle:"Economist admits practical joke"
        }, {
            line1:"Deeply fried now",
            line2:"considered healthy",
            subtitle:"Scientists change the definition of \"Healthy\""
        }, {
            line1:"Apple announces",
            line2:"the new iphone 9",
            subtitle:"5, 6, 7 and 8 deemed \"not hip enough\""
        }, {
            line1:"The world did end",
            line2:"on may 21st!",
            subtitle:"Priest argues we are actually dead"
        }, {
            line1:"France imposes an",
            line2:"internet kitten tax",
            subtitle:"Every cat picture on the internet will cost 3 €"
        }, {
            line1:"Thank you &",
            line2:"goodbye",
            subtitle:"The Zine Weekly takes its farewell"
        }
    ];

    // Check whether canvas and CSS3 animations are supported:

    if(!$.support.canvas){
        $('#fin').html('Sorry, your browser does not<br />support &lt;canvas&gt;').show();
        return;
    }

    if(!$.support.css3Animation){
        $('#fin').html('Sorry, your browser does not<br />support CSS3 Animations').show();
        return;
    }

    // Use jQuery.Deferred to bind a callback when all
    // the images that comprise the paper are loaded:

    $.when(

        loadImage(imgPath+"paper_top.png"),
        loadImage(imgPath+"paper_left.png"),
        loadImage(imgPath+"paper_center.jpg"),
        loadImage(imgPath+"paper_right.png"),
        loadImage(imgPath+"paper_bottom.png")

    ).then(function( imgTop, imgLeft, imgCenter, imgRight, imgBottom ){

        // Loop through the paper covers and
        // create a new canvas for each one:

        $.each(papers,function(i){

            var canvas  = document.createElement("canvas"),
                c       = canvas.getContext("2d");

            canvas.width = 717;
            canvas.height = 526;

            // Drawing the paper background slices:

            c.drawImage( imgTop, 0, 0 );
            c.drawImage( imgLeft, 0, 12 );
            c.drawImage( imgCenter, 14, 12 );
            c.drawImage( imgRight, 711, 12 );
            c.drawImage( imgBottom, 0, 516 );

            // Drawing the text using our helper
            // function (see at the bottom):

            drawText( this.line1, this.line2, this.subtitle, c, 358, 250 );

            // Appending the element to the page.
            // This triggers the CSS3 animation.

            setTimeout(function(){
                $("body").append(canvas);
            },i*5800);

        });

        // "This is all"
        $('#fin').delay(papers.length*5800).fadeIn();
    });

    /*------------------------
        Helper functions
    ------------------------*/

    // Load an image by URL and resolve a jQuery.Deferred:

    function loadImage(src){

        var def = new $.Deferred(),
            img = new Image();

        img.onload = function(){

            //  Resolve the deferred. The img parameter
            //  will be available in the then function:

            def.resolve(img);
        }

        // Always set the src attribute
        // after the onload callback:

        img.src = src;

        return def.promise();
    }

    // Draw two lines of text and a subtitle
    // on the canvas (passed as the c param):

    function drawText( line1, line2, subtitle, c, x, y ){

        c.font = "65px Anton,Calibri";
        c.textAlign = "center";
        c.fillStyle = "#3e3e3e";

        c.fillText(line1.toUpperCase(),x,y);
        c.fillText(line2.toUpperCase(),x,y+80);

        c.font = "italic 20px Georgia,serif";
        c.fillStyle = "#737373";

        c.fillText(subtitle,x,y+120);
    }
});

(function(){

    // Adding custom checks for canvas and css3
    // animations support, to the jQuery.support object:

    $.support.canvas = 'getContext' in document.createElement('canvas');

    $.support.css3Animation = (function(){
        var sp = $('<span>');

        return (
            sp.css("-webkit-animation") !== undefined   ||
            sp.css("-moz-animation") !== undefined      ||
            sp.css("animation") !== undefined
        );

    })();
})();

要生成報紙,我們需要首先加載構成圖像的五個切片。這聽起來像是使用 jQuery 的 Deferred 對象 的完美場所 ,在 1.5 版中引入。它的作用是在一些異步事件完成時通知我們。正如您在上面的代碼中看到的,我們在 loadImage() 中使用它 功能。 then() 第 58 行的方法只有在所有 5 張圖片都加載完畢後才會被調用。

$.each裡面 循環,我們為每個封面創建一個畫布元素,並在 setTimeout() 引入的延遲後將它們添加到頁面 打電話。

一旦我們在頁面上設置了畫布,我們就可以繼續對其進行動畫處理。

CSS

畫布元素被視為任何其他元素。這意味著您可以像處理常規圖像一樣安全地設置和轉換它們。

將畫布添加到頁面後,它將採用您在下面看到的樣式:

canvas{
    position:fixed;
    width:717px;
    height:526px;

    top:50%;
    left:50%;

    margin:-263px 0 0 -358px;
    opacity:0;

    /* Configure the animation for Firefox */
    -moz-animation-duration:6s;
    -moz-animation-name:spin;
    -moz-animation-timing-function:linear;

    /* Configure it for Chrome and Safari */
    -webkit-animation-duration:6s;
    -webkit-animation-name:spin;
    -webkit-animation-timing-function:linear;
}

這裡沒有什麼不尋常的。我們將畫佈在頁面中居中,並定義動畫的不同方面,例如 duration , 名字 ,以及一個計時函數 . “線性”將使我們的動畫以恆定速度運行,而不是像默認使用的“輕鬆”那樣加速。

在此之後,我們必須使用@keyframes 聲明來指定我們的元素在動畫期間如何看待不同的關鍵點:

@-moz-keyframes spin{
    0%{
        opacity:0.2;
        -moz-transform:scale(0.2) rotate(0deg);
    }

    15%{
        opacity:1;
        margin:-263px 0 0 -358px;
        -moz-transform:scale(1) rotate(1090deg);
    }

    90%{
        opacity:1;
        top:50%;
        -moz-transform:scale(1) rotate(1090deg);
    }

    100%{
        top:500%;
        opacity:1;
        -moz-transform:scale(1) rotate(1090deg);
    }
}

當畫布元素添加到頁面時,我們從 0% 開始 上面的位置。元素的不透明度 設置為 0.2,使用 scale() 將其縮小 5 倍 轉型。它可以快速動畫到完整尺寸(scale(1) ) 15%90% 動畫的時間(或大約四秒半),它保持固定在屏幕上,之後它迅速落在窗口底部邊框之外(頂部增加到 500%)。

指定要在動畫的每個百分點中保留的屬性很重要。一個例子是 -moz-transform:scale(1) rotate(1090deg) 聲明,重複三遍。沒有它,Chrome 和 Safari(但不是 Firefox)將恢復到動畫中間 0 度的默認旋轉。

而且,由於這仍然被瀏覽器供應商認為是一個實驗性功能,我們需要為 webkit 編寫相同的代碼:

@-webkit-keyframes spin{
    0%{
        opacity:0.2;
        -webkit-transform:scale(0.2) rotate(0deg);
    }
    15%{
        opacity:1;
        margin:-263px 0 0 -358px;
        -webkit-transform:scale(1) rotate(1090deg);
    }
    90%{
        opacity:1;
        top:50%;
        -webkit-transform:scale(1) rotate(1090deg);
    }

    100%{
        top:500%;
        opacity:1;
        -webkit-transform:scale(1) rotate(1090deg);
    }
}

這樣我們的旋轉報紙效果就完成了!

結論

與 1930 年代的任何警察劇以及 1930 年代本身一樣,本教程必須結束。希望你們在學習本教程後獲得和我編寫教程一樣的樂趣。如果您有任何想法或建議,請務必在評論部分分享。您還可以下載帶有報紙模板的 PSD,這樣您就可以自己製作了,如下所示。


Tutorial JavaScript 教程
  1. 使用 Recoil.js 管理全局狀態

  2. Javascript Tagalog - 數組反轉方法

  3. 為什麼您的電子郵件可能會反彈以及您可以做些什麼

  4. 現代標記語言AbstractMark的發展歷程

  5. 使用 github 操作發布無服務器應用程序

  6. 在 Express 中輸入路線

  7. chrome控制台上的vanilla js錯誤“無法設置未定義的屬性”

  1. 時間死區

  2. React Native 入門

  3. 使用 EventEmitter 在 Node.js 中處理事件

  4. 獲取 API:基礎知識

  5. 前 15 個 jQuery 技巧

  6. 使用 vue 輕鬆創建 2 狀態、SVG 驅動的轉換

  7. Onclick javascript使瀏覽器返回上一頁?

  1. React.js 和 Typescript 入門

  2. 使用 Vue 3、Node、Express 和 MongoDB 構建 CRUD 應用程序 |教程

  3. 令人敬畏的 JavaScript 庫要簽出。

  4. 如何在不從 HTML 重新加載到燒瓶的情況下獲取輸入表單?