グラデーションは、Webデザインのほぼすべての場所で見ることができます。グラデーションの背景、テキスト、ボタン、グラフなどは、単色よりも柔軟で自然です。
今日お話しするのはSVG
、のグラデーション描画です。
シリーズの他SVG
の記事:SVGの基本、SVGアニメーション、 SVGでの変換。
概要
グラデーショングラフィックの描画経験があるかもしれませんcss
。グラデーション長方形を描画したい場合は、次のように記述できます。
<div class="bg"></div>
.bg{
height: 100px;
width: 200px;
//给元素设置渐变背景
background: linear-gradient(#fb3,#58a);
}
复制代码
SVG
描画では、要素のfill
(塗りつぶしの色)とstroke
(境界線の色)のプロパティを設定することで色を実現します。
<rect height="100" width="150" stroke="#45B649" stroke-width="2" fill="#DCE35B"></rect>
复制代码
グラデーションカラーの設定については、のようcss
に直接書くことはできませんが、 (線形グラデーション)と(放射状グラデーション)のfill="linear-gradient(color1, color2)"
特別なグラデーションタグを使用します。<linearGradient>
<radialGradient>
線形グラデーション
基本的な使用法
最初に、最も単純な例である線形グラデーションの長方形を描画する方法を見てみましょう。
<svg>
<defs>
<linearGradient id="gradient-test">
<stop offset="0%" stop-color="#DCE35B" />
<stop offset="100%" stop-color="#45B649" />
</linearGradient>
</defs>
<rect height="100" width="150" fill="url(#gradient-test)"></rect>
</svg>
复制代码
<linearGradient>
通常、<defs>
要素にグラデーションラベルを定義し、<linearGradient>
そのid
属性を一意の識別子として使用します。これは、後で使用する必要がある場所で参照するのに便利です。
<linearGradient>
の<stop>
タグはグラデーションカラーのカラーストップを定義し、その属性offset
と stop-color
属性はそれぞれカラーストップの位置とカラー値を定義し、色の透明度stop-opacity
を設定する属性もあります。stop-color
色を近づけると、色が止まります。
<linearGradient id="gradient-1">
<stop offset="30%" stop-color="#DCE35B" />
<stop offset="70%" stop-color="#45B649" />
</linearGradient>
复制代码
長方形の左側の30%の領域#DCE35B
は単色で塗りつぶされ、右側の30%の領域は#45B649
単色で塗りつぶされます。実際のグラデーションは、長方形の中央の40%にのみ表示されます。
如果两个颜色都设为50%,就得到了两块均分矩形的实色。在这基础上,我们可以生成各种颜色的条纹图案。
渐变的方向和范围
在没有设置渐变方向的时候,渐变的默认方向是从左向右。
如果要设定渐变方向,要用到<linearGradient>
的x1
,y1
,x2
,y2
这几个属性。
<linearGradient id="gradient-1" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#DCE35B" />
<stop offset="100%" stop-color="#45B649" />
</linearGradient>
复制代码
我们知道,在平面上,方向一般由向量来表示。而渐变的方向由(x1,y1)
(起点)和(x2,y2)
(点)两个点定义的向量来表示。
在一般的应用场景中,x1
,y1
,x2
,y2
的取值范围是[0,1]
(或者用百分数[0%, 100%]
)。
对于矩形而言,不管矩形的长宽比例是多少,它的左上角对应的都是(0,0)
,右下角则对应(1,1)
。
x1="0" y1="0" x2="0" y2="1"
表示从(0,0)
到(0,1)
,即渐变方向从矩形上边框垂直向下到下边框。
x1="0" y1="0.3" x2="0" y2="0.7"
的情形如下: 可以看出,x1
,y1
,x2
,y2
不仅决定渐变的方向,还决定了渐变的范围,超出渐变范围的部分由起始或结束色标的颜色进行纯色填充。
案例1:渐变文字
<svg width="600" height="270">
<defs>
<linearGradient id="background"> <!--背景渐变色-->
<stop offset="0%" stop-color="#232526" />
<stop offset="100%" stop-color="#414345" />
</linearGradient>
<linearGradient id="text-color" x1="0" y1="0" x2="0" y2="100%"> <!--文字渐变色-->
<stop offset="0%" stop-color="#DCE35B" />
<stop offset="100%" stop-color="#45B649" />
</linearGradient>
</defs>
<rect x="0" y="0" height="100%" width="100%" fill="url(#background)"></rect>
<text y="28%" x="28%">试问闲情都几许?</text>
<text y="44%" x="28%">一川烟草</text>
<text y="60%" x="28%">满城风絮</text>
<text y="76%" x="28%">梅子黄时雨</text>
</svg>
复制代码
<style>
text{
font-size: 32px;
letter-spacing:5px;
fill:url(#text-color); //文字的填充使用渐变色
}
</style>
复制代码
文字的填充,我们用了垂直方向的渐变色,对于每一行文字,都是从黄色渐变到绿色。
如果要将这几行文字作为一个整体来设置渐变色,像下面这样,应该怎样设置呢?
这就要用到gradientUnits
属性了。
gradientUnits
属性定义渐变元素(<linearGradient>
、<radialGradient>
)要参考的坐标系。 它有两个取值:objectBoundingBox
和 userSpaceOnUse
。
默认值是objectBoundingBox
,它定义渐变元素的参考坐标系为引用该渐变的SVG元素,渐变的起止、范围、方向都是基于引用该渐变的SVG元素(之前的<rect>
,这里的<text>
)自身,比如这里的每一个<text>
元素的左上角都是渐变色的(0,0)
位置,右下角都是(100%,100%)
。
userSpaceOnUse
则以当前的SVG元素视窗区域(viewport) 为渐变元素的参考坐标系。也就是SVG元素的左上角为渐变色的(0,0)
位置,右下角为(100%,100%)
。
<svg height="200" width="300">
<defs>
<!-- 定义两个渐变,除了gradientUnits,其他配置完全相同 -->
<linearGradient id="gradient-1" x1="0" y1="0" x2="100%" y2="100%" gradientUnits="objectBoundingBox">
<stop offset="0%" stop-color="#C6FFDD" />
<stop offset="100%" stop-color="#f7797d" />
</linearGradient>
<linearGradient id="gradient-2" x1="0" y1="0" x2="100%" y2="100%" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#C6FFDD" />
<stop offset="100%" stop-color="#f7797d" />
</linearGradient>
</defs>
<rect x="0" y="0" ></rect>
<rect x="150" y="0" ></rect>
<rect x="0" y="100" ></rect>
<rect x="150" y="100" ></rect>
</svg>
复制代码
rect{
height: 100px;
width: 150px;
fill: url(#gradient-1); //四个矩形都填充渐变色,下面左图为gradient-1,右图为gradient-2。
}
复制代码
gradientUnits:userSpaceOnUse
适用于画布中有多个图形,但每个图形都是整体渐变中的一部分这样的场景。值得注意的是,当gradientUnits="userSpaceOnUse"
时,x1
,y1
,x2
,y2
的取值只有用%
百分数这样的相对单位才表示比例,如果取值为x2="1"
,那就真的是1px
,这一点与gradientUnits="objectBoundingBox"
是不同的。
案例2:渐变的环形进度条
在上一篇文章中,我们实现了可交互的环形进度条: 这里我们将其改造成渐变的环形进度条。
使用渐变色作为描边stroke
的颜色,中间使用一个白色透明度渐变的圆,增加立体感。
<!--改动部分的代码-->
<svg height="240" width="240" viewBox="0 0 100 100">
<defs>
<linearGradient id="circle">
<stop offset="0%" stop-color="#A5FECB" />
<stop offset="50%" stop-color="#20BDFF" />
<stop offset="100%" stop-color="#5433FF" />
</linearGradient>
<linearGradient id="center">
<stop offset="0%" stop-color="rgba(255,255,255,0.25)" />
<stop offset="100%" stop-color="rgba(255,255,255,0.08)" />
</linearGradient>
</defs>
<!--灰色的背景圆环-->
<circle cx="50" cy="50" r="40" stroke-width="12" stroke="#eee" fill="none"></circle>
<!--渐变的动态圆环-->
<circle
class="process-circle"
cx="50" cy="50" r="40"
transform="rotate(-90 50 50)"
stroke-width="12"
stroke="url(#circle)"
fill="none"
stroke-linecap="round"
stroke-dasharray="251"></circle>
<!--白色透明度渐变的圆,增加立体感-->
<circle cx="50" cy="50" r="40" fill="url(#center)"></circle>
</svg>
复制代码
径向渐变
基础使用
径向渐变是色彩从中心点向四周辐射的渐变。
<svg height="300" width="200">
<defs>
<radialGradient id="test">
<stop offset="0%" stop-color="#e1eec3" />
<stop offset="100%" stop-color="#f05053" />
</radialGradient>
</defs>
<rect fill="url(#test)" x="10" y="10" width="150" height="150"></rect>
</svg>
复制代码
和线性渐变的结构类似,我们将径向渐变标签<radialGradient>
定义在<defs>
元素中,其id
属性作为其唯一标识,以便后面需要使用的地方对其进行引用。
<radialGradient>
中的<stop>
标签定义渐变色的色标,它的offset
和 stop-color
属性分别定义色标的位置和颜色值。
渐变的范围
径向渐变的范围由<radialGradient>
的cx,cy,r
三个属性共同决定,它们的默认值均是50%,是相对值,相对的是引用该渐变的SVG元素。
cx
和cy
定义径向渐变范围的圆心,(50%, 50%)
意味着是引用该渐变的SVG元素的中心。r
设定渐变范围的半径,当r=50%
时,说明渐变范围的半径在x
和y
方向的分别是引用该渐变的SVG元素width
和height
的50%。
//当rect高度减小时,渐变在y方向的半径也减小。
<rect fill="url(#test)" x="10" y="10" width="150" height="100"></rect>
复制代码
在cx,cy,r
都取默认值的情况下,径向渐变的范围刚好覆盖引用该渐变的SVG元素。实际开发中,我们常常需要调整渐变范围。
渐变起点的移动
在默认情况下,渐变起点都是在渐变范围的中心,如果想要不那么对称的渐变,就需要改变渐变起点的位置。
<radialGradient>
的fx
和fy
就是用来设置渐变色起始位置的。fx
和fy
的值也是相对值,相对的也是引用该渐变的SVG元素。
我们可以设定渐变的范围(cx
,cy
,r
),也可以设定渐变的起点位置(fx
,fy
)。但是如果渐变的起点位置在渐变的范围之外,会出现一些我们不想要的效果。
测试代码如下,可直接运行:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
display: flex;
justify-content: center;
}
.control{
margin-top:20px;
}
</style>
</head>
<body>
<svg height="300" width="200">
<defs>
<radialGradient id="test">
<stop offset="0%" stop-color="#e1eec3" />
<stop offset="100%" stop-color="#f05053" />
</radialGradient>
</defs>
<rect fill="url(#test)" x="10" y="10" width="150" height="150"></rect>
</svg>
<div class="control">
<div>cx:<input value="50" type="range" min="0" max="100" id="cx" /></div>
<div>cy:<input value="50" type="range" min="0" max="100" id="cy" /></div>
<div>r:<input value="50" type="range" min="0" max="100" id="r" /></div>
<div>fx:<input value="50" type="range" min="0" max="100" id="fx" /></div>
<div>fy:<input value="50" type="range" min="0" max="100" id="fy" /></div>
</div>
<script>
const rg = document.getElementById('test')
document.querySelectorAll('input').forEach((elem) => {
elem.addEventListener('change', (ev) => {
rg.setAttribute(ev.target.id, ev.target.value+'%')
})
})
</script>
</body>
</html>
复制代码
综合案例:透明的泡泡
最后我们用线性渐变和径向渐变画一个泡泡。
分析:
- 背景是一个用线性渐变填充的矩形。
- バブルは3つの部分に分かれています。円と放射状のグラデーションで満たされた2つの楕円です。
ここでの放射状のグラデーションは、主に色の透明度のグラデーションです。stop-color
色の透明度を設定するには、値を直接指定するか、色rgba
の透明度をstop-opacity
設定stop-color
します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.bubble{
animation: move 5s linear infinite;
animation-direction:alternate;
}
//泡泡的运动
@keyframes move {
0%{
transform: translate(0,0);
}
50%{
transform: translate(250px,220px);
}
100%{
transform: translate(520px,50px);
}
}
</style>
</head>
<body>
<svg height="400" width="700">
<defs>
<!--背景的线性渐变-->
<linearGradient id="background">
<stop offset="0%" stop-color="#DCE35B" />
<stop offset="100%" stop-color="#45B649" />
</linearGradient>
<!--光斑的径向渐变,通过fx、fy设置不对称的渐变-->
<radialGradient id="spot" fx="50%" fy="30%">
<stop offset="10%" stop-color="white" stop-opacity=".7"></stop>
<stop offset="70%" stop-color="white" stop-opacity="0"></stop>
</radialGradient>
<!--泡泡本体的径向渐变-->
<radialGradient id="bubble">
<stop offset="0%" stop-color="rgba(255,255,255,0)" ></stop>
<stop offset="80%" stop-color="rgba(255,255,255,0.1)" ></stop>
<stop offset="100%" stop-color="rgba(255,255,255,0.42)"></stop>
</radialGradient>
</defs>
<rect fill="url(#background)" width="100%" height="100%"></rect>
<g class="bubble">
<circle cx="100" cy="100" r="70" fill="url(#bubble)"></circle>
<ellipse rx="50" ry="20" cx="80" cy="60" fill="url(#spot)" transform="rotate(-25, 80, 60)" ></ellipse>
<ellipse rx="20" ry="10" cx="140" cy="130" fill="url(#spot)" transform="rotate(125, 140, 130)" ></ellipse>
</g>
</svg>
</body>
</html>
复制代码
上記のグラデーションカラーはすべて次のWebサイトからのものです:uigradients.com/