原生SVG是不支持这样渐变的。矢量绘图软件在作出这些渐变后也要在导出时将渐变转换为位图,内嵌在矢量图里,但是这样做要么不能解决放大缩小带来的失真问题,要么使得矢量图太大。那么如何用SVG作出这种渐变呢?
通常SVG渐变是这样做的:
<defs>
<linearGradient id="grad1" x1="0%" y1="100%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#fff" stop-opacity="1"/>
<stop offset="100%" stop-color="#000" stop-opacity="1"/>
</linearGradient>
</defs>
表示从y=100%, x=0%开始到y=0%,x=100%结束中,0%处为颜色#fff,100%处为颜色#000;即左下角为白色,右上角为黑色。
整体SVG:
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg"><defs>
<linearGradient id="grad1" x1="0%" y1="100%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#fff" stop-opacity="1"/>
<stop offset="100%" stop-color="#000" stop-opacity="1"/>
</linearGradient>
</defs>
<circle cx="50" cy="50" r="50" fill="url(#grad1)"/>
</svg>
但是这样只是得到一个圆形的线性渐变而不是我们想要的下面这样的渐变👇

因为不支持而做不到,那只能绕个弯子,关键是CSS也不支持……
办法倒也不是没有,在SVG中插入<foreignObject/>然后直接用JS在<canvas/>上画出渐变。画出来的话,占用空间更小一点而且分辨率没有太多限制,除非分辨率太高需要很久才能画完。
<!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>
canvas {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
</body>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
const CX = w / 2;
const CY = h / 2;
const OFFSET = 90;//旋转角度
const START = 90;//开始渐变角度
const RANGE = 180;//渐变角度
const ROUNT = 360;//周角
const WHITE = 255;//最亮颜色值
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var theta = (Math.atan2(y - CY, x - CX) + Math.PI) / (Math.PI * 2) * (ROUNT - 1);
theta = (theta + OFFSET) % ROUNT + START
theta = Math.max(Math.min(Math.floor(((ROUNT - 1) - theta) / RANGE * WHITE), WHITE), 0);
var color = theta.toString(16);
while (color.length < 2) {
color = '0' + color
}
color = '#000000' + color
ctx.fillStyle = color;
ctx.fillRect(x, y, 1, 1)
}
}
</script>
</html>