| https://cdn.jsdelivr.net/npm/d3@7 - библиотека d3 v.7 |
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script> |
Bitrix\Main\Page\Asset::getInstance()->addJs(SITE_TEMPLATE_PATH . "/js/d3.v7.min.js"); |
Основные методы работы
выбрать svg
var svg = d3.select("svg"); |
var svg = d3.select("#familyTree").append("svg"); |
svg.attr("width", 1000);
svg.attr("height", 300); |
var svg = d3.select("#familyTree").append("svg")
.attr("width", 1000)
.attr("height", 300); |
Шкала X
//Создание шкалы для оси X
const xScale = d3.scaleLinear()
.domain([0, 10]) // минимальное и максимальное значение
.range([0, 500]); // ширина графика
// Создание оси X
const xAxis = d3.axisBottom(xScale);
// Добавление оси X
svg.append("g")
.attr("transform", "translate(30,0)") //чтобы текст от шкалы влазил
.call(xAxis);
|
//Создание шкалы для оси Y
const yScale = d3.scaleLinear()
.domain([0, 100]) // минимальное и максимальное значение
.range([300, 0]); // // ширина графика
// Создание оси Y
const yAxis = d3.axisLeft(yScale);
// Добавление оси Y
svg.append("g")
.attr("transform", "translate(30,0)")
.call(yAxis); |
var data = [22, 25, 28, 32, 30, 28, 27];
var line = d3.line()
.x((d, i) => xScale(i*100))
.y(d => yScale(d*10))
.curve(d3.curveMonotoneX); //можно не указывать, будет ломаная линия
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("transform", "translate(30,0)")
.attr("d", line); |
Создание гистограммы
data = [20, 100, 60, 40, 70];
var barWidth = 20; // Ширина столбика гистограммы
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("width", barWidth)
.attr("height", d => d)
.attr("transform", "translate(30,0)")
.attr("x", (d, i) => barWidth * i)
|
data = [10, 20, 30, 40, 50];
var circles = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.style("fill", "steelblue")
.attr("r", function(d) { return (d+5); })
.attr("cx", function(d) { return Math.random() * 1000; })
.attr("cy", d => d*2); |
Примеры работы с d3.treemap
Пример 1

файл test.csv
name,parent,value Origin,, rect1,Origin,112 rect2,Origin,23 rect3,Origin,11 rect4,Origin,40 rect5,Origin,300 rect6,Origin,25 |
//отступы
const margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 445 - margin.left - margin.right,
height = 445 - margin.top - margin.bottom;
// добавляем svg
const svg = d3.select("#familyTree")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// читаем csv
d3.csv("<?=$this->GetFolder()?>/test.csv").then(function(data) { //$this->GetFolder() - битриксовский путь к папке
/*console.log(data); выдаст
0: {name: 'Origin', parent: '', value: ''}
1: {name: 'rect1', parent: 'Origin', value: '112'}
2: {name: 'rect2', parent: 'Origin', value: '23'}
3: {name: 'rect3', parent: 'Origin', value: '11'}
4: {name: 'rect4', parent: 'Origin', value: '40'}
5: {name: 'rect5', parent: 'Origin', value: '300 '}
6: {name: 'rect6', parent: 'Origin', value: '25'}
columns: ['name', 'parent', 'value']
*/
// переформатирование данных
const root = d3.stratify()
.id(function(d) { return d.name; }) // столбец name
.parentId(function(d) { return d.parent; }) // столбец parent
(data);
root.sum(function(d) { return +d.value }) // сумма колонок value
// d3.treemap вычисляет положение каждого элемента иерархии
// Координаты добавляются к корневому объекту выше
d3.treemap()
.size([width, height])
.padding(4)
(root)
//добавляем прямоугольники
svg
.selectAll("rect")
.data(root.leaves())
.join("rect")
.attr('x', function (d) { return d.x0; })
.attr('y', function (d) { return d.y0; })
.attr('width', function (d) { return d.x1 - d.x0; })
.attr('height', function (d) { return d.y1 - d.y0; })
.style("stroke", "#371722") //обводка
.style("fill", "#e5e0db"); //фон
// добавляем текст label в прямоугольники
svg
.selectAll("text")
.data(root.leaves())
.join("text")
.attr("x", function(d){ return d.x0+15}) //координата x
.attr("y", function(d){ return d.y0+25}) //координата y
.text(function(d){ return d.data.name}) //из столбца name
.attr("font-size", "15px") //размер шрифта
.attr("fill", "#371722") //цвет текста
}); |

const treeData =
{"name": "Петр",
"value": 15,
"type": "black",
"level": "blue",
"children": [
{
"name": "Василий",
"value": 10,
"type": "grey",
"level": "blue"
},
{
"name": "Екатерина",
"value": 10,
"type": "grey",
"level": "red",
"children": [
{
"name": "Дмитрий",
"value": 7.5,
"type": "grey",
"level": "blue"
},
{
"name": "Евгений",
"value": 7.5,
"type": "grey",
"level": "blue"
},
{
"name": "Арсений",
"value": 7.5,
"type": "grey",
"level": "blue"
},
{
"name": "Валерий",
"value": 7.5,
"type": "grey",
"level": "blue"
}
]
},
{
"name": "Мария",
"value": 10,
"type": "grey",
"level": "red"
},
{
"name": "Ольга",
"value": 10,
"type": "grey",
"level": "red",
"children": [
{
"name": "Александр",
"value": 7.5,
"type": "grey",
"level": "blue"
}
]
},
{
"name": "Вероника",
"value": 10,
"type": "grey",
"level": "red"
}
]};
// размеры и отступы
const margin = {top: 20, right: 90, bottom: 30, left: 90},
width = 660 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// слой дерева
const treemap = d3.tree().size([height, width]);
// конструируем иерархические данные из treeData
let nodes = d3.hierarchy(treeData);
// узлы дерева вставляем наше дерево
nodes = treemap(nodes);
const svg = d3.select("#familyTree").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const g = svg.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
// соединения между узлами
const link = g.selectAll(".link")
.data( nodes.descendants().slice(1))
.enter().append("path")
.attr("class", "link")
.style("stroke", d => d.data.level)
.attr("d", d => {
return "M" + d.y + "," + d.x
+ "C" + (d.y + d.parent.y) / 2 + "," + d.x
+ " " + (d.y + d.parent.y) / 2 + "," + d.parent.x
+ " " + d.parent.y + "," + d.parent.x;
});
// узлы
const node = g.selectAll(".node")
.data(nodes.descendants())
.enter().append("g")
.attr("class", d => "node" + (d.children ? " node--internal" : " node--leaf"))
.attr("transform", d => "translate(" + d.y + "," + d.x + ")");
// кружки
node.append("circle")
.attr("r", d => d.data.value)
.style("stroke", d => d.data.type)
.style("fill", d => d.data.level);
// текст-подписи
node.append("text")
.attr("dy", ".35em")
.attr("x", d => d.children ? (d.data.value + 5) * -1 : d.data.value + 5)
.attr("y", d => d.children && d.depth !== 0 ? -(d.data.value + 5) : d.data.value)
.style("text-anchor", d => d.children ? "end" : "start")
.text(d => d.data.name); |