Круговая диаграмма с подписями
возможно ли сделать такую диаграмму посредством css или js. Через абсолют такое себе, более адаптивный вариант к реализации есть какой то?
Ответы (1 шт):
Для начала создадим круг с числами.
let circleDiv = document.querySelector('#circle')
circleDiv.style.position = 'relative'
let indexes = []
for (let i = 0; i < 7; i++) {
indexes.push(i + 1)
}
let angle = 270
let angleIncrement = 360 / indexes.length
let radius = 100
let centerX = circleDiv.offsetWidth / 2
let centerY = circleDiv.offsetHeight / 2
for (let i = 0; i < indexes.length; i++) {
let index = document.createElement('div')
index.textContent = indexes[i]
index.style.position = 'absolute'
let r = angle * Math.PI / 180
index.style.left = centerX + radius * Math.cos(r) + 'px'
index.style.top = centerY + radius * Math.sin(r) + 'px'
angle += angleIncrement
circleDiv.appendChild(index)
}
#circle {
width: 250px;
height: 250px;
}
<div id="circle"></div>
Объяснение
Сначала получим доступ к нашему элементу где будет храниться круг, далее зададим ему position: relative, чтобы все элементы, которые позиционированы абсолютно, позиционировались относительно нашего элемента. Далее создаём массив с 7'ю элементами (как у вас на картинке). Начальный угол 270, т.к. 1 должно находится в самом вверху. Далее задаём на сколько должен увеличиваться угол и сам радиус круга, дальше находим центр нашего элемента и записываем переменные как центра по X'у, так и по Y'у. Далее проходимся циклом по массиву indexes, создаём элемент с нашим индексом, задаём ему абсолютное позиционирование и задаём top и left, в них, прибавляем centerX (Или centerY в зависимости от пропорции) к радиусу который умножен на радиан нашего угла и это красота обёрнута в cos (Или
sin), далее к нашему углу прибавляем angleIncrement и переносим наш созданный элемент в родительский элемент. Ничего сложного.
Зададим стилей
let circleDiv = document.querySelector('#circle')
circleDiv.style.position = 'relative'
let indexes = []
for (let i = 0; i < 7; i++) {
indexes.push(i + 1)
}
let angle = 270
let angleIncrement = 360 / indexes.length
let radius = 100
let centerX = circleDiv.offsetWidth / 2
let centerY = circleDiv.offsetHeight / 2
for (let i = 0; i < indexes.length; i++) {
let index = document.createElement('div')
index.textContent = indexes[i]
index.style.position = 'absolute'
let r = angle * Math.PI / 180
index.style.left = centerX + radius * Math.cos(r) + 'px'
index.style.top = centerY + radius * Math.sin(r) + 'px'
index.style.zIndex = '2'
index.className = 'circle-index'
angle += angleIncrement
circleDiv.appendChild(index)
}
let backgroundCircle = document.createElement('div')
backgroundCircle.className = 'background-circle'
circleDiv.appendChild(backgroundCircle)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, 'Segoe UI';
}
#circle {
width: 250px;
height: 250px;
}
.circle-index {
background-color: rgb(51, 204, 153);
padding: .125em;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
color: rgb(255, 255, 255);
font-weight: bold;
}
.background-circle {
width: 80%;
height: 80%;
border: 3px solid rgb(70, 45, 113);
border-radius: 50%;
position: absolute;
z-index: 1;
left: 40px;
top: 40px;
}
<div id="circle"></div>
Тут надеюсь ничего объяснять не надо. Если всё-таки объяснение требуется, отпишитесь в комментариях.
Создадим текст рядом с числами
let circleDiv = document.querySelector('#circle')
circleDiv.style.position = 'relative'
let texts = {
'1': {
header: 'Подача заявки',
desc: 'Вам достаточно предоставить нам инвойс с весом и объемом продукции, сообщим о необходимом дне загрузки',
},
'2': {
header: 'Просчёт кп по индивидуальным условиям',
desc: 'В полном соответствии Вашим пожеланиям',
},
'3': {
header: 'Заключение договора или контракта на перевозку',
desc: '',
},
'4': {
header: 'Загрузка товаров у поставщика и логистика',
desc: '',
},
'5': {
header: 'Растаможивание и прохождение фитосанитарного контроля в РФ',
desc: '',
},
'6': {
header: 'Выгрузка товаров у нас на складах ( с возможностью хранения) или доставка до необходимого Вам места или региона.',
desc: '',
},
'7': {
header: 'Подача отчетности поквартально',
desc: '',
},
}
let indexes = []
for (let i = 0; i < 7; i++) {
indexes.push(i + 1)
}
let angle = 270
let angleIncrement = 360 / indexes.length
let radius = 100
let centerX = circleDiv.offsetWidth / 2
let centerY = circleDiv.offsetHeight / 2
for (let i = 0; i < indexes.length; i++) {
let index = document.createElement('div')
let j = indexes[i]
index.textContent = j
index.style.position = 'absolute'
let r = angle * Math.PI / 180
let left = centerX + radius * Math.cos(r)
let top = centerY + radius * Math.sin(r)
index.style.left = left + 'px'
index.style.top = top + 'px'
index.style.zIndex = '2'
index.className = 'circle-index'
let text = document.createElement('div')
let currentText = texts[j]
text.innerHTML = `<div class="circle-header">${currentText.header}</div><div class="circle-desc">${currentText.desc}</div>`
j < 8 ? circleDiv.appendChild(text) : void 0
let header = text.querySelector('.circle-header')
let desc = text.querySelector('.circle-desc')
text.style.position = 'absolute'
text.id = 'text-' + j
angle += angleIncrement
circleDiv.appendChild(index)
}
let backgroundCircle = document.createElement('div')
backgroundCircle.className = 'background-circle'
circleDiv.appendChild(backgroundCircle)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, 'Segoe UI';
}
#circle {
width: 250px;
height: 250px;
margin: 250px auto;
}
.circle-index {
background-color: rgb(51, 204, 153);
padding: .125em;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
color: rgb(255, 255, 255);
font-weight: bold;
}
.background-circle {
width: 80%;
height: 80%;
border: 3px solid rgb(70, 45, 113);
border-radius: 50%;
position: absolute;
z-index: 1;
left: 40px;
top: 40px;
}
.circle-header {
color: rgb(70, 45, 113);
font-weight: bold;
}
.circle-desc {
color: rgb(0, 0, 0);
}
#text-1 {
top: -120px;
left: 65px;
}
#text-2 {
left: 250px;
top: -5px;
}
#text-3 {
top: 140px;
left: 255px;
}
#text-4 {
top: 250px;
left: 200px;
}
#text-5 {
top: 250px;
left: -100px;
}
#text-6 {
top: 120px;
left: -150px;
width: 187px;
}
#text-7 {
left: -200px;
top: 45px;
}
<div id="circle"></div>
Весь текст я расставлял в ручную т.к. уже не смог придумать способа расставлять его автоматически (сдулся), вот так вот, все пропорции в CSS.
Надеюсь мой ответ хоть чем-то вам поможет.
