简体   繁体   English

圆形笔划上的 svg 多种颜色

[英]svg multiple color on circle stroke

I want to create a rainbow circle, like the picture below:我想创建一个彩虹圈,如下图:

在此处输入图片说明

How can I draw the curved and multiple color stop gradient?如何绘制曲线和多色停止渐变?

Here's my current code:这是我当前的代码:

 <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>

This approach won't work.这种方法行不通。 SVG doesn't have conical gradients. SVG 没有锥形渐变。 To simulate the effect, you would have to fake it with a large number of small line segments.要模拟效果,您必须使用大量小线段来伪造它。 Or some similar technique.或者一些类似的技术。

Update:更新:

Here is an example.这是一个例子。 I approximate the 360deg of hue with six paths.我用六个路径来近似 360 度的色调。 Each path contains an arc which covers 60deg of the circle.每条路径都包含一个弧,它覆盖了圆的 60 度。 I use a linear gradient to interpolate the colour from the start to the end of each path.我使用线性渐变从每条路径的开始到结束插入颜色。 It's not perfect (you can see some discontinuities where the coloursmeet ) but it would possibly fool most people.它并不完美(您可以看到颜色相交的一些不连续性)但它可能会愚弄大多数人。 You could increase the accuracy by using more than six segments.您可以通过使用六个以上的段来提高准确性。

 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" 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 here: http://jsfiddle.net/Weytu/在这里小提琴: http : //jsfiddle.net/Weytu/

Update 2:更新 2:

For those that want more than six segments, here is some javascript that will produce a wheel with any number of segments that you wish.对于那些想要超过六个段的人,这里有一些 javascript 会产生一个你想要的任何数量的段的轮子。

 function makeColourWheel(numSegments) { if (numSegments <= 0) numSegments = 6; 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>

You can use the conic-gradient to solve it:您可以使用圆锥梯度来解决它:

 .color-wheel { display: inline-block; padding: 25px; border-radius: 100%; background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red); background-repeat: no-repeat; background-size: cover; background-position: center center; background-size: auto; } .color-wheel::after { content: ''; display: block; padding: 75px; border-radius: 100%; background: #ffffff; }
 <div class="color-wheel"></div>

But this is currently only supported in Chrome.但这目前仅在 Chrome 中受支持。 Take a look here for more information: https://caniuse.com/#feat=css-conic-gradients在这里查看更多信息: https : //caniuse.com/#feat=css-conic-gradients

I also built javascript/svg solution which can solve it easily:我还构建了可以轻松解决的 javascript/svg 解决方案:

 const resolution = 1; const outerRadius = 100; const innerRadius = 75; function polarToCartesian(centerX, centerY, radius, angleInDegrees) { const angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0; return { x: centerX + radius * Math.cos(angleInRadians), y: centerY + radius * Math.sin(angleInRadians) }; } function describeArc(x, y, radius, startAngle, endAngle) { const start = polarToCartesian(x, y, radius, endAngle); const end = polarToCartesian(x, y, radius, startAngle); const arcSweep = endAngle - startAngle <= 180 ? '0' : '1'; const d = [ 'M', start.x, start.y, 'A', radius, radius, 0, arcSweep, 0, end.x, end.y, 'L', x, y, 'L', start.x, start.y ].join(' '); return d; } function generateConicGradiant(radius, resolution, target) { for (var i = 0; i < 360 * resolution; i++) { const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); path.setAttribute( "d", describeArc( radius, radius, radius, i / resolution, (i + 2) / resolution ) ); path.setAttribute('fill', 'hsl(' + (i / resolution) + ', 100%, 50%)'); target.appendChild(path); } } function generateOverlay(outerRadius, innerRadius, target) { const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); circle.setAttribute('cx', outerRadius); circle.setAttribute('cy', outerRadius); circle.setAttribute('r', innerRadius); circle.setAttribute('fill', 'white'); target.appendChild(circle); } var root = document.getElementById('color-wheel'); generateConicGradiant(outerRadius, resolution, root); generateOverlay(outerRadius, innerRadius, root);
 #color-wheel { width: 200px; height: 200px; }
 <svg viewBox="0 0 200 200" version="1.1" id="color-wheel"></svg>

to improve oVi's answer: here you can set diameter and stroke-width to exact pixel sizes改进 oVi 的答案:在这里您可以将diameterstroke-width为精确的像素大小

 .color-wheel { --diameter: 160px; --stroke-width: 20px; position: relative; width: var(--diameter); height: var(--diameter); } .color-wheel > .color-circle { position: absolute; left: 0; top: 0; border-radius: 50%; width: 100%; height: 100%; background: conic-gradient(red, orange, yellow, lime, green, turquoise, blue, purple, red); /* four color system */ } .color-wheel > .inner-circle { --inner-diameter: calc(var(--diameter) - 2 * var(--stroke-width)); --margin: calc(-0.5 * var(--inner-diameter)); position: absolute; left: 50%; top: 50%; width: var(--inner-diameter); height: var(--inner-diameter); margin-left: var(--margin); margin-top: var(--margin); border-radius: 50%; background: white; } .color-wheel > .overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
 <div class="color-wheel"> <div class="color-circle"></div> <div class="inner-circle"></div> <div class="overlay"> hello world. this is a pure CSS color ring : ) </div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM