<sub id="rrh1b"><menuitem id="rrh1b"></menuitem></sub>

    <th id="rrh1b"><address id="rrh1b"><dfn id="rrh1b"></dfn></address></th><th id="rrh1b"></th>

    <th id="rrh1b"></th>

    <sub id="rrh1b"></sub>

        <sub id="rrh1b"><meter id="rrh1b"></meter></sub>
        <address id="rrh1b"><menuitem id="rrh1b"><font id="rrh1b"></font></menuitem></address>

          首页»HTML/CSS»用css绘制各种形状

          用css绘制各种形状

          来源:segmentfault 发布时间:2017-05-06 阅读次数:

           自适应的椭圆

            1.自适应的椭圆

            实现方式是通过border-radius这个属性;border-radius它可以单独指定水平和垂直半径。用 / ?#25351;?#36825;两个值。并且该属性的值不仅可以接受长度值,还能接收百?#30452;?#30340;值。百?#30452;?#30340;值会基于元素的尺寸进行解析,宽是水平半径的解析,高是垂直半径的解析。

            所以可以把两个半径的值都设置成50%;

          border-radius: 50% / 50%; 
          /* 值都是50% 就可以简化成 border-radius: 50%; */

            最终的效果:

            2.半椭圆的实现

            border-radius的值是可以分开设置?#27169;?#29992;空格进行分开,甚至可以为四个角提供完全不同的水平和垂直的半径。

            border-radius四个值的渲染顺序是从左上角开始,顺时针渲染;

            当只给定3个值时,第四个值和第二个相等;

            当给定两个值时,第三个值和第一个值相等,第四个值和第二个值相等。

            所以半椭圆的实现方法就是:

          border-radius: 50% / 100% 100% 0 0; 
          
          /*
           *  会解析成下面的样子
              border-top-left-radius: 50% 100%;
              border-top-right-radius: 50% 100%;
              border-bottom-right-radius: 50% 0px;
              border-bottom-left-radius: 50% 0px;
          */

            最终效果:

            同理的四?#31181;?#30340;椭圆的生成方法:

          /* 不能设置圆角的就设置成 0 */
          border-radius: 100% 0 0 0; 

            最终效果:

           平行四边形的实现

            在生成平行四边形时,直接对当前对div使用transform: skew(-45deg);变形,会导致div里面的内容?#19981;?#21457;生变形,就像下面这样:

            通用的解决办法是通过伪元素的方法,就?#21069;?#25152;有的样式用到伪元素上,对伪元素进行变形,由于内容不在伪元素里,所以内容不会受?#25509;?#21709;。具体的实现如下:

          <div class="parallelogram">
              click
          </div>
          .parallelogram {
              text-align: center;
              position: relative;
          }
          
          .parallelogram::before {
              transform: skew(-45deg);
              position: absolute;
              left: 0;
              right: 0;
              top: 0;
              bottom: 0;
              z-index: -1;
              content: ' ';
              background: #fb3;
          }

            生成的效果如下:

            这种技巧不仅对于skew()变形来说有用,还适用于其他任何变形样式,当想变形任何一个元素而不想改变它的内容的时候都可以用到它。

           菱形?#35745;?#30340;生成

            在css中,?#34892;?#38656;求是要把?#35745;?#35009;剪成菱形,使用css可以很好的解决这个问题,为不需要预先把?#35745;?#35009;剪成菱形而影响后期的维护。

          • 基于变形的方案

            直接使用类似平行四边形的方式旋转,给img设置max-width: 100%,会导致?#35745;?#34987;裁剪成八边形。因为100%会被解析成div的边长。所以解决这个问题的办法就是让?#35745;?#30340;宽等于div这个容器的对角线的长度,比较好的办法就?#21069;淹计?#29992;scale放大根号2倍(大概是1.42倍),具体实现的代码如下:

          <div class="picture">
              <img src="cat.jpg" />
          </div>
          .picture {
              width: 400px;
              height: 400px;
              transform: rotate(45deg);
              overflow: hidden;
          }
          
          .picture1 > img {
              max-width: 100%;
              height: 400px;
              transform: rotate(-45deg) scale(1.42);
          }

            效果如下:

            scale和width放大的区别:

            scale的缩放?#35745;?#26159;以它的?#34892;?#28857;进行缩放?#27169;?#22312;不指定transform-origin的前提下),通过width属性来放大?#35745;?#26102;,只会以它左上角的原点进行缩放,然后用额外的负边距来调整?#35745;?#30340;位置。

          • 裁切路径方案
            上面的办法还需要前套一层多余的html标签,使用clip-path这个属性,这个原本是svg的属性,使用polygon()这个多边形的函数,使用的百?#30452;?#30340;值会解析为元素自身的尺寸。

          img {
              clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
          }

            clip-path这个属性还能参与动画,只要动画是在同一个形状函数之间进行?#27169;?#32780;?#19994;?#30340;数量是相同的就可以,比如我们希望鼠标hover时?#20132;?#30340;扩展为完成的面积,只需这样:

          .picture {
              clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
              transition: 1s clip-path;
          }
          .picture:hover {
              clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
          }

           切脚效果的实现

          • 径向渐变的方式

            实现一个角被切掉的效果,可以使用渐变,渐变接受一个角度作为方向,并?#20197;?#35768;文字溢出并超出切角区域(因为它只是背景图案),具体实现如下:

          div {
            background: #58a;
            background: linear-gradient(-45deg, transparent 15px, #58a 0);
          }

            效果如下:

            实现两个切角的办法:

          div {
              width: 200px;
              height: 100px;
              background: #58a;
              background: linear-gradient(-45deg, transparent 15px, #58a 0) 
                          right, linear-gradient(45deg, transparent 15px, #65a 
                           0) left;
              background-size: 50% 100%;
              background-repeat: no-repeat;
          }

          效果如下:

            同理的四个切角的实现:

          div {
              width: 200px;
              height: 100px;
              background: #58a;
              background: linear-gradient(135deg, transparent 15px, #58a 0) top 
          left, linear-gradient(-135deg, transparent 15px, #58a 0) top right, linear-gradient(-45deg, transparent 15px, #58a 0) bottom right, linear-gradient(45deg, transparent 15px, #58a 0) bottom left;
              background-size: 50% 50%;
              background-repeat: no-repeat;
          }

            效果如下:

            上面的代码可维护比较差,在改变切角和颜色时都要修改多处,所以我们可以使用scss的mixin来写:

          @mixin beveled-corners($bg, $tl:0, $tr:$tl, $br:$tl, $bl:$tr) {
              background: $bg;
              background:
              linear-gradient(135deg, transparent $tl, $bg 0) top left,
              linear-gradient(225deg, transparent $tr, $bg 0) top right,
              linear-gradient(-45deg, transparent $br, $bg 0) bottom right,
              linear-gradient(45deg, transparent $bl, $bg 0) bottom left;
              background-size: 50% 50%;
              background-repeat: no-repeat;
          }
          

            调用时:

          @include beveled-corners(#58a, 15px, 5px);
          

            最后生成的效果是左上角和右下角是15px的切角,右上角和左下角是5px的切角。上面的minxin设置?#39034;?#20540;,当传入的值少于四个值时,就跟border-radius赋值一样。

            一样的?#35272;?#25105;?#19988;?#21487;以创建弧形切角,至少改成径向渐变

          div {
              width: 200px;
              height: 100px;
              background: #58a;
              background: radial-gradient(circle at top left, transparent 15px, #58a 0) top left, radial-gradient(circle at top right, transparent 15px, #58a 0) top right, radial-gradient(circle at bottom right, transparent 15px, #58a 0) bottom right, radial-gradient(circle at bottom left, transparent 15px, #58a 0) bottom left;
              background-size: 50% 50%;
              background-repeat: no-repeat;
          }

          效果如下:

          • 内联SVG与border-image的方式

            SVG 可以实现与尺寸完全无关的完美缩放,当文本溢出的时候,则会起到普通边框的作用,令文字折行。具体的实现如下:

          div {
            width: 200px;
            height: 100px;
            border: 15px solid transparent;
            border-image: 1 url('data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>');
          }

            效果如下:

            解决中间的背景色的填充可以给div块加一个和border一样的背景色:

          div {
              width: 200px;
              height: 100px;
              border: 15px solid transparent;
              border-image: 1 url(data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg" width="3" heigh="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>);
              background: #58a;
              background-clip: padding-box;
          }
          • 裁切路径方案
            CSS 裁切路径最神奇的地方在于我们可以同时使用百?#30452;?#25968;值(它会以元素自身的宽高作为基数度进行换算)和绝对长度值,从而提供巨大的灵活性。

            如果用裁切路径将一个元素切出20px大小的斜面切角,具体的代码如下:

          background: #58a;
          clip-path: polygon( 20px 0, calc(100% - 20px) 0, 100% 20px, 100% calc(100% - 20px), calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 20px), 0 20px);

            这个方法最大的好处:可以使用任意类型的背景,甚至可以对替换元素(比如?#35745;?#36827;行裁切,并且支持动画效果。

            缺点:当内边距?#36824;?#23485;时,它会裁切掉文本。

           梯形标签页的实现

            梯形的实现可以通过

          div {
              position: relative;
              display: inline-block;
              padding: .5em 1em .35em;
              color: white;
          }
          
          div::before {
              content: '';
              position: absolute;
              top: 0;
              right: 0;
              bottom: 0;
              left: 0;
              z-index: -1;
              background: #58a;
              transform: scaleY(1.3) perspective(.5em) rotateX(5deg);
              transform-origin: bottom;
          }

            效果如下:

            变形效果会让这个元素以它自身的?#34892;?#32447;为轴进行空间上的旋转,这会让它的尺寸很难控制,解决办法可以设置transform-origin:bottom;,当它在3D空间?#34892;?#36716;时,把它的底边固定。固定底边的同时,高度的缩水会变得更加显眼。为了解决这个问题,可以通过变形属性(scaleY())来改变它的尺寸。

            同样的方法可以实现下面这种tab布局:

            具体代码如下:

          nav > a {
              position: relative;
              display: inline-block;
              padding: .3em 1em 0;
          }
          nav > a::before {
              content: '';
              position: absolute;
              top: 0; right: 0; bottom: 0; left: 0;
              z-index: -1;
              background: #ccc;
              background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,0));
              border: 1px solid rgba(0,0,0,.4);
              border-bottom: none;
              border-radius: .5em .5em 0 0;
              box-shadow: 0 .15em white inset;
              transform: perspective(.5em) rotateX(5deg);
              transform-origin: bottom;
          }

            通过把transform-origin改成bottom left或bottom right,就可以立即得到左侧倾?#34987;蠐也?#20542;斜的标签页。

            这个方法的缺点是:斜边的角度?#35272;?#20110;元素的宽度。不过,对于宽度变化不大的多个元素(比如导航菜单)来说,这个方法还是非常管用的。

           简单的饼图的绘制

            思路?#21069;言?#24418;的左右两部?#31181;?#23450;为上述两种颜色,然后用伪元素覆?#24039;先ィ?#36890;过旋转来决定露出多大的扇区。

            具体的代码如下:

          .pie {
              width: 100px;
              height: 100px;
              border-radius: 50%;
              background: yellowgreen;
              background-image: linear-gradient(to right, transparent 50%, #655 0);
              
          .pie::before {
              content: '';
              display: block;
              margin-left: 50%;
              height: 100%;
              border-radius: 0 100% 100% 0 / 50%;
              background-color: inherit;
              transform-origin: left;
          }

            实现的效果如下:

            这种方?#20132;?#25903;持动画,就可以用CSS动画来实现一个饼图从0 变化到100% 的动画,从而得到一个炫酷的进度指示器:

          @keyframes spin {
              to { transform: rotate(.5turn); }
          }
          @keyframes bg {
              50% { background: #655; }
          }
          .pie::before {
              content: '';
              display: block;
              margin-left: 50%;
              height: 100%;
              border-radius: 0 100% 100% 0 / 50%;
              background-color: inherit;
              transform-origin: left;
              animation: spin 3s linear infinite, bg 6s step-end infinite;
          }

            生成多个不同比率的静态饼图的办法,可以通过上面的那个动画的实现,需要设置动画处于暂停状态,然后设置负的动画延时直接跳转到动画中的任意时间点, 最终实现的代码如下:

          <div class="pie" style="animation-delay: -20s">
              <span>20</span>
          </div>
          <div class="pie" style="animation-delay: -60s">
              <span>60</span>
          </div>
          .pie{
              position: relative;
              width: 100px;
              height: 100px;
              line-height: 100px;
              border-radius: 50%;
              background: yellowgreen;
              background-image: linear-gradient(to right, transparent 50%, #655 0);
              color: #000;
              text-align: center;
          }
          
          @keyframes spin {
              to { transform: rotate(.5turn); }
          }
          @keyframes bg {
              50% { background: #655; }
          }
          
          .pie::before {
              content: '';
              position: absolute;
              top: 0; left: 50%;
              width: 50%; height: 100%;
              border-radius: 0 100% 100% 0 / 50%;
              background-color: inherit;
              transform-origin: left;
              animation: spin 50s linear infinite, bg 100s step-end infinite;
              animation-play-state: paused;
              animation-delay: inherit;
          }
          .pie span {
              position: relative;
              z-index: 10;
          }

            效果如下:

           用SVG 解决方案

          <svg viewBox="0 0 32 32">
              <circle r="16" cx="16" cy="16" />
          </svg>
          svg {
              width: 100px; 
              height: 100px;
              transform: rotate(-90deg);
              background: yellowgreen;
              border-radius: 50%;
          }
          circle {
              fill: yellowgreen;
              stroke: #655;
              stroke-width: 32;
              stroke-dasharray: 38 100; /* 可得到比率为38%的扇区 */
          }
          

            让饼图的周长无限接近100,就可以直接把比率的百?#30452;?#20540;指定为strokedasharray的长度,不需要做任何计算了。因为周长是2πr,半径就是100/22π ≈ 15.915,最终把这个?#31561;?#25972;为16。在SVG的viewBox属性中指定其尺寸,而不再使用width和height属性,这样就可以让它自动适应容器的大小了。

            SVG的优点是?增加第三种颜色是非常容易?#27169;?#24182;且可以用内联样式来指定颜色。

          QQ群:WEB开发者官方群(515171538),验证消息:10000
          微信群:?#26377;?#32534;微信 849023636 邀请您加入,验证消息:10000
          提示:更多精彩内容关注微信公众号:全栈开发者?#34892;模╢sder-com)
          css
          网友评论(共0条评论) 正在载入评论......
          理智评论文明上网,拒绝恶意谩骂 发表评论 / 共0条评论
          登录会员?#34892;?/span>
          彩运

            <sub id="rrh1b"><menuitem id="rrh1b"></menuitem></sub>

            <th id="rrh1b"><address id="rrh1b"><dfn id="rrh1b"></dfn></address></th><th id="rrh1b"></th>

            <th id="rrh1b"></th>

            <sub id="rrh1b"></sub>

                <sub id="rrh1b"><meter id="rrh1b"></meter></sub>
                <address id="rrh1b"><menuitem id="rrh1b"><font id="rrh1b"></font></menuitem></address>

                    <sub id="rrh1b"><menuitem id="rrh1b"></menuitem></sub>

                    <th id="rrh1b"><address id="rrh1b"><dfn id="rrh1b"></dfn></address></th><th id="rrh1b"></th>

                    <th id="rrh1b"></th>

                    <sub id="rrh1b"></sub>

                        <sub id="rrh1b"><meter id="rrh1b"></meter></sub>
                        <address id="rrh1b"><menuitem id="rrh1b"><font id="rrh1b"></font></menuitem></address>

                          3d字谜 排列五走势图预测 中国足彩网注册送3元 十大电子游艺平台 山东11选5开奖结果 年香港六合彩五行 六合图库举世无双 十二生肖出特码 3d复式守号 江苏到北京 梅西总进球数600 黑龙江十一选五正好网 河北20选5好运三复式 极速快3吧 英文网球比分