#javascript #html #css #svg #градиент
Я хочу создать радугу по окружности, как на рисунке ниже. Но как мне нарисовать изогнутый и многоцветный градиент? Вот мой текущий код: Перевод вопроса: svg multiple color on circle stroke
Ответы
Ответ 1
Такое возможно при помощи полифилла 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%; }Ответ 2
Такой подход не будет работать. SVG не имеет конических градиентов. Чтобы имитировать эффект, вам нужно было бы подделать его большим количеством маленьких отрезков. Или применить какую-то другую, подобную технику. Update: Вот пример. Я аппроксимирую 360deg оттенками на шести отрезках, созданными path's. Каждый path содержит дугу, которая покрывает 60 градусов окружности. Я использую linear gradient для интерполяции цвета от начала до конца каждого пути. Это не идеально (вы можете увидеть некоторые разрывы, где цвета встречаются), но это не заметит большинство людей. Вы можете увеличить точность, используя более шести сегментов. Пример на fiddle Update 2: Для вариантов, с шестью и более сегментами, есть решение на 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 multiple color on circle stroke @Paul LeBeauОтвет 3
Пожалуй, оставлю это здесь... В Интернете вопрос до сих пор актуален. SVG: + Масштабируемость; + Возможность анимации; + Малый объём и понятность кода. Canvas: + Масштабируемость; + Возможность анимации; – Объём кода больше, расчёты сложнее. CSS: + Нативный код, без привлечения новых технологий; – Масштабируемость и анимация затруднительна; – Непрозрачность внутренней части круга. /************* * SVG * ************/ var oView = document.getElementById('svg'), nHue = 360, oCircle, nAngle; while (nHue--) { nAngle = nHue * Math.PI / 180; oCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); oCircle.setAttribute('cx', 50 - Math.sin(nAngle) * 45); oCircle.setAttribute('cy', 50 - Math.cos(nAngle) * 45); oCircle.setAttribute('r', '5'); oCircle.setAttribute('fill', 'hsl(' + nHue + ', 100%, 50%)'); oView.appendChild(oCircle); } /************** * CANVAS * *************/ var cnv = document.getElementById('cnv'); var ctx = cnv.getContext('2d'); var nCY = cnv.height / 2; var nCX = cnv.width / 2; var nR = cnv.width / 2; var nHues = 360; while (nHues--) { nStartCX = nCX + (Math.cos(nHues * Math.PI / 180) * nR * 0.8); nStartCY = nCY + (Math.sin(nHues * Math.PI / 180) * nR * 0.8); nStopCX = nCX + (Math.cos((nHues + 2) * Math.PI / 180) * nR * 0.8); nStopCY = nCY + (Math.sin((nHues + 2) * Math.PI / 180) * nR * 0.8); nStartDX = nCX + (Math.cos(nHues * Math.PI / 180) * nR); nStartDY = nCY + (Math.sin(nHues * Math.PI / 180) * nR); nStopDX = nCX + (Math.cos((nHues + 2) * Math.PI / 180) * nR); nStopDY = nCY + (Math.sin((nHues + 2) * Math.PI / 180) * nR); ctx.save(); ctx.beginPath(); ctx.moveTo(nStartCX, nStartCY); ctx.lineTo(nStartDX, nStartDY); ctx.lineTo(nStopDX, nStopDY); ctx.lineTo(nStopCX, nStopCY); ctx.fillStyle = 'hsl(' + nHues + ', 100%, 50%)'; ctx.fill(); ctx.closePath(); } ctx.restore(); /************* * CSS * *************/ .rgb { border-radius: 50%; position: relative; background: radial-gradient(ellipse at center, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 1) 56%, rgba(255, 255, 255, 0) 57%, rgba(255, 255, 255, 0) 100%), /* white hole */ linear-gradient(10deg, rgb(255, 0, 0) 0%, rgba(255, 0, 0, 0) 40%), /* red */ linear-gradient(70deg, rgb(255, 255, 0) 0%, rgba(255, 255, 0, 0) 50%), /* yeloow */ linear-gradient(130deg, rgb(0, 255, 0) 0%, rgba( 0, 255, 0, 0) 45%), /* gren */ linear-gradient(190deg, rgb(0, 255, 255) 0%, rgba(0, 255, 255, 0) 50%), /* cyan */ linear-gradient(250deg, rgb(0, 0, 255) 0%, rgba(0, 0, 255, 0) 50%), /* blue */ linear-gradient(310deg, rgb(255, 0, 255) 0%, rgba(255, 0, 255, 0) 50%)/* magenta */ ; } canvas, svg, div { display: inline-block; height: 180px; width: 180px; } pre { top: 55px; position: absolute; font: bold 26px monospace; text-shadow: 1px 3px 3px rgba(0, 0, 0, 0.75); }SVG Canvas CSSОтвет 4
Добавлю перевод моего ответа на похожий вопрос в английской версии: https://stackoverflow.com/a/58399254/1566316 с дополнением. Можно использовать преобразование центральной проекции (перспективы) над прямоугольниками с линейным градиентом, сжав их в треугольники по одной стороне с помощью transform:matrix3d или rotate3d и perspective в css. Если четвёртый параметр matrix3d не равен нулю, он задаёт обратное (1/x) значение кординаты точки схода перспективы на оси х линии горизонта. Тринадцатый параметр смещает прямоугольник по горизонтали. Хотя и допустимо использовать calc в матрице, она не работает с единицами измерения, поэтому при масштабировании работа matrix3d сбивается и использовтать её получается только в svg и только в Firefox, так как в svg в Chromium не поддерживаются параметры, ответсвенные за перспективу (4, 8). Однако в последнем уже есть conic-gradient, хотя его нельзя применить к любому элементу svg, а только к foreignObject. Как работает свойство tranform-origin в svg мне так и не удалось разобраться, поэтому элементы матрицы частично подобраны наугад. SVG версия цветового круга. Контрольные точки градиента получены по следующей формуле (из геометрии прямоугольного треугольника со сторонами 350х200): 0.5 ± tan(v/255.*pi/3)/350*100. где v - значение изменяющегося цветового канала. SVG версия кольца. В HTML можно использовать transform:rotate3D. Расположив точку зрения очень близко к прямоугольнику можно получить почти треугольник. *{ margin:0; padding:0; } .c{ height:90vmin; width:90vmin; margin:5vmin; overflow: hidden; border-radius:50%; position:absolute; } .c>div{ position:relative; height:180vmin; width:100vmin; perspective: 0.40vmin; top:-45vmin; left:-4.8vmin; } .c>div>div{ height: 100%; width: 100%; left:0; top:1%; height: 98%; transform-origin:99.98% 50%; position:relative; transform: rotate3d(0, 1, 0, -80deg); border:black; } #YM>div{ background:linear-gradient(#ef08,#ff0 0.5%,#fc0 18.27%,#f90 29.24%,#f60 37.28%,#f00 50%,#f06 62.72%,#f09 70.76%,#f0c 81.73%,#f0f 99.5%,#e0f8); } #MC{ transform: rotateZ(120deg); } #CY{ transform: rotateZ(-120deg); } #MC>div{ background:linear-gradient(#f0e8,#f0f 0.5%,#c0f 18.27%,#90f 29.24%,#60f 37.28%,#00f 50%,#06f 62.72%,#09f 70.76%,#0cf 81.73%,#0ff 99.5%,#0fe8); } #CY>div{ background:linear-gradient(#0ef8,#0ff 0.5%,#0fc 18.27%,#0f9 29.24%,#0f6 37.28%,#0f0 50%,#6f0 62.72%,#9f0 70.76%,#cf0 81.73%,#ff0 99.5%,#fe08); }
Комментариев нет:
Отправить комментарий