介紹
該作品原本是阿姆斯特丹設計師 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);
}
}
項目代碼
-
完整代碼地址
-
項目結構
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