svg实现小兔子逛灯会

407 阅读2分钟

学了一段时间的svg,正好快要元宵节了,就用svg实现了一幅兔子逛花灯的图。

红色圆灯笼

image.png

1、先画灯笼中间的主要区域。以a、b点先画半椭圆,然后b点到c点是直线,再画c点到d点半椭圆,闭合图形,填充红色

2、画灯笼中间的黄色灯架。先画三个半椭圆,然后填充色设置为透明

3、将三个半椭圆用g标签定义为一组,然后通过复制、旋转、平移得到右边的部分的黄色灯架线,中间的黄色点是旋转的参考点

4、其他部分实现比较简单就不具体说明。

展开查看完整代码

<template>
  <svg class="lantern-wrap color1">
      <defs>
          <!-- 左边三条线定义为一组,以便重复引用,旋转、平移-->
          <g id="lanternLine">
              <path d="M 105 30 A 60 60 0 0 0 105 160" class="lantern-line"/>
              <path d="M 120 30 A 40 60 0 0 0 120 160" class="lantern-line"/>
              <path d="M 135 30 A 20 60 0 0 0 135 160" class="lantern-line"/>
          </g>
          <g id="lanternTop">
              <path d="M 100 15 L 180 15, 180 40, 100 40 Z" class="lantern-top"/>
          </g>
          <!-- 顶部矩形渐变色 -->
          <linearGradient id="lanternTopColor" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0" stop-color="#dc8f03"/>
              <stop offset="0.2" stop-color="#ffa500"/>
              <stop offset="0.5" stop-color="#dc8f03"/>
              <stop offset="0.7" stop-color="#ffa500"/>
              <stop offset="1" stop-color="#dc8f03"/>
          </linearGradient>
      </defs>
      <svg>
          <!-- 灯笼顶部和底部-->
          <path d="M 140 -20 L 140 200" class="lantern-line" stroke-width="3px"/>
          <use xlink:href="#lanternTop"></use>
          <use xlink:href="#lanternTop" transform="translate(0 135)"></use>
          <!-- 灯笼主要区域 -->
          <path d="M 100 30 A 90 60 0 1 0 100 160 L 180 160 A 90 60 0 0 0 180 30 Z" class="lantern-circle"/>
          <!-- 灯笼中间的分隔线 -->
          <use xlink:href="#lanternLine"></use>
          <!-- 方案1:以原点为旋转的参考点,旋转之后平移到对应位置 -->
          <!-- <use :xlink:href="`#lanternLine${color}`" transform="rotate(180, 0, 0) translate(-270 -190)"></use>-->
          <!-- 方案2:以(135, 95)为旋转的参考点,旋转之后直接显示在对应位置 -->
          <use xlink:href="#lanternLine" transform="rotate(180, 135, 95)"></use>
          <!-- 灯穗 -->
          <rect x="132" y="197" width="16" height="80" class="lantern-lamp"/>
          <circle cx="140" cy="200" r="8" class="lamp-shade-circle"/>
      </svg>
  </svg>
</template>

<style lang="scss" scoped>
.lantern-wrap {
  width: 500px;
  height: 500px;
}

$lantern1-line: #ffa500;
$lantern1-circle: #dc8f03;
.color1 {
  .lantern-line {
      stroke: $lantern1-line;
      fill: transparent;
  }

  .lantern-top {
      stroke: $lantern1-line;
      fill: url(#lanternTopColor);
  }

  .lantern-circle {
      stroke: $lantern1-line;
      fill: red;
  }

  .lamp-shade-circle {
      fill: $lantern1-circle;
  }

  .lantern-lamp {
      fill: $lantern1-line;
  }
}
</style>
      

莲花灯笼

1、先画出一片水平花瓣,如图1中的黑色花瓣,也可以直接画垂直的花瓣,根据个人习惯。将黑色的水平花瓣用g标签包裹,用于后续复制。莲花正中间的花瓣,也就是图中的绿色花瓣是将水平花瓣以(100,100)为参考点旋转90度,然后再平移translate(100, -100)的位置得到。左侧的两片粉色花瓣是同样的方式,先旋转再平移,旋转和平移的角度不同。 微信图片_20230131204308.png 2、通过对左侧粉色花瓣组复制、翻转、平移得到右侧花瓣。 scale()实现缩放,当参数为-1时可以实现翻转,翻转之后的图形会翻转至-x轴,需要再平移至对应的位置。 微信图片_20230131204314.png

展开查看完整代码
<template>
  <svg class="lantern-wrap">
      <defs>
          <linearGradient id="lanternColor" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0" stop-color="#c43447"/>
              <stop offset="0.2" stop-color="#c43447"/>
              <stop offset="0.6" stop-color="#e47777"/>
              <stop offset="0.9" stop-color="#f8eaa0"/>
              <stop offset="1" stop-color="#fee93e"/>
          </linearGradient>
          <linearGradient id="lanternDarkColor" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0" stop-color="#c43447"/>
              <stop offset="0.1" stop-color="#c43447"/>
              <stop offset="0.5" stop-color="#f9f4ca"/>
          </linearGradient>
          <g id="petalItem">
  <!--                    <path d="M 0 100 L 90 150 160 100 L 90 50 0 100" stroke="red" fill="none"  stroke-dasharray="5"  stroke-width="2"/>-->
              <path d="M 0 100 Q 90 150 160 100 Q 90 50 0 100" stroke="#fca630" fill="url(#lanternColor)"/>
  <!--                    <path d="M 200 100 L 100 100" stroke="red" fill="none"  stroke-dasharray="5"  stroke-width="2"/>-->
  <!--                    <path d="M 100 100 L 100 200" stroke="blue" fill="none"  stroke-dasharray="5"  stroke-width="2"/>-->
          </g>
          <g id="petalGroup">
              <use xlink:href="#petalItem" transform="rotate(30, 100, 100) translate(107, 90)"></use>
              <use xlink:href="#petalItem" transform="rotate(60, 100, 100) translate(130, -5)"></use>
          </g>
          <g id="petalDark">
              <path d="M 0 100 Q 40 150 150 100 Q 40 50 0 100" stroke="#fca630" fill="url(#lanternDarkColor)"/>
          </g>
          <g id="petalDarkGroup">
              <use xlink:href="#petalDark" transform="rotate(48, 100, 100) translate(130, 40)"></use>
              <use xlink:href="#petalDark" transform="rotate(70, 100, 100) translate(130, -50)"></use>
          </g>
          </defs>
          <svg>
              <!-- 灯笼顶部-->
              <path d="M 190 70 L 190 150" class="top-line"/>
              <!-- 灯笼主要区域-->
              <use xlink:href="#petalDarkGroup" transform="translate(400, 0) scale(-1, 1)"></use>
              <use xlink:href="#petalDarkGroup"></use>
              <use xlink:href="#petalGroup" transform="translate(400, 0) scale(-1, 1)"></use>
              <use xlink:href="#petalGroup"></use>
              <use xlink:href="#petalItem" transform="rotate(90, 100, 100) translate(100, -100)"></use>
              <use xlink:href="#petalItem" transform="rotate(90, 100, 100) translate(100, -100)"></use>
              <!-- 灯笼底部-->
              <path d="M 160 260 L 160 270 240 270 240 260" fill="#bb95a3"/>
              <path d="M 193 282 L 188 353 203 350 206 282" fill="#a96295"/>
              <circle cx="200" cy="278" r="8" fill="#829ac2"/>
          </svg>
  </svg>
</template>

<style lang="scss" scoped>
.lantern-wrap {
  width: 500px;
  height: 500px;
}
</style>

      

灯笼颜色

给灯笼设置不同的填充色

image.png

灯笼1和灯笼2中间椭圆部分设置的渐变色,如下:

<linearGradient id="lantern1Color" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#e5020f"/>
    <stop offset="0.5" stop-color="#fde921"/>
    <stop offset="1" stop-color="#e5020f"/>
</linearGradient>
<linearGradient id="lantern2Color" x1="0%" y1="0%" x2="100%" y2="100%">
    <stop offset="0" stop-color="#d5221f"/>
    <stop offset="0.2" stop-color="#d92d23"/>
    <stop offset="0.5" stop-color="#e68862"/>
    <stop offset="0.7" stop-color="#d5221f"/>
</linearGradient>

image.png

5个莲花灯笼设置的渐变色,如下:

<!-- 灯笼1 黄色灯笼渐变色-->
<linearGradient id="lantern1Color" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#ffff78"/>
    <stop offset="0.5" stop-color="#ffff78"/>
    <stop offset="0.7" stop-color="#fbd425"/>
    <stop offset="0.8" stop-color="#feae12"/>
    <stop offset="1" stop-color="#fb6d11"/>
</linearGradient>
<linearGradient id="lantern1DarkColor" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#ffee2a"/>
    <stop offset="0.1" stop-color="#ffee2a"/>
    <stop offset="0.2" stop-color="#ffd420"/>
    <stop offset="0.3" stop-color="#fea914"/>
    <stop offset="1" stop-color="#fb6d11"/>
</linearGradient>
<!-- 灯笼2 玫红灯笼渐变色-->
<linearGradient id="lantern2Color" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#c43447"/>
    <stop offset="0.2" stop-color="#c43447"/>
    <stop offset="0.6" stop-color="#e47777"/>
    <stop offset="0.9" stop-color="#f8eaa0"/>
    <stop offset="1" stop-color="#fee93e"/>
</linearGradient>
<linearGradient id="lantern2DarkColor" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#c43447"/>
    <stop offset="0.1" stop-color="#c43447"/>
    <stop offset="0.5" stop-color="#f9f4ca"/>
</linearGradient>
<!-- 灯笼3 粉色灯笼渐变色-->
<linearGradient id="lantern3Color" x1="0%" y1="0%" x2="100%" y2="100%">
    <stop offset="0.3" stop-color="#fd6c59"/>
    <stop offset="0.6" stop-color="#fcb393"/>
    <stop offset="0.8" stop-color="#fae2c0"/>
</linearGradient>
<linearGradient id="lantern3DarkColor" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#fd6c59"/>
    <stop offset="0.3" stop-color="#fae2c0"/>
    <stop offset="0.8" stop-color="#fae2c0"/>
</linearGradient>
<!-- 灯笼4 蓝色灯笼渐变色-->
<linearGradient id="lantern4Color" x1="0%" y1="30%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#0427bc"/>
    <stop offset="0.4" stop-color="#0388ff"/>
    <stop offset="0.7" stop-color="#04eef8"/>
    <stop offset="1" stop-color="#fbfd47"/>
</linearGradient>
<linearGradient id="lantern4DarkColor" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#0427bc"/>
    <stop offset="0.4" stop-color="#04eef8"/>
    <stop offset="0.9" stop-color="#049ffe"/>
</linearGradient>
<!-- 灯笼5 紫色灯笼渐变色-->
<linearGradient id="lantern5Color" x1="0%" y1="30%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#f56ef0"/>
    <stop offset="0.4" stop-color="#f787db"/>
    <stop offset="0.8" stop-color="#d6cefd"/>
</linearGradient>
<linearGradient id="lantern5DarkColor" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0" stop-color="#eb59ce"/>
    <stop offset="0.4" stop-color="#d6cefd"/>
</linearGradient>

兔子

画兔子用到的知识点无非也是复制、平移、旋转,就直接上代码

<template>
    <svg class="rabbit-content">
        <defs>
            <g id="eyes">
                <path d="M 100 130 A 20 25 0 1 1 140 130" class="line-color transparent-bg" stroke-width="2"/>
            </g>
            <g id="rouge">
                <ellipse cx="120" cy="125" rx="15" ry="10" class="line-color rouge"/>
            </g>
            <g id="button">
                <path d="M 195 322 L 210 322" class="yellow" stroke-width="2"/>
                <path d="M 225 320 L 210 320" class="yellow" stroke-width="2"/>
                <circle cx="210" cy="320" r="4" class="button"/>
            </g>
            <linearGradient id="clothes" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0" stop-color="#bd2425"/>
                <stop offset="0.3" stop-color="#da281c"/>
                <stop offset="0.7" stop-color="#df3236"/>
                <stop offset="0.9" stop-color="#bd2425"/>
            </linearGradient>
            <linearGradient id="yellowButton" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0" stop-color="#f6e580"/>
                <stop offset="0.4" stop-color="#c39621"/>
                <stop offset="1" stop-color="#f6e580"/>
            </linearGradient>
            <linearGradient id="yellowClothes" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0" stop-color="#c39621"/>
                <stop offset="0.5" stop-color="#f6e580"/>
                <stop offset="0.7" stop-color="#f6e580"/>
                <stop offset="1" stop-color="#c39621"/>
            </linearGradient>
        </defs>
        <svg>
            <!-- 兔子耳朵-->
            <path d="M 135 130 A 20 75 0 1 1 169 115" class="line-color white-bg"/>
            <path d="M 145 125 A 12 45 0 1 1 160 117" class="line-color pink-bg"/>
            <path d="M 222 112 A 20 75 0 1 1 255 125" class="line-color white-bg"/>
            <path d="M 227 114 A 12 65 0 1 1 250 123" class="line-color pink-bg"/>
            <!-- 兔子衣服-->
            <path d="M 150 278 L 90 290 100 330 140 330 140 400 290 400 280 310 320 270 260 248 "
                  fill="#e9323a"
                  class="line-color clothes"
            />
            <!-- 兔子衣服扣子-->
            <path d="M 210 290 L 210 400" class="yellow" stroke-width="2"></path>
            <use xlink:href="#button" x="0" y="0"></use>
            <use xlink:href="#button" x="0" y="0" transform="translate(0, 30)"></use>
            <use xlink:href="#button" x="0" y="0" transform="translate(0, 60)"></use>
            <!-- 兔子衣服边边-->
            <path d="M 90 290 L 100 288 Q 110 310 110 330 L 100 330 Z" class="clothes-yellow"/>
            <path d="M 260 248 L 250 250 Q 270 264 312 278 L 320 270 Z" class="clothes-yellow"/>
            <path d="M 140 390 L 139 400 Q 210 413 290 400 L 289 390 Q 200 402 140 390" class="clothes-yellow"/>
            <!-- 兔子的头部-->
            <ellipse cx="200" cy="200" rx="100" ry="90" class="line-color white-bg"/>
            <!-- 兔子眼睛-->
            <use xlink:href="#eyes" x="60" y="70" transform="rotate(20, 240, 110)"></use>
            <use xlink:href="#eyes" x="60" y="70" transform="rotate(-25, 150, 50)"></use>
            <!-- 兔子腮红-->
            <use xlink:href="#rouge" x="0" y="0" transform="rotate(10, 170, 180) translate(10, 80)"></use>
            <use xlink:href="#rouge" x="0" y="0" transform="rotate(-10, 170, 180) translate(150, 90)"></use>
            <!-- 兔子嘴-->
            <path d="M 170 230 A 20 30 0 1 0 230 230" fill="#eb4a51" stroke="#7f7665" stroke-width="1"/>
            <!-- 兔子牙齿-->
            <path d="M 190 220 Q 190 250 200 245 L 200 234, 200 245 Q 210 250 210 220" fill="#fff" stroke="#7f7665" stroke-width="1"/>
            <path d="M 160 220 Q 185 250 200 225 Q 220 250 235 220" fill="#fff" stroke="#7f7665" stroke-width="1"/>
            <!-- 兔子舌头-->
            <path d="M 182 267 A 20 10 0 1 1 218 267 Q 200 284 182 267" class="line-color pink-bg" stroke-width="1"/>
            <!-- 兔子手-->
            <!-- <path d="M 90 292 L 50 300 50 330 99 328 " fill="transparent" stroke="red" stroke-width="1"/>-->
            <!--<path d="M 280 254 L 310 233 340 240 317 269 " fill="transparent" stroke="red" stroke-width="1"/>-->
            <path d="M 90 292 C 50 300 50 330 99 328" class="line-color white-bg"/>
            <path d="M 280 254 C 310 230 340 240 317 269" class="line-color white-bg"/>
            <!-- 兔子腿-->
            <!--                <path d="M 160 403 L 130 480 195 480 198 406" fill="transparent" stroke="red" stroke-width="1"/>-->
            <!--                <path d="M 220 406 L 210 480 270 480 256 404" fill="transparent" stroke="red" stroke-width="1"/>-->
            <path d="M 160 403 C 130 480 195 480 198 406" class="line-color white-bg"/>
            <path d="M 220 406 C 210 480 270 480 256 404" class="line-color white-bg"/>
        </svg>
    </svg>
</template>

<style lang="scss" scoped>
    .rabbit-content {
        width: 500px;
        height: 500px;
    }
    .rabbit-header {
        stroke: black;
        fill: transparent;
    }

    .line-color {
        stroke: #7f7665;
        stroke-width: 1;
    }

    .white-bg {
        fill: white;
    }

    .transparent-bg {
        fill: transparent;
    }

    .pink-bg {
        fill: #faa5a0;
        stroke: #faa5a0;
    }

    .yellow {
        fill: #f3e075;
        stroke: #f3e075;
    }

    .clothes {
        fill: url(#clothes);
    }

    .button {
        fill: url(#yellowButton);
    }

    .clothes-yellow {
        fill: url(#yellowClothes);
        stroke: #7f7665;
    }

    .rouge {
        fill: #f3bcb6;
        stroke: #f3bcb6;
    }
</style>

放大缩小svg图片

image.png

在灯笼中组件的代码中加上viewBox


<template>
    <svg class="lantern-wrap" :viewBox="viewBox">
    <!-- 此处同红灯笼处的代码相同,省略-->
</template>
<script setup>
import {computed, defineProps} from 'vue';

const props = defineProps({
    width: {
        type: Number,
        default: 300
    },
    height: {
        type: Number,
        default: 320
    }
});
    const viewBox = computed(() => `0 0 ${props.width} ${props.height}`);
 </script>   

将灯笼组件引入Index文件中

<template>
    <div class="page-wrap">
        <div class="lantern-content">
            <lantern></lantern>
        </div>
        <div class="lantern-content2">
            <lantern></lantern>
        </div>
    </div>
</template>

<script setup>
import Lantern from '../components/Lantern'
</script>

<style lang="scss" scoped>
.page-wrap {
    width: 800px;
    height: 500px;
    margin: 50px auto;
    display: flex;
}
/*设置灯笼的大小*/
.lantern-content {
    width: 200px;
    height: 200px;
}
/*设置灯笼的大小*/
.lantern-content2 {
    width: 150px;
    height: 150px;
}
</style>