Я хочу создать радугу по окружности, как на рисунке ниже.
Но как мне нарисовать изогнутый и многоцветный градиент?
Вот мой текущий код:
<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="test">
<stop offset="0%" stop-color="#f00"/>
<stop offset="100%" stop-color="#0ff"/>
</linearGradient>
</defs>
<circle cx="50" cy="50" r="40" fill="none" stroke="url(#test)" stroke-width="6"/>
</svg>
Перевод вопроса: svg multiple color on circle stroke
Такое возможно при помощи полифилла conic-gradient Лии Веру.
.circle {
background: conic-gradient(#f00, #ff00bd, #0020ff, #00f3ff, #00ff08, #fff700, #f00);
border-radius: 50%;
width: 200px;
height: 200px;
position: relative;
}
.circle:after {
position: absolute;
content: '';
left: 20px;
top: 20px;
width: calc(100% - 40px);
height: calc(100% - 40px);
background: #fff;
border-radius: 50%;
}
<div class="circle"></div>
<script src='http://leaverou.github.io/prefixfree/prefixfree.min.js'></script>
<script src='http://leaverou.github.io/conic-gradient/conic-gradient.js'></script>
Такой подход не будет работать. SVG не имеет конических градиентов. Чтобы имитировать эффект, вам нужно было бы подделать его большим количеством маленьких отрезков. Или применить какую-то другую, подобную технику.
Вот пример. Я аппроксимирую 360deg оттенками на шести отрезках, созданными path's. Каждый path содержит дугу, которая покрывает 60 градусов окружности. Я использую linear gradient для интерполяции цвета от начала до конца каждого пути.
Это не идеально (вы можете увидеть некоторые разрывы, где цвета встречаются), но это не заметит большинство людей. Вы можете увеличить точность, используя более шести сегментов.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="220" height="220" viewBox="-10 -10 220 220">
<defs>
<linearGradient id="redyel" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#ff0000"/>
<stop offset="100%" stop-color="#ffff00"/>
</linearGradient>
<linearGradient id="yelgre" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#ffff00"/>
<stop offset="100%" stop-color="#00ff00"/>
</linearGradient>
<linearGradient id="grecya" gradientUnits="objectBoundingBox" x1="1" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#00ff00"/>
<stop offset="100%" stop-color="#00ffff"/>
</linearGradient>
<linearGradient id="cyablu" gradientUnits="objectBoundingBox" x1="1" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#00ffff"/>
<stop offset="100%" stop-color="#0000ff"/>
</linearGradient>
<linearGradient id="blumag" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#0000ff"/>
<stop offset="100%" stop-color="#ff00ff"/>
</linearGradient>
<linearGradient id="magred" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="1" y2="0">
<stop offset="0%" stop-color="#ff00ff"/>
<stop offset="100%" stop-color="#ff0000"/>
</linearGradient>
</defs>
<g fill="none" stroke-width="15" transform="translate(100,100)">
<path d="M 0,-100 A 100,100 0 0,1 86.6,-50" stroke="url(#redyel)"/>
<path d="M 86.6,-50 A 100,100 0 0,1 86.6,50" stroke="url(#yelgre)"/>
<path d="M 86.6,50 A 100,100 0 0,1 0,100" stroke="url(#grecya)"/>
<path d="M 0,100 A 100,100 0 0,1 -86.6,50" stroke="url(#cyablu)"/>
<path d="M -86.6,50 A 100,100 0 0,1 -86.6,-50" stroke="url(#blumag)"/>
<path d="M -86.6,-50 A 100,100 0 0,1 0,-100" stroke="url(#magred)"/>
</g>
</svg>
Пример на fiddle
Для вариантов, с шестью и более сегментами, есть решение на javascript, которое будет создавать круг с любым количеством сегментов.
function makeColourWheel(numSegments)
{
if (numSegments <= 0)
numSegments = 12;
if (numSegments > 360)
numSegments = 360;
var svgns = xmlns="http://www.w3.org/2000/svg";
var svg = document.getElementById("colourwheel");
var defs = svg.getElementById("defs");
var paths = svg.getElementById("paths");
var radius = 100;
var stepAngle = 2 * Math.PI / numSegments;
var lastX = 0;
var lastY = -radius;
var lastAngle = 0;
for (var i=1; i<=numSegments; i++)
{
var angle = i * stepAngle;
// Calculate this arc end point
var x = radius * Math.sin(angle);
var y = -radius * Math.cos(angle);
// Create a path element
var arc = document.createElementNS(svgns, "path");
arc.setAttribute("d", "M " + lastX.toFixed(3) + "," + lastY.toFixed(3)
+ " A 100,100 0 0,1 " + x.toFixed(3) + "," + y.toFixed(3));
arc.setAttribute("stroke", "url(#wheelseg" + i + ")");
// Append it to our SVG
paths.appendChild(arc);
// Create a gradient for this segment
var grad = document.createElementNS(svgns, "linearGradient");
grad.setAttribute("id", "wheelseg"+i);
grad.setAttribute("gradientUnits", "userSpaceOnUse");
grad.setAttribute("x1", lastX.toFixed(3));
grad.setAttribute("y1", lastY.toFixed(3));
grad.setAttribute("x2", x.toFixed(3));
grad.setAttribute("y2", y.toFixed(3));
// Make the 0% stop for this gradient
var stop = document.createElementNS(svgns, "stop");
stop.setAttribute("offset", "0%");
hue = Math.round(lastAngle * 360 / Math.PI / 2);
stop.setAttribute("stop-color", "hsl(" + hue + ",100%,50%)");
grad.appendChild(stop);
// Make the 100% stop for this gradient
stop = document.createElementNS(svgns, "stop");
stop.setAttribute("offset", "100%");
hue = Math.round(angle * 360 / Math.PI / 2);
stop.setAttribute("stop-color", "hsl(" + hue + ",100%,50%)");
grad.appendChild(stop);
// Add the gradient to the SVG
defs.appendChild(grad);
// Update lastx/y
lastX = x;
lastY = y;
lastAngle = angle;
}
}
makeColourWheel(60);
<svg id="colourwheel" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="-10 -10 220 220">
<defs id="defs">
</defs>
<g id="paths" fill="none" stroke-width="15" transform="translate(100,100)">
</g>
</svg>
Перевод ответа: svg multiple color on circle stroke @Paul LeBeau
Сборка персонального компьютера от Artline: умный выбор для современных пользователей