SVG修饰属性
SVG修饰属性
@jarringslee
文章目录
- SVG修饰属性
- SVG描边属性
- 小案例: 为图标添加鼠标经过的描边动画
- 小案例 绘制线条爱心效果
- 小案例:模仿OPPO AI里程碑效果
- SVG模糊和阴影效果
- SVG线性渐变和径向渐变
- clip-path 裁剪
SVG描边属性
基本属性:
属性 | 描述 | 取值示例 |
---|---|---|
stroke 笔画属性 | 定义描边颜色(支持颜色值、渐变、图案) | stroke:#fo0; |
stroke-width 笔画宽度属性 | 描边宽度(支持像素、百分比、px、em等单位) | stroke-width: 2px; |
stroke-linecap 笔画笔帽属性 | 定义描边线段两边的线头形状 | butt(无线帽)、round(圆形线帽)、square(方形线帽) |
stroke-dasharray | 虚线模式(实线长度+间隔长度) | stroke-dasharray: 10 ; |
stroke-dashoffset | 调整虚线与间隔的起始位置 | stroke-dashoffset: 100; |
stroke-opacity | 描边颜色的不透明度 | 0(完全透明) ~ 1(完全不透明) |
stroke-dasharray 虚线笔画属性可以定义一个或多个数字 调整虚线属性,实现和虚线的间隔值。
-
stroke-dasharray:100;
默认px,实现和虚线间隔都是100 -
stroke-dasharray:100 50;
100px是实线长度,50px是实现间隔(虚线长度) -
stroke-dasharray:100 50 5 10 10 5;
分别为实线和虚线交替的长度
stroke-dasharray的应用 鼠标经过添加描边动画效果
- 使用@keyframes创造动画效果:设置两个(0% 100%)或多个关键帧的不同虚线模式的数值
- 使用:hover为svg添加该动画效果。
stroke-dashoffset 用于调整虚线模式的起始偏移量。增大该属性能让虚线模式向路径起点移动,视觉上像线条被擦除。
stroke-dashoffset的应用 鼠标经过添加描边动画效果 做法同上
描边属性小练习:
<svg width="300" height="80"><g fill="none" stroke="black" stroke-width="6"><path stroke-linecap="butt" d="M5 20 l215 0" /><path stroke-linecap="round" d="M5 40 l215 0" /><path stroke-linecap="square" d="M5 60 l215 0" /></g></svg><br><svg width="300" height="80"><g fill="none" stroke="black" stroke-width="4"><path stroke-dasharray="5,5" d="M5 20 l215 0" /><path stroke-dasharray="10,10" d="M5 40 l215 0" /><path stroke-dasharray="20,10,5,5,5,10" d="M5 60 l215 0" /></g></svg>
小案例: 为图标添加鼠标经过的描边动画
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>SVG常见属性以及描边效果</title><style>svg {/* 以下属性全都有“none”属性值 *//*填充颜色 */fill: red;/* 描边颜色 */stroke: blue;/* 描边宽度 */stroke-width: 10px;/* 描边虚线属性 */stroke-dasharray: 400;/* 描边起始位置偏移量 */stroke-dashoffset: none;}/* 创造动画效果 */@keyframes move1 {0% {stroke-dasharray: 0 100;}40% {stroke-dasharray: 100 0;}100% {stroke-dasharray: 100 50;}}/* 鼠标悬停时添加动画效果 */#svg1:hover {animation: move1 1.5s;}@keyframes move2 {0% {stroke-dashoffset: none;}50% {stroke-dashoffset: 1000;}100% {stroke-dashoffset: none;}}#svg2:hover {animation: move2 3.5s;}</style>
</head><body><svg id="svg1" class="icon" width="200px" height="200px" viewBox="0 0 1024 1024" version="1.1"xmlns="http://www.w3.org/2000/svg"><pathd="M512 928A416 416 0 1 1 928 512 416 416 0 0 1 512 928z m0-768A352 352 0 1 0 864 512 352 352 0 0 0 512 160z m192 448H512a32 32 0 0 1-32-32V320a32 32 0 0 1 64 0v224H704a32 32 0 0 1 0 64z" /><!--如果想写死一个属性就直接加到html标签中。比如 <pathd="......" fill="#333333" />; css再高的权重也无法触及。 --></svg><svg id="svg1" t="1760535574940" class="icon" viewBox="0 0 1024 1024" version="1.1"xmlns="http://www.w3.org/2000/svg" p-id="1292" xmlns:xlink="http://www.w3.org/1999/xlink" width="200"height="200"><pathd="M78.215823 160.016004v469.294938c0 23.618362 19.137914 42.69227 42.69227 42.692269H200.980101l65.734575 65.734575c16.641664 16.641664 43.716372 16.641664 60.358037 0l65.734574-65.734575h37.443745v113.803383c0 23.554356 19.073908 42.628264 42.628264 42.628263h197.459749l46.148616 46.212622a42.69227 42.69227 0 0 0 60.358036 0l46.148616-46.212622h80.136015a42.69227 42.69227 0 0 0 42.628264-42.628263V472.879296a42.69227 42.69227 0 0 0-42.628264-42.628264h-113.803382V160.016004a42.69227 42.69227 0 0 0-42.628264-42.69227H120.908093a42.69227 42.69227 0 0 0-42.69227 42.69227z m140.430045 426.666674h-55.045505v-384.03841h540.406049v384.03841H375.14152a42.69227 42.69227 0 0 0-30.211021 12.481248l-48.004802 48.004802-48.068807-48.004802a42.69227 42.69227 0 0 0-30.211022-12.481248z m469.358944 156.431646H515.571566V672.067218h231.06311a42.69227 42.69227 0 0 0 42.69227-42.69227V515.571566h71.111112v227.542758h-55.045505a42.69227 42.69227 0 0 0-30.211022 12.481248l-28.482849 28.546855-28.546855-28.546855a42.69227 42.69227 0 0 0-30.147015-12.481248z"p-id="1293"></path><pathd="M234.647469 316.44765c0 23.554356 19.137914 42.69227 42.69227 42.69227h234.647468a42.69227 42.69227 0 0 0 0-85.38454H277.339739a42.69227 42.69227 0 0 0-42.69227 42.69227z m0 156.431646c0 23.554356 19.137914 42.69227 42.69227 42.69227h117.323734a42.69227 42.69227 0 0 0 0-85.320534H277.339739a42.69227 42.69227 0 0 0-42.69227 42.628264z"p-id="1294"></path></svg><div></div><svg id="svg2" class="icon" width="200px" height="200px" viewBox="0 0 1024 1024" version="1.1"xmlns="http://www.w3.org/2000/svg"><pathd="M512 928A416 416 0 1 1 928 512 416 416 0 0 1 512 928z m0-768A352 352 0 1 0 864 512 352 352 0 0 0 512 160z m192 448H512a32 32 0 0 1-32-32V320a32 32 0 0 1 64 0v224H704a32 32 0 0 1 0 64z" /><!--如果想写死一个属性就直接加到html标签中。比如 <pathd="......" fill="#333333" />; css再高的权重也无法触及。 --></svg><svg id="svg2" t="1760535574940" class="icon" viewBox="0 0 1024 1024" version="1.1"xmlns="http://www.w3.org/2000/svg" p-id="1292" xmlns:xlink="http://www.w3.org/1999/xlink" width="200"height="200"><pathd="M78.215823 160.016004v469.294938c0 23.618362 19.137914 42.69227 42.69227 42.692269H200.980101l65.734575 65.734575c16.641664 16.641664 43.716372 16.641664 60.358037 0l65.734574-65.734575h37.443745v113.803383c0 23.554356 19.073908 42.628264 42.628264 42.628263h197.459749l46.148616 46.212622a42.69227 42.69227 0 0 0 60.358036 0l46.148616-46.212622h80.136015a42.69227 42.69227 0 0 0 42.628264-42.628263V472.879296a42.69227 42.69227 0 0 0-42.628264-42.628264h-113.803382V160.016004a42.69227 42.69227 0 0 0-42.628264-42.69227H120.908093a42.69227 42.69227 0 0 0-42.69227 42.69227z m140.430045 426.666674h-55.045505v-384.03841h540.406049v384.03841H375.14152a42.69227 42.69227 0 0 0-30.211021 12.481248l-48.004802 48.004802-48.068807-48.004802a42.69227 42.69227 0 0 0-30.211022-12.481248z m469.358944 156.431646H515.571566V672.067218h231.06311a42.69227 42.69227 0 0 0 42.69227-42.69227V515.571566h71.111112v227.542758h-55.045505a42.69227 42.69227 0 0 0-30.211022 12.481248l-28.482849 28.546855-28.546855-28.546855a42.69227 42.69227 0 0 0-30.147015-12.481248z"p-id="1293"></path><pathd="M234.647469 316.44765c0 23.554356 19.137914 42.69227 42.69227 42.69227h234.647468a42.69227 42.69227 0 0 0 0-85.38454H277.339739a42.69227 42.69227 0 0 0-42.69227 42.69227z m0 156.431646c0 23.554356 19.137914 42.69227 42.69227 42.69227h117.323734a42.69227 42.69227 0 0 0 0-85.320534H277.339739a42.69227 42.69227 0 0 0-42.69227 42.628264z"p-id="1294"></path></svg>
</body></html>
小案例 绘制线条爱心效果
- 下载一个爱心图案并设置为透明( fill 通过 css 设置为 none );
- 利用 stroke 和 stroke-width 属性为图案绘制边框;
- 获取图案总长度: 在 path 标签中设置 id(如 id=“heart”),在控制台中利用js指令
heart.getTotalLength()
来获取爱心描边的总长度(可截取整数 如2616.08251953125 → 2616) - **通过css设置起始效果: **stroke-dasharray 设为2616(即第一段实线长度刚好为图案的总长)、stroke-dashoffset也设为2616(即每段实线偏移量刚好为图案的总长,刚好使第一段实线消失),模拟出爱心边框消失的效果;
- 通过关键帧动画设置动态绘制的效果: 关键帧动画:0%保持stroke-dashoffset=2616不变,100%将stroke-dashoffset设置为0(去除偏移量,使线段完全回到原来的位置)在animation中可以设置forwards效果(让爱心被绘制后定格,也可以设置为infinite循环动画)。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>svg {fill: none;stroke: red;stroke-width: 5px;/* 初始时线段总长和偏移量都等于图案总长模拟线段消失的效果 */stroke-dasharray: 2616;stroke-dashoffset: 2616;animation: moveheart 1.5s linear forwards;/* 1.5s动画时间 平滑运动 定格在最后一帧 */}/* 偏移量从图案总长到0的过渡 */@keyframes moveheart {0% {stroke-dashoffset: 2616;}100% {stroke-dashoffset: 0;}}</style>
</head><body><svg t="1760633803545" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"p-id="2599" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><!-- 给图案添加id方便利用js指令获取长度 --><path id="heart"d="M667.786667 117.333333C832.864 117.333333 938.666667 249.706667 938.666667 427.861333c0 138.250667-125.098667 290.506667-371.573334 461.589334a96.768 96.768 0 0 1-110.186666 0C210.432 718.368 85.333333 566.112 85.333333 427.861333 85.333333 249.706667 191.136 117.333333 356.213333 117.333333c59.616 0 100.053333 20.832 155.786667 68.096C567.744 138.176 608.170667 117.333333 667.786667 117.333333z"p-id="2600"></path></svg>
</body></html>
小案例:模仿OPPO AI里程碑效果
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ljl里程碑svg</title><style>body {margin: 0;background-color: #f5f7fa;display: flex;flex-direction: column;align-items: center;height: 100vh;overflow: hidden;/* font-family: "Microsoft YaHei", sans-serif; */}/* 整个展示区域 */.container {width: 80%;max-width: 1000px;position: relative;display: flex;flex-direction: column;align-items: center;}svg {width: 100%;height: auto;}.slider-wrapper {width: 100%;margin-top: 10px;/* 控制滑块与曲线的间距 */display: flex;justify-content: center;}input[type="range"] {width: 100%;height: 6px;border-radius: 5px;background: #ddd;outline: none;-webkit-appearance: none;}input[type="range"]::-webkit-slider-thumb {width: 20px;height: 20px;border-radius: 50%;background: #00d084;cursor: pointer;-webkit-appearance: none;}text {font-size: 16px;font-weight: 500;text-anchor: middle;fill: #333;opacity: 0;transition: opacity 0.4s ease;}.above {dominant-baseline: auto;}.below {dominant-baseline: hanging;}.area {height: 200px;}/* text {border: 1px soild grey;} 不能这么干! */</style>
</head><body><div class="area"></div><div class="container"><svg viewBox="0 0 800 300" preserveAspectRatio="xMidYMid meet"><!-- 曲线 --><path id="milestone-path" d="M50 200 Q200 100 400 200 T750 160" stroke="#00d084" stroke-width="6"fill="none" stroke-linecap="round" /><!-- 文字 --><text x="200" y="90" class="above">2015 年 · 起步</text><text x="400" y="240" class="below">2018 年 · 成长</text><text x="650" y="140" class="above">2022 年 · 突破</text></svg><!-- 滑块部分紧贴SVG下方 --><div class="slider-wrapper"><input type="range" id="slider" min="0" max="100" value="0"></div></div><script>const path = document.getElementById('milestone-path');const totalLength = path.getTotalLength();const slider = document.getElementById('slider');const texts = document.querySelectorAll('text');// 初始化路径隐藏path.style.strokeDasharray = totalLength;path.style.strokeDashoffset = totalLength;slider.addEventListener('input', () => {const percent = slider.value;const drawLength = (percent / 100) * totalLength;path.style.strokeDashoffset = totalLength - drawLength;// 控制文字texts.forEach((t, i) => {const threshold = (i + 1) * 30; // 每 30% 显示一个文字t.style.opacity = percent >= threshold ? 1 : 0;});});</script></body></html>
SVG模糊和阴影效果
SVG效果标签都要包含在defs标签中
给svg添加特殊效果的基本标签:defs嵌套filter 一个filter元素可包含一个或多个效果滤镜
filter有一个必要的id属性用于识别过滤器,图形通过id指向要使用的过滤器
图形中用filter="url(# )"来声明id,id属性的值要保持唯一性
x、y为滤镜的起始点坐标
<defs><filter id="f111" x="" y=""></filter>
</defs><rect filter="url(#f111)"/>
模糊效果: feGaussianblur 高斯模糊效果(单标签),利用stdDeviation属性定义模糊的数值(数值越高模糊效果越明显)
阴影效果: feOffset feBlend 其本质为将图像根据原位置偏移作为阴影
<filter><feOffset dx="" dy="" in="" /><feBlend in="" />
</filter>
feOffset 阴影偏移
- dx dy 表示根据原位置偏移的量,单位为像素
- in 表示阴影图像来源,通常有两个值
- SourceAlpha 原图像的黑色形状作为阴影
- SourceGraphic 原始图像作为阴影
feBlend 在偏移图像上方混合原始图像
in属性一般为原始图像SourceGraphic
小练习:
<svg width="140" height="140"><defs><filter x="0" y="0" width="200%" height="200%" id="f2"><feOffset in="SourceAlpha" dx="20" dy="20" /><feGaussianBlur stdDeviation="10" /><feBlend in="SourceGraphic" /></filter></defs><rect width="90" height="90" stroke="green" stroke-width="3" fill="yellow" filter="url(#f2)" /></svg>
SVG线性渐变和径向渐变
线性渐变 linearGradient 可实现水平渐变、垂直渐变或角度渐变等从某点向另一点的线性渐变。
同样也需要id属性。
<defs><linearGradient x1="" y1="" x2="" y2="" id=""><stop offset="10%" stop-color="yellow"/><stop offset="" stop-color=""/><stop offset="" stop-color=""/></linearGradient>
</defs>
- x1 y1 x2 y2表示渐变的起点坐标和终点坐标。
- x1=x2 y1≠y2 产生垂直渐变
- x1≠x2 y1=y2 产生水平渐变
- x1≠x2 y1≠y2 产生角度渐变
- linearGradient标签中需要嵌套一个或多个stop标签来表示u原色
- offset一般为百分数,表示该颜色所在渐变轨迹中的相对位置(0%为起点处,100%为终点处)
- stop-color为一个颜色值
径向渐变 radialGradiet 可实现某个点由内向外圆形渐变的效果
<defs><radialGradient id="" cx="" cy="" r="" fx="" fy=""> <stop offset="10%" stop-color="yellow"/><stop offset="" stop-color=""/><stop offset="" stop-color=""/></radialGradient>
</defs>
其中,cx cy r属性定义了外层圆的基本特征,fx fy定义了内层圆的基本特征。
小练习:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>SVG 渐变椭圆</title>
</head><body><svg width="300" height="300" viewBox="0 0 300 300"><defs><!-- 垂直线性渐变 --><linearGradient id="vertical" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="lightblue" /><stop offset="100%" stop-color="yellow" /></linearGradient><!-- 角度线性渐变 --><linearGradient id="angled" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="pink" /><stop offset="100%" stop-color="lightgreen" /></linearGradient><!-- 中心径向渐变 --><radialGradient id="centered" cx="50%" cy="50%" r="50%"><stop offset="0%" stop-color="white" /><stop offset="100%" stop-color="blue" /></radialGradient><!-- 偏心径向渐变 --><radialGradient id="offcenter" cx="30%" cy="30%" r="50%"><stop offset="0%" stop-color="#ff9a9e" /><stop offset="50%" stop-color="#fecfef" /><stop offset="100%" stop-color="#fecfef" /></radialGradient></defs><ellipse cx="75" cy="75" rx="60" ry="40" fill="url(#vertical)" /><ellipse cx="225" cy="75" rx="60" ry="40" fill="url(#angled)" /><ellipse cx="75" cy="225" rx="60" ry="40" fill="url(#centered)" /><ellipse cx="225" cy="225" rx="60" ry="40" fill="url(#offcenter)" /></svg>
</body></html>
clip-path 裁剪
创建复杂的裁剪形状,使元素仅显示被裁剪区域内的部分
语法: clip-path: 内置几何形
内置几何形如: circle()、polygon()等
.circle {clip-path:circle(40% at 50% 50%)
}
可视化工具: https://tools.jb51.net/static/api/css3path/index.h
相关图性参数在里面查阅:选中并调节好所需图形,粘贴下面的代码到目标盒子的选择器即可。
小案例:裁剪盒子
将盒子裁剪成平行四边形。
小案例: 重叠盒子的过渡动画
- 效果:鼠标经过盒子时,盒子中的图片A平滑地变成图片B。、
- 用一个div标签包裹个尺寸相同的img图片,并使用定位将两张图片压至完全重合;
- 在网站上使用图形:确定一个图形作为B覆盖在A之上的形状,将该图形的点位拉成一条线,并复制此时的css代码,作为图形B的图片状态;再将原图形代码复制,作为鼠标放在div盒子时的图形B的图片状态,此时,正常情况下图形B被压成一条线,所以看到的是图形A,而鼠标放到盒子上时会变成图形B。
- 给盒子加上transition动画效果,使过渡更加自然。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box1 {margin: 50px;color: white;background-color: darkblue;/* justify-content: center; */text-align: center;line-height: 65px;height: 70px;width: 200px;size: 30px;-webkit-clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);}a {color: inherit;text-decoration: none;}a:hover {color: aquamarine}.box2 {position: relative;}.box2 img {width: 700px;position: absolute;top: 0;left: 0;transition: 0.3s linear;}.box2 img:nth-child(2) {-webkit-clip-path: polygon(0% 0%, 0 0, 0 50%, 0 100%, 0 100%);clip-path: polygon(0% 0%, 0 0, 0 50%, 0 100%, 0 100%);}.box2:hover img:nth-child(2) {-webkit-clip-path: polygon(0% 0%, 100% 1%, 100% 50%, 100% 100%, 0% 100%);clip-path: polygon(0% 0%, 100% 1%, 100% 50%, 100% 100%, 0% 100%);}</style>
</head><body><div class="box1"><a href="https://pvp.qq.com">电竞专属客户端</a></div><div class="box2"><img src="https://auto-pic.china.com/5ca5d352bc82c.jpg" alt=""><img src="https://auto-pic.china.com/5ca5d35f80632.jpg" alt=""></div>
</body></html>