乐趣区

关于前端:世界杯火热进行中-用一个div画个足球场助助兴

四年一度的世界杯正在炽热进行中,有没有熬夜看你喜爱的队伍较量呢。在这欢庆的气氛中,我决定用代码参加一把世界杯,擦边参加,那就是用 CSS 画一个足球场,失常的用 CSS 布局必定是十分 easy 的,所以决定只用一个 div 实现,接下来开始注释。

足球场的尺寸

画之前首先要获取几个要害地位的尺寸,查问度娘的后果如下:

  • 场地:长 105 米,宽 68 米;
  • 球门:长 7.32 米,高 2.44 米;
  • 大禁区(罚球区):长 40.32 米,宽 16.5 米;
  • 小禁区(球门区):长 18.32 米,宽 5.5 米
  • 中圈区:半径 9.15 米;
  • 角球去:半径 1 米;
  • 罚球弧:半径 9.15 的半圆

基于这份数据定义一些根本的变量,本次实现基于下面的值乘以 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: 2px solid var(--lineColor);
}

接下来开始画核心局部的圆圈,因为只应用一个 div,所以将大量应用 CSS 突变实现各种线条局部内容,这里须要留神的中央是有倒影的应用代码上只须要画出半圆,所以要减少 no-repeat 防止在左侧绘制出另一半圆。

radial-gradient(
  circle,
  #0000 var(--centerCircle) 0,
  var(--lineColor) calc(var(--centerCircle)),
  var(--lineColor) calc(var(--centerCircle) + 2px),
  #0000 calc(var(--centerCircle) + 2px)
) no-repeat calc(var(--fieldWidth) / 4) 50% / 100% 100%

而后绘制四个角落的角球区域圆圈,高低两个角球局部须要离开绘制,外围代码都是一样,只是 background-position 的地位不一样。

// 下面角球 1/4 圆
radial-gradient(
  circle, 
  #0000 var(--cornerCircle),
  var(--lineColor) calc(var(--cornerCircle)),
  var(--lineColor) calc(var(--cornerCircle) + 2px),
  #0000 calc(var(--cornerCircle) + 2px)
) no-repeat calc(var(--fieldWidth) / 4 * -1) calc(var(--fieldHeight) / 2 * -1) / 100%

而后绘制大禁区局部,这部分实质是一个矩形,然而右边线条和底部的线条是重合的,所以还须要绘制残余的三根线条,这里为了缩小一部分代码,其中两条线应用 conic-gradient 绘制,残余的一条线应用 linear-gradient 绘制。

conic-gradient(
  from -90deg at right 2px bottom 2px,
   rgba(31, 157, 161, 0) 0 90deg,#fff 0) 0 calc((var(--fieldHeight) - var(--grandForbiddenAreaHeight)) / 2)/var(--grandForbiddenAreaWidth) var(--grandForbiddenAreaHeight) no-repeat,
linear-gradient(
  0deg,
  var(--lineColor) 2px,
  #0000 2px
) 0px calc((var(--fieldHeight) - var(--grandForbiddenAreaHeight)) / 2)/var(--grandForbiddenAreaWidth) 2px no-repeat

小禁区和大禁区实现形式是一样的,只是在于区域的大小尺寸不一样,减少两个禁区后的成果如下:

接下来绘制罚球弧,这个是一条圆弧,貌似突变不能单纯的只绘制一条弧线,如果有晓得的欢送交换,这里应用伪元素实现,基于伪元素的边框加圆角并暗藏其中的三边边框即可达到冀望的成果。

&::after {
  ...
  border: 2px solid #fff;
  border-radius: 50%;
  background: #0000;
  border-top-color: #0000;
  border-left-color: #0000;
  border-bottom-color: #0000;
}

此时的根本效果图曾经差不多了,再应用另外一个伪元素绘制一下球门的地位。

最初再减少一下球场内的草坪成果。这里应用了反复线性突变,代码如下:

repeating-linear-gradient(
  90deg,
  #56a224 0px,
  #56a224 10px, 
  #a9da27 10px, 
  #a9da27 20px
)

最初残缺的效果图如下:

在线代码:https://code.juejin.cn/pen/71…

最初

残缺的实现过程就完结了,这只是一种实现的思路,在理论的我的项目中不倡议应用,除此之外也还有很多其余的实现形式,欢送探讨你的实现形式。看完感觉有用记得点个赞再走,珍藏起来说不定哪天就用上啦~

专一前端开发,分享前端相干技术干货,公众号:南城大前端(ID: nanchengfe)

退出移动版