Появилась такая необходимость модернизировать стандартный doughnut chart, которые предоставляют библиотеки, но не знаю с чего начать. То есть необходимо изменить высоту и размер разных элементов в dought chart. Подскажите, как возможно изменить библиотеки(3d.js, chart.js, echart) или проще попробовать самому нарисовать svg чарт,
Вот вариант на js+svg, тут надо посчитать углы и точки арок:
let data = Array(5).fill(0).map((e,i)=> ({
r1: 10+i*2,
r2: -i*0.5,
value: Math.random()+0.1,
color: `hsl(${i*45},65%,65%)`
}));
let total = data.reduce((a, d) => a + d.value, 0);
let r = 40;
let a = 0;
chart.innerHTML = data.map(d => {
let cs1 = Math.cos(a);
let sn1 = Math.sin(a);
let angle = d.value/total*2*Math.PI;
a += angle;
let cs2 = Math.cos(a);
let sn2 = Math.sin(a);
let ir = r + d.r1;
let or = r + d.r2;
let la = angle > Math.PI ? 1 : 0;
return `<path d="${[
"M", [cs1*ir, sn1*ir],
"A", [ir, ir, 0, la, 1, cs2*ir, sn2*ir],
"L", [cs2*or, sn2*or],
"A", [or, or, 0, la, 0, cs1*or, sn1*or]
].join('')}" fill="${d.color}"></path>`;
}).join("");
body {
margin: 0;
overflow: hidden;
}
path {
opacity: 0.7;
transition: 1;
transition: 500ms;
cursor: pointer;
}
path:hover {
opacity: 1;
}
<svg id=chart viewbox=-60-60,120,120 width=100vw height=100vh></svg>
Для разбиения окружности на сектора вы можете использовать stroke-dasharray
Для смещения начала сектора используется stroke-dashoffset
Здесь нижний круг имеет серый цвет над ним расположен цветной сектор второго круга.
При r="40"
Полная длина окружности равна perimetr = 2 * 3.14 * 40 = 251,2
В этом примере строка заполнена на 80% amount = 80 , значит её нужно сдвинуть
stroke-dashoffset = perimeter - perimeter * amount / 100 = 50.3
<svg width="100%" height="100%" viewbox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="tomato"/>
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="grey"/>
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#00CCFF" stroke-dasharray="251.2" stroke-dashoffset="50.3"/>
<text x="40" y="50" fill="black" font-size="10">Text</text>
</svg>
Ниже пример с 50% заполнением
<svg width="100%" height="100%" viewbox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="tomato"/>
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="grey"/>
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#00CCFF" stroke-dasharray="251.2" stroke-dashoffset="125.6"/>
<text x="40" y="50" fill="black" font-size="10">Text</text>
</svg>
Несколько цветных секторов
<svg width="300px" height="300px" viewbox="0 0 100 100">
<!-- Центральный круг серый цвет -->
<circle cx="50" cy="50" r="40" fill="#eee"/>
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="grey"/>
<!-- Progress -->
<!-- Пример заполнения секторов Старт 3 часа (дефолтное положение начала рисования окружности)-->
<!-- 100% fill -->
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#2196f3" stroke-dasharray="251.2" stroke-dashoffset="0"/>
<!-- 80% fill -->
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#ff5722" stroke-dasharray="251.2" stroke-dashoffset="50.3"/>
<!-- 70% fill -->
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#009688" stroke-dasharray="251.2" stroke-dashoffset="75.36"/>
<!-- 50% fill -->
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#9c27b0" stroke-dasharray="251.2" stroke-dashoffset="125.6"/>
<!-- 40% fill -->
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#e91e63" stroke-dasharray="251.2" stroke-dashoffset="150.72"/>
<!-- 20% fill -->
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#f44336" stroke-dasharray="251.2" stroke-dashoffset="200.96"/>
<!-- Текст в центре -->
<text x="40" y="50" fill="black" font-size="10">Text</text>
</svg>
$(".progress").each(function() {
var dataProgress = $(this).attr("stroke-dashoffset");
$(this).attr("stroke-dashoffset", "251.2");
$(this).animate({
"stroke-dashoffset": dataProgress
},1500)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<svg width="300px" height="300px" viewbox="0 0 100 100">
<!-- Center color -->
<circle cx="50" cy="50" r="40" fill="#eee"/>
<!-- Default color of ring -->
<circle cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="white"/>
<circle class="progress" cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#2196f3" stroke-dasharray="251.2" stroke-dashoffset="0"/>
<circle class="progress" cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#ff5722" stroke-dasharray="251.2" stroke-dashoffset="50.3"/>
<circle class="progress" cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#009688" stroke-dasharray="251.2" stroke-dashoffset="75.36"/>
<circle class="progress" cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#9c27b0" stroke-dasharray="251.2" stroke-dashoffset="125.6"/>
<circle class="progress" cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#e91e63" stroke-dasharray="251.2" stroke-dashoffset="150.72"/>
<circle class="progress" cx="50" cy="50" r="40" fill="transparent" stroke-width="20" stroke="#f44336" stroke-dasharray="251.2" stroke-dashoffset="200.96"/>
<text x="40" y="50" fill="black" font-size="10">Text</text>
</svg>
Вот решение на d3, все что тут нужно сделать - менять внутренний и внешний радиус у arc-генератора:
.attr('d', d => {
var ir = radius/3 + Math.random()*radius/5;
var or = ir + Math.random()*radius/5;
return arc.innerRadius(ir).outerRadius(or)(d)
})
var data = [ Math.random(), Math.random(), Math.random(), Math.random()]
var width = 260;
var height = 260;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory10);
var svg = d3.select("body")
.append('svg')
.attr('viewBox', `${-width/2} ${-height/2} ${width} ${height}`)
var arc = d3.arc();
var pie = d3.pie()
.value(d => d )
.sort(null);
var path = svg.selectAll('path')
.data(pie(data))
.enter()
.append("g")
.append('path')
.attr('d', d => {
var ir = radius/3 + Math.random()*radius/5;
var or = ir + Math.random()*radius/5;
return arc.innerRadius(ir).outerRadius(or)(d)
})
.attr('fill', (d,i) => color(i))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
когда индекс будет равен 6, нужно обнулить его до 1 и чтобы он продолжил увеличивать себя до 6 и снова уменьшил себя до 1
Всем доброго времени сутокДелаю простое приложение на React-Redux, опыта с React немного
Необходимо обратиться к вложенному свойству объекта js, имя которого задано переменнойОбщая картина такова: