#javascript #html #css #svg #canvas
Есть вот такое колесо:
Т.е. нужно сделать 3 сплошных circle, поместить друг в друга и второй разделить на
6 частей.
Цвет элемента будет меняться по нажатию, т.е. плавно из серого переходить в градиент
и добавляться верхний border.
Подскажите, как лучше такое реализовать, на SVG или же Canvas?
Вот эти иконки будут интерактивно меняться в зависимости от выбранной части, также
текст в центре.
Ответы
Ответ 1
Решение SVG + CSS Окружность можно разделить на 6 отдельных секторов с помощью команды Elliptical Arc для path подробнее здесь Рисуем один сектор svg { height: 440px; width: 440px; } .sector { fill: #5F5E5F; stroke: #BFBFBF; stroke-width:2; } :hover.sector { fill:#9F45E2; stroke-width:6; stroke:#9F45E2; transition: fill 0.5s, stroke-width 0.5s; } Добавляем ещё 5 секторов svg { height: 440px; width: 440px; } .sector { fill: #5F5E5F; stroke: #BFBFBF; stroke-width:2; } :hover.sector { fill:#9F45E2; stroke-width:6; stroke:#9F45E2; transition: fill 0.5s, stroke-width 0.5s; Добавляем окружности для создания центральной части, добавляем текст и иконки. Иконки брал здесь Для придания нужного размера иконкам используем scale(0.7) Для позиционирования икон используется команда translate(X Y) Ниже полный код: svg { height: 440px; width: 440px; } .sector { fill: #5F5E5F; stroke: #BFBFBF; stroke-width:2; } :hover.sector { fill:#9F45E2; stroke-width:6; stroke:#9F45E2; transition: fill 0.5s, stroke-width 0.5s; } #F { fill: #5F5E5F; stroke: #BFBFBF; } #S { fill: none; stroke: #BFBFBF; stroke-width:5; } #T { fill: #707070; stroke: #FFFFFF; stroke-width:3; } .icon { fill:none; stroke:#CCCACD; transition: fill 0.5s; } :hover.icon { fill:#9F45E2; } JS Разбить круг на любое количество секторов можно с помощью javascript, который реализует формулу Elliptical Arc для path Задаются переменные fromAngle, toAngle начального и конечного угла сектора Задаются переменные для расчета начальных и конечных координат сектора fromCoordX, fromCoordY, toCoordX, toCoordY Вызов функции для рисования 6 секторов - createSector(55, 55, 50, 6);, где 55 координаты центра окружности 50 - радиус окружности 6 - количество секторов var fromAngle, toAngle, fromCoordX, fromCoordY, toCoordX, toCoordY, path, d; function createSector(cx, cy, r, part) { for (var i = 0; i < part; i++) { path = document.createElementNS("http://www.w3.org/2000/svg", "path"); fromAngle = i * 360 / part; toAngle = (i + 1) * 360 / part; fromCoordX = cx + (r * Math.cos(fromAngle * Math.PI / 180)); fromCoordY = cy + (r * Math.sin(fromAngle * Math.PI / 180)); toCoordX = cx + (r * Math.cos(toAngle * Math.PI / 180)); toCoordY = cy + (r * Math.sin(toAngle * Math.PI / 180)); d = 'M' + cx + ',' + cy + ' L' + fromCoordX + ',' + fromCoordY + ' A' + r + ',' + r + ' 0 0,1 ' + toCoordX + ',' + toCoordY + 'z'; path.setAttributeNS(null, "d", d); document.getElementById('pie').appendChild(path); } } createSector(55, 55, 50, 6); svg { height: 220px; width: 220px; } path { fill: #5F5E5F; stroke: #BFBFBF; stroke-width:2; } 8 секторов var fromAngle, toAngle, fromCoordX, fromCoordY, toCoordX, toCoordY, path, d; function createSector(cx, cy, r, part) { for (var i = 0; i < part; i++) { path = document.createElementNS("http://www.w3.org/2000/svg", "path"); fromAngle = i * 360 / part; toAngle = (i + 1) * 360 / part; fromCoordX = cx + (r * Math.cos(fromAngle * Math.PI / 180)); fromCoordY = cy + (r * Math.sin(fromAngle * Math.PI / 180)); toCoordX = cx + (r * Math.cos(toAngle * Math.PI / 180)); toCoordY = cy + (r * Math.sin(toAngle * Math.PI / 180)); d = 'M' + cx + ',' + cy + ' L' + fromCoordX + ',' + fromCoordY + ' A' + r + ',' + r + ' 0 0,1 ' + toCoordX + ',' + toCoordY + 'z'; path.setAttributeNS(null, "d", d); document.getElementById('pie').appendChild(path); } } createSector(55, 55, 50, 8); svg { height: 220px; width: 220px; } path { fill: #5F5E5F; stroke: #BFBFBF; stroke-width:2; } 12 секторов var fromAngle, toAngle, fromCoordX, fromCoordY, toCoordX, toCoordY, path, d; function createSector(cx, cy, r, part) { for (var i = 0; i < part; i++) { path = document.createElementNS("http://www.w3.org/2000/svg", "path"); fromAngle = i * 360 / part; toAngle = (i + 1) * 360 / part; fromCoordX = cx + (r * Math.cos(fromAngle * Math.PI / 180)); fromCoordY = cy + (r * Math.sin(fromAngle * Math.PI / 180)); toCoordX = cx + (r * Math.cos(toAngle * Math.PI / 180)); toCoordY = cy + (r * Math.sin(toAngle * Math.PI / 180)); d = 'M' + cx + ',' + cy + ' L' + fromCoordX + ',' + fromCoordY + ' A' + r + ',' + r + ' 0 0,1 ' + toCoordX + ',' + toCoordY + 'z'; path.setAttributeNS(null, "d", d); document.getElementById('pie').appendChild(path); } } createSector(55, 55, 50, 12); svg { height: 220px; width: 220px; } path { fill: #5F5E5F; stroke: #BFBFBF; stroke-width:2; }Ответ 2
Сверстал что-то подобное, при помощи синусов да косинусов. чтобы получить прямо точь в точь что и в макете надо еще с этим посидеть. пока так, для понимания я думаю хватит. let items = ['🍌','🍉','🍇','🍓','🍒','🍍'], r1 = 90, r2 = 50, step = Math.PI*2/items.length; let activate = el => document.querySelectorAll('.arc') .forEach(arc => arc.style.strokeWidth = (arc.classList.contains(el.id) ? 4:0) + 'px'); let cs = a => [Math.cos(a), Math.sin(a)] let icon = (e, i) => { let p = cs(i*step + step/2), r = (r1/2 + r2/2); return `${e} `; } let grid = (e, i) => { let p1 = cs(i*step); return ``; } let arc = (e, i) => { let p1 = cs(i*step), p2 = cs(i*step + step), r = r1+2.5; return ` `; } let sector = (e, i) => { let p1 = cs(i*step), p2 = cs(i*step + step); return ` ` } svg.innerHTML += items.map(sector).join('') svg.innerHTML += items.map(icon).join('') svg.innerHTML += ` `; svg.innerHTML += items.map(grid).join('') svg.innerHTML += items.map(arc).join('') path.sector { fill: url(#gradient); cursor: pointer; fill-opacity:0.5; transition: 0.5s; } path.arc { fill: none; stroke: purple; stroke-width: 0; pointer-events: none; transition: 0.5s; } path.sector:hover { fill-opacity:1; } text { dominant-baseline: middle; text-anchor: middle; pointer-events: none; } circle { fill: none; stroke: lightgray; pointer-events: none; stroke-width: 5px; } path.grid { stroke: lightgray; pointer-events: none; stroke-width: 3px; } Ответ 3
В общем я только с градиентной заливкой на hover завис ..а так все хотелки выполнены Если что то не ясно спрашивайте, не применял алгоритмов и само изготовление не сложное
Комментариев нет:
Отправить комментарий