今天小編為大家帶來的是社區作者 南城FE的文章,讓我們一起來學習用一個div畫個足球場。
四年一度的世界盃正在火熱進行中,有沒有熬夜看你喜歡的隊伍比賽呢。在這歡慶的氛圍中,我決定用代碼參與一把世界盃,擦邊參與,那就是用CSS畫一個足球場,正常的用CSS布局肯定是非常easy的,所以決定只用一個div完成,接下來開始正文。
足球場的尺寸
畫之前首先要獲取幾個關鍵位置的尺寸,查詢度娘的結果如下:
基於這份數據定義一些基本的變量,本次實現基於上面的值乘以2作為像素值,部分小區域數值有所調整。整體變量定義如下:
:root{--lineColor:#fff;--fieldWidth:210px;--fieldHeight:136px;--centerCircle:18px;--cornerCircle:4px;--grandForbiddenAreaWidth:32px;--grandForbiddenAreaHeight:80px;--smallRestrictedAreaWidth:11px;--smallRestrictedAreaHeight:36px;--goalWidth:4px;--goalHeight:14px;}CSS倒影
這裡用到了CSS倒影 box-reflect,因為只能用一個div,所以要儘可能利用現有的CSS能力,減少額外的代碼量。足球場本質是一個對稱圖形,在這裡使用CSS倒影就很合適,如果不考慮只用一個div,還可以多次使用倒影。本次CSS邏輯只實現內容左側部分,右側內容由 box-reflect 倒影實現。
-webkit-box-reflect:right;實現過程
首先增加邊框部分,本文所有的線條都是按2px實現。
div{width:calc(var(--fieldWidth)/2);height:var(--fieldHeight);border:2pxsolidvar(--lineColor);}
接下來開始畫中心部分的圓圈,因為只使用一個div,所以將大量使用CSS漸變實現各種線條部分內容,這裡需要注意的地方是有倒影的使用代碼上只需要畫出半圓,所以要增加 no-repeat 避免在左側繪製出另一半圓。
radial-gradient(circle,#0000var(--centerCircle)0,var(--lineColor)calc(var(--centerCircle)),var(--lineColor)calc(var(--centerCircle)+2px),#0000calc(var(--centerCircle)+2px))no-repeatcalc(var(--fieldWidth)/4)50%/100%100%
然後繪製四個角落的角球區域圓圈,上下兩個角球部分需要分開繪製,核心代碼都是一樣,只是 background-position 的位置不一樣。
//上面角球1/4圓radial-gradient(circle,#0000var(--cornerCircle),var(--lineColor)calc(var(--cornerCircle)),var(--lineColor)calc(var(--cornerCircle)+2px),#0000calc(var(--cornerCircle)+2px))no-repeatcalc(var(--fieldWidth)/4*-1)calc(var(--fieldHeight)/2*-1)/100%
然後繪製大禁區部分,這部分本質是一個矩形,但是左邊線條和底部的線條是重合的,所以還需要繪製剩餘的三根線條,這裡為了減少一部分代碼,其中兩條線使用 conic-gradient 繪製,剩餘的一條線使用 linear-gradient 繪製。
小禁區和大禁區實現方式是一樣的,只是在於區域的大小尺寸不一樣,增加兩個禁區後的效果如下:conic-gradient(from-90degatright2pxbottom2px,rgba(31,157,161,0)090deg,#fff0)0calc((var(--fieldHeight)-var(--grandForbiddenAreaHeight))/2)/var(--grandForbiddenAreaWidth)var(--grandForbiddenAreaHeight)no-repeat,linear-gradient(0deg,var(--lineColor)2px,#00002px)0pxcalc((var(--fieldHeight)-var(--grandForbiddenAreaHeight))/2)/var(--grandForbiddenAreaWidth)2pxno-repeat
接下來繪製罰球弧,這個是一條圓弧,貌似漸變不能單純的只繪製一條弧線,如果有知道的歡迎交流,這裡使用偽元素實現,基於偽元素的邊框加圓角並隱藏其中的三邊邊框即可達到期望的效果。
&::after{...border:2pxsolid#fff;border-radius:50%;background:#0000;border-top-color:#0000;border-left-color:#0000;border-bottom-color:#0000;}
此時的基本效果圖已經差不多了,再使用另外一個偽元素繪製一下球門的位置。

最後再增加一下球場內的草坪效果。這裡使用了重複線性漸變,代碼如下:
repeating-linear-gradient(90deg,#56a2240px,#56a22410px,#a9da2710px,#a9da2720px)最後完整的效果圖如下:在線代碼:https://code.juejin.cn/pen/7171244744473853991
最後
完整的實現過程就結束了,這只是一種實現的思路,在實際的項目中不建議使用,除此之外也還有很多其他的實現方式,歡迎討論你的實現方式。看完覺得有用記得點個讚再走,收藏起來說不定哪天就用上啦~
點擊左下角閱讀原文,到SegmentFault 思否社區和文章作者展開更多互動和交流,「公眾號後台「回復「入群」即可加入我們的技術交流群,收穫更多的技術文章~