中文版30種瀕危動物碎片拼圖

介紹

該作品原本是阿姆斯特丹設計師 Bryan James用純CSS技術表現出30種動物的碎片拼圖形象,這30動物,非常的可愛,但不幸的是,它們都是瀕臨滅絕的動物,它們的生存情況正面臨着危機。 你能看到它們在掙扎,它們在反抗… 它們在這個互動的作品裏申訴…

點擊打開 30個物種,30種碎片拼圖 (“Species in Pieces”互動式瀕危動物展覽) 的網站主頁,
灰盔鳥
空靈的背景音樂引入了顏色飽滿的多邊形圖案,配合着30種瀕危動物的文字介紹。伴隨30只生命樣貌的切換,一幅幅幾何狀組合的破碎,設計師試圖展現過去10年來棲息地遭受破壞是如何把動物推向滅絕的邊緣——曾是 2014 年巴西世界盃吉祥物的三帶犰狳( Three-Banded Armadillo of Brazil)數量減少了 30%,新幾內亞島上的原針鼴鼠( Long-Beaked Echidna )因人類的狩獵而在過去 35-40 年間減少近 80%。

鴞鸚鵡
克尼斯納海馬
小頭鼠海豚

從擇選物種、設計圖形到蒐集生存處境等數據,James 歷時半年,終於完成了這場展覽。在接受《赫芬頓郵報》(The Huffington Post)的採訪時,他表示自己深信唯有看見,纔有機會理解。他希望借用看似乾癟的的數位科技棱角,營造出特殊的美感,來表達在地球上生存着的美好生命隨時有可能消失剝離的意象。而之所以叫“30 PIECES”,是因爲James起初在編程的時候,第一幅成型的作品剛剛好是30片三角形拼接而成。

設計實現

這個作品展示的是 30 個瀕危動物,沒有使用 canvas 繪製,而是隻使用了 CSS/ clip-path這個屬性,如下:

clip-path: polygon(49% 0, 95% 65%, 11% 94%);

clip-path的前身其實是 SVG,所以它理應和 SVG 相似,是以點的座標相連實現遮罩的, 創建一個小的 Demo 非常簡單,只需一個 div,就可以畫出千奇百怪的造型,這便是整個項目的基礎。

 width: 200px;
height: 200px;
 background-color: #fff88b;
clip-path: polygon(49% 0, 95% 65%, 11% 94%);

運動效果實現

如何讓它運動呢? 其實也很簡單, 那就是transition
是的,這個屬性支持 transition 補間動畫,只需要這樣設置,你的“碎片”就會按照你預想的軌跡運動了。

    div {
     width: 200px;
     height: 200px;
     background-color: #fff88b;
     transition: 1s;
     clip-path: polygon(49% 0, 95% 65%, 11% 94%);
    }
    div:hover {
     clip-path: polygon(49% 19%, 95% 85%, 1% 99%);
    }

圖形繪製

在一個空白頁面放入設計圖,通過點擊每個點,自動計算到頁面左邊、頂端的百分比。
圖形繪製
代碼如下:

    $(document.body).on('click', function (e){
      var mouseX = e.pageX;
      var mouseY = e.pageY;
      var shapesoffsetX = $('.polygon-wrap').offset().left;
      var shapesoffsetY = $('.polygon-wrap').offset().top;
      var polygonswidth=$('.polygon-wrap').width();
      var polygonsheight=$('.polygon-wrap').height();
      var shapesmouseX = mouseX - shapesoffsetX;
      var shapesmouseY = mouseY - shapesoffsetY;
      var mousepercentX = shapesmouseX / polygonswidth;
      var mousepercentY = shapesmouseY / polygonsheight;
      var finalmouseX = (mousepercentX) * 100 ;
      var finalmouseY = (mousepercentY) * 100 ;
      var normalisedX = parseFloat(finalmouseX).toFixed(3);
      var normalisedY = parseFloat(finalmouseY).toFixed(3);
      nodecount = nodecount+1;
      if (nodecount < 3) {
        nodescss = nodescss + normalisedX + '% ' + normalisedY + '% ,';
      } else  
      if (nodecount == 3) {
        nodescss = nodescss + normalisedX + '% ' + normalisedY + '% );';
        alert(nodescss);
        nodescss = '-webkit-clip-path: polygon( ';
        nodecount = 0;
      }   
    });

draw-demo.html

<!DOCTYPE html">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
    <body>
        <div class="polygon-wrap">
            <img class="feature" src="assets/img/polygon-demo.png" alt="polygon">
            <script src="assets/js/jquery-3.js"></script>
            <script>
                nodescss = '-webkit-clip-path: polygon( ';
                nodecount = 0;
                $(document.body).on('click', function(e) {
                    var mouseX = e.pageX;
                    var mouseY = e.pageY;
                    var shapesoffsetX = $('.polygon-wrap').offset().left;
                    var shapesoffsetY = $('.polygon-wrap').offset().top;
                    var polygonswidth = $('.polygon-wrap').width();
                    var polygonsheight = $('.polygon-wrap').height();
                    var shapesmouseX = mouseX - shapesoffsetX;
                    var shapesmouseY = mouseY - shapesoffsetY;
                    var mousepercentX = shapesmouseX / polygonswidth;
                    var mousepercentY = shapesmouseY / polygonsheight;
                    var finalmouseX = (mousepercentX) * 100;
                    var finalmouseY = (mousepercentY) * 100;
                    var normalisedX = parseFloat(finalmouseX).toFixed(3);
                    var normalisedY = parseFloat(finalmouseY).toFixed(3);
                    nodecount = nodecount + 1;
                    if (nodecount < 3) {
                        nodescss = nodescss + normalisedX + '% ' + normalisedY + '% ,';
                    } else
                    if (nodecount == 3) {
                        nodescss = nodescss + normalisedX + '% ' + normalisedY + '% );';
                        alert(nodescss);
                        console.log(nodescss);
                        nodescss = '-webkit-clip-path: polygon( ';
                        nodecount = 0;
                    }
                });
            </script>
    </body>

</html>

draw-demo.html用於獲取鼠標點擊三個點形成的相對位置座標用於畫三角形,例如-webkit-clip-path : polygon(67.3% 25.143%, 68.2% 20.143%, 71.3% 32.714%);

需要注意的是需要畫其他多邊形的話要將if (nodecount == 3)修改成你需要的值,如果是四邊形就改成if (nodecount == 4)

draw-demo.html的相對座標是相對於polygon-wrap這個class的而species-in-pieces.html是相對於show-stage這個id, 不同的參照物得到的相對座標是不一樣的


在這裏插入圖片描述
當然也有不少問題,點擊的精確度並不如預想,圖形繪製有間隙,只能通過微調讓它對齊,這十分考驗人的耐心。


特殊邊框的按鈕

在這裏插入圖片描述

像上面這種按鈕,實際上是通過元素背景配合僞元素實現的,具體代碼如下:

    .btn {
        height: 54px;
        width: 54px;
        border-radius: 50%;
        background: (背景圖);
        &::after {
            content: "";
            position: absolute;
            top: 5px;
            left: 5px;
            width: 44px;
            height: 44px;
            background-color: #64d6e2;
            border-radius: 100px;
        }
    }

通過這種方式,在元素內部創建僞元素定位遮蓋該元素背景圖,就能達到圖中的效果。 而 hover 邊框變寬,實際上是給元素加了 transfrom:scale屬性,讓元素略微放大,僞元素略微縮小。

動物的微動

動物在運動的時候,非常的細膩,不止一個地方在運動,有時會交替運動,顯得十分生動。探究其原理,是類名控制,這就需要設置一個不斷循環的定時器,而且要在幾個狀態間反覆切換。代碼如下:

    setInterval(() => {
          b.removeClass("state3");
          setTimeout(() => {
            b.addClass("state1");
          }, 1000);
          setTimeout(() => {
            b.removeClass("state1").addClass("state2");
          }, 2500);
          setTimeout(() => {
            b.removeClass("state2").addClass("state3");
          }, 3500)
        }, 5000)

通過 interval 嵌套 timeout 的方式達到微動狀態間的切換,每個類名對應每個動物的不同微動狀態。第二種微動狀態也如上代碼,大同小異,這裏不做贅述。

動物碎片的閃爍

動物展示的時候會發現,碎片有閃爍的效果,這是通過僞元素實現的。創建一個 100% 寬高的僞元素,添加一個 animation,讓其有一個透明度的變化,達到相當於遮罩層的閃爍。通過 scss 循環,可以方便的設定動畫執行延遲。代碼如下:

    .pieces{
       content: "";
       display: block;
       width: 100%;
       height: 100%;
       animation: shimmer .8s forwards;
    }
    @keyframes shimmer {
      0% {
        background-color: rgba(255,255,255,0);
      }
      35% {
        background-color: rgba(255,255,255,.1);
      }
      100% {
        background-color: rgba(255,255,255,0);
      }
    }

項目代碼

  • 完整代碼地址

    https://github.com/keginx/species-in-pieces

  • 項目結構

    species-in-pieces# tree
    .
    ├── assets
    │   ├── audio  音頻文件
    │   │   ├── ambient-loop-piano.mp3
    │   │   ├── hover_ui.mp3
    │   │   ├── none.mp3
    │   │   └── smash.mp3
    │   ├── css   網頁css文件
    │   │   └── main.css
    │   ├── fonts  動畫特效用到的字體
    │   │   ├── blocextcond.ttf
    │   │   └── blocextcond.woff
    │   ├── img  圖片文件
    │   │   ├── 1366x768_vaquita.png
    │   │   ├── svg  可縮放矢量圖形
    │   │   │   ├── awwwards.svg
    │   │   │   └── fwa.svg
    │   │   └── wallpapers   所有壁紙圖片
    │   │       ├── 1024x1024
    │   │       ├── 1366x768
    │   │       ├── 1920x1080
    │   │       ├── 2560x1600
    │   │       └── all-animals
    │   └── js
    │       ├── jquery-3.js   jquery庫
    │       ├── main.js		主要js文件
    │       └── soundmanager2.min.js  聲音控制需要的庫文件
    ├── draw-demo.html 用於獲取鼠標後形成的多邊形座標的demo
    ├── README.md
    └── species-in-pieces.html		主頁
    

    assets/css /main,css 是作品動畫實現需要用到的樣式文件
    assets/js/main.js 是存放自定義函數的主要js文件


參考

1. http://species-in-pieces.com
2. https://www.miaov.com/index.php/news/newsDetail/nid/152
3. http://project.microbu.com/161114/dongwu/
4. https://www.webhek.com/post/species-in-pieces.html
5. https://www.techug.com/post/species-in-pieces.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章