学了一段时间的svg,正好快要元宵节了,就用svg实现了一幅兔子逛花灯的图。
红色圆灯笼
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)的位置得到。左侧的两片粉色花瓣是同样的方式,先旋转再平移,旋转和平移的角度不同。
2、通过对左侧粉色花瓣组复制、翻转、平移得到右侧花瓣。
scale()实现缩放,当参数为-1时可以实现翻转,翻转之后的图形会翻转至-x轴,需要再平移至对应的位置。
展开查看完整代码
<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>
灯笼颜色
给灯笼设置不同的填充色
灯笼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>
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图片
在灯笼中组件的代码中加上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>