Страницы

Поиск по вопросам

пятница, 13 декабря 2019 г.

Вращающееся меню навигации?

#javascript #html #css #svg


Товарищи, подскажите! Куда копать, возможно ли это вообще - как реализовать такой
круг в html, чтобы при клике на конкретное меню - оно вращалось и выбранное меню становилось
на верх (как колесо фортуны, но не рандом).

Интересует так же, как это изобразить в коде? Достаточно только css или нужно что-то
еще? Есть какие то примеры, наводки? 



Update:

Заново прошу помощи! Есть вот такой круг (спасибо MaximLensky): codepen.io/topicstarter/pen/dExqLr

Как сделать из него семиугольник (здесь пятиугольник). А так же добавить сверху такие
меню, как на картинке?

Как его анимировать, чтобы при нажатии на элемент - круг вращался и наверх по центру
становился выбранный элемент, изменялся цвет? Дополнительные меню сверху - просто ссылки,
такого же цвета, как и основной элемент.

Важно, чтобы текст и цвета можно было изменить.

Так же прикрепляю примерно что-то похожее (вращение): codepen.io/AndersFly666/pen/GZxVYO


    


Ответы

Ответ 1



Что касается верстки всяких разных кругов, тут ваши лучшие друзья это Math.sin Math.cos и Math.PI Вот пример с использованием d3.js, но могло быть и без него PS: длинный текст надо тоже вписать в круг и его вращать Самая актуальная версия тут https://codepen.io/strangerintheq/pen/wbVRGL let data = Array(5).fill(0).map(object) let a = Math.PI*2/data.length, start = -Math.PI/2 let r1 = 30, r2 = 35, r3 = 37, r4 = 95; let basePts = []; basePts.push(pt(0, r1)) basePts.push(pt(a, r2)) basePts.push(pt(a*2-0.15, r3)) basePts.push(pt(a*1.5-0.1, r4)) let arc = `A ${r4} ${r4} 0 0 1 ${pt(a/2, r4)}` ; append('path', 'line') .attr('stroke', d => d.color) .attr('fill', 'none') .attr('d', 'M' + basePts.join('L') + arc) .attr('transform', (d, i) => `rotate(${-i*360/data.length})`) append('text', 'icon') .attr('fill', d => d.color) .html(d => d.icon) .attr('x', (e, i) => pt(a*i+a*0.7,80)[0]) .attr('y', (e, i) => pt(a*i+a*0.7,80)[1]) append('text', 'number') .attr('fill', d => d.color) .html((d, i) => i+1) .attr('x', (e, i) => pt(a*i+a*1.5,44)[0]) .attr('y', (e, i) => pt(a*i+a*1.5,44)[1]) basePts.shift(); append('path', 'active') .attr('d', 'M' + basePts.join('L') + arc) .attr('transform', (d, i) => `rotate(${-i*360/data.length})`) .on('click', (d,i) => { let angle = (i + 1)*360 / data.length d3.select('g').attr('transform', `rotate(${angle})`) d3.selectAll('text').attr('transform', function(){ let x = d3.select(this).attr('x') let y = d3.select(this).attr('y') return `rotate(${-angle},${x},${y})`; }) }) function append(node, clazz) { return d3.select('g') .selectAll(node + '.' + clazz) .data(data) .enter() .append(node) .classed(clazz, true) } function pt (a, r) { a = - a - Math.PI/2 return [Math.cos(a)*r, Math.sin(a)*r]; } function object(){ return { color: `hsl(${Math.random()*360},55%,55%)`, icon: `ð${Math.floor(Math.random()*100)};` } } text { stroke: transparent; dominant-baseline: middle; text-anchor: middle; } .icon { font-family: FontAwesome; font-size: 20px; transition: 1s; } .number { font-family: arial, sans-serif; font-size: 15px; transition: 1s; } path.active{ fill: transparent; cursor: pointer; } g { transition: 1s; } UPD: Классика жанра, в макете 5 углов, но надо 7, как хорошо что я не умею делать это в inkscape, я просто поменяю пару цифр в своем коде let data = Array(7).fill(0).map(object) let a = Math.PI*2/data.length, start = -Math.PI/2 let r1=30, r2=35, r3=37, r4=95, rotation=0; let pts = []; pts.push(pt(0, r1)) pts.push(pt(a, r2)) pts.push(pt(a*2-0.15, r3)) pts.push(pt(a*1.5-0.45, r4)) let arc = (radius, angle) => `A ${radius} ${radius} 0 0 1 ${pt(angle, radius)}` ; append('path', 'line') .attr('stroke', d => d.color) .attr('d', 'M' + pts.join('L') + arc(r4, a-0.7)) .attr('transform', (d, i) => `rotate(${-i*360/data.length})`) append('text', 'icon rotate') .attr('fill', d => d.color) .html(d => d.icon) .attr('x', (e, i) => pt(a*i+a*0.35,80)[0]) .attr('y', (e, i) => pt(a*i+a*0.35,80)[1]) append('path', 'text-wrap-path') .attr('id', (d, i) => `text-wrap-path_${i}`) .attr('x', (e, i) => pt(a*i+a*0.77,67)[0]) .attr('y', (e, i) => pt(a*i+a*0.77,67)[1]) .attr('d', (e, i) => { let c = pt(a*i+a*0.77,67); return Array(5).fill(0).map((e,i) => line(Math.acos(1-2/5*i))) function line(a) { let p1 = pt(a, 21), p2 = pt(-a, 21); return 'M' + (c[0]+p1[0]) + ',' + (c[1]+p1[1]) + 'L' + (c[0]+p2[0]) + ',' + (c[1]+p2[1]) } }) append('text', 'text') .append('textPath') .attr('href', (e,i) => `#text-wrap-path_${i}`) .text(d => d.text) .attr('fill', d => d.color) .attr('startOffset', 40) append('text', 'number rotate') .attr('fill', d => d.color) .html((d, i) => i + 1) .attr('x', (e, i) => pt(a*i+a*1.2,44)[0]) .attr('y', (e, i) => pt(a*i+a*1.2,44)[1]) pts.shift(); append('path', 'active') .attr('fill', 'transparent') .attr('d', 'M' + pts.join('L') + arc(r4, a-0.7)) .attr('transform', (d, i) => `rotate(${-i*360/data.length})`) .on('click', click) lineAndText(r4+15, 0) lineAndText(r4+30, 1) lineAndText(r4+45, 2) function lineAndText(r,n){ append('path', 'line1 l' + n) .attr('id', (d, i) => `line1_l${n}_${i}`) .attr('stroke', d => d.color) .attr('d', 'M' + pt(a-0.05*(n+1), r) + arc(r, 0.2-0.05*(n+1))) .attr('transform', (d, i) => `rotate(${-i*360/data.length})`) append('text', 'menu l' + n) .append('textPath') .attr('href', (e,i) => `#line1_l${n}_${i}`) .text(d => d.menu[n]) .attr('fill', d => d.color) .attr('startOffset', 40) } function click(d,i) { let angle = (i+1)*360/data.length-30 let from = rotation; rotation = angle; d3.selectAll('.line1').style('opacity', 0) d3.selectAll('.line1.index_'+i).style('opacity', 1) d3.selectAll('.menu').style('opacity', 0) d3.selectAll('.menu.index_'+i).style('opacity', 1) d3.select('g').transition().duration(1000) .attrTween('transform', () => t => `rotate(${from+(angle-from)*t})`) d3.selectAll('.text-wrap-path').transition().duration(1000) .attrTween('transform', function() { let x = d3.select(this).attr('x') let y = d3.select(this).attr('y') return t => `rotate(-${from+(angle-from)*t}, ${x}, ${y})` }) d3.selectAll('text.rotate').transition().duration(1000) .attrTween('transform', function() { let x = d3.select(this).attr('x') let y = d3.select(this).attr('y') return t => `rotate(-${from+(angle-from)*t}, ${x}, ${y})` }) } function append(node, clazz) { return d3.select('g') .selectAll(node + '.' + clazz) .data(data) .enter() .append(node) .attr('fill', 'none') .attr('class', (d, i) => `${clazz} index_${i}`) } function pt (a, r) { a = - a - Math.PI/2 return [Math.cos(a)*r, Math.sin(a)*r]; } function object(){ return { color: `hsl(${Math.random()*360},55%,55%)`, icon: `ð${Math.floor(Math.random()*100)};`, menu: [`menu 1`, `menu 2`, `menu 3`], text: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur'.split(' ').filter(() => Math.random() > 0.5).join(' ') } } text { stroke: transparent; dominant-baseline: middle; text-anchor: middle; } .icon { font-family: FontAwesome; font-size: 18px; } .number { font-family: arial, sans-serif; font-size: 15px; } path.active{ cursor: pointer; } .line1, .menu { opacity: 0; transition: 1s; } text.menu{ dominant-baseline: text-before-edge; font-size:13px; cursor:pointer; } textPath { transition: 500ms; } text.menu:hover textPath { fill: red; } text.text { font-size: 8px; }

Ответ 2



Накидал макет на Svg в редакторе векторной графики Inkscape Для этого я вырезал в Gimp нужный фрагмент, и загрузил в inkscape, преимущественно пользовался инструментом path без закрутия пути Символы добавил с font-awesome что потребовало подключения самого шрифта с cdn и обычное копирование и вставка самой иконки 1 2 3 4 5 Lorem Ipsum issimply dummy text of the printing and typesetting industry. Lorem Ipsum has been theindustry's standard Contrary to popular belief, Lorem Ipsum is not simply random t is a long established fact that a reader will be distracted by the readable content (of a page when) Contrary to popularbelief, Lorem Ipsum is not simplyrandom text. Contrary to popular belief, Lorem Ipsum is not simply random text.

Комментариев нет:

Отправить комментарий