I am creating an org chart with thousands of nodes but created a sample example here,
https://jsfiddle.net/jy6j87g0/2/
As you can see zooming and panning is working but I would like to make it work like one here,
http://live.yworks.com/demobrowser/index.html#Organization-Charts
To be specific
I am trying to make my fiddle,
I am struggling to find where to start, should I look further into CSS transformation or use d3.js instead and create everything from scratch.
Link to library
- https://github.com/dabeng/OrgChart
'use strict';
(function($) {
$(function() {
var datascource = {
'name': 'Lao Lao',
'title': 'general manager',
'children': [{
'name': 'Bo Miao',
'title': 'department manager'
}, {
'name': 'Su Miao',
'title': 'department manager',
'children': [{
'name': 'Tie Hua',
'title': 'senior engineer'
}, {
'name': 'Hei Hei',
'title': 'senior engineer',
'children': [{
'name': 'Pang Pang',
'title': 'engineer'
}, {
'name': 'Xiang Xiang',
'title': 'UE engineer'
}]
}]
}, {
'name': 'Yu Jie',
'title': 'department manager'
}, {
'name': 'Yu Li',
'title': 'department manager'
}, {
'name': 'Hong Miao',
'title': 'department manager'
}, {
'name': 'Yu Wei',
'title': 'department manager'
}, {
'name': 'Chun Miao',
'title': 'department manager'
}, {
'name': 'Yu Tie',
'title': 'department manager'
}]
};
$('#chart-container').orgchart({
'data': datascource,
'nodeContent': 'title',
'pan': true,
'zoom': true
})
.on('touchmove', function(event) {
event.preventDefault();
});
});
})(jQuery);
<link href="https://cdn.rawgit.com/FortAwesome/Font-Awesome/master/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://dabeng.github.io/OrgChart/css/style.css" rel="stylesheet"/>
<link href="https://dabeng.github.io/OrgChart/css/jquery.orgchart.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script src="https://dabeng.github.io/OrgChart/js/jquery.orgchart.js"></script>
<div id="chart-container">
</div>
The code snippet below fulfills the 3 requirements set out in your question:
The transform matrix and the mouse position observed in the mousemove
event handler are stored in module variables, and used later in the wheel
event handler.
In my tests, the wheel
event was always triggered after the scaling had been processed by OrgChart. If this processing order is not the same in your case, or not stable, you can wrap the code of the wheel
event handler in a setTimeout(fn, 0)
construct to make sure that the scaling has already been performed by OrgChart:
.on("wheel", function (event) {
setTimeout(function () {
// Process the event after OrgChart
(put the code here)
}, 0);
}
'use strict';
(function ($) {
$(function () {
var datascource = {
'name': 'Lao Lao',
'title': 'general manager',
'children': [{
'name': 'Bo Miao',
'title': 'department manager'
}, {
'name': 'Su Miao',
'title': 'department manager',
'children': [{
'name': 'Tie Hua',
'title': 'senior engineer'
}, {
'name': 'Hei Hei',
'title': 'senior engineer',
'children': [{
'name': 'Pang Pang',
'title': 'engineer'
}, {
'name': 'Xiang Xiang',
'title': 'UE engineer'
}]
}]
}, {
'name': 'Yu Jie',
'title': 'department manager'
}, {
'name': 'Yu Li',
'title': 'department manager'
}, {
'name': 'Hong Miao',
'title': 'department manager'
}, {
'name': 'Yu Wei',
'title': 'department manager'
}, {
'name': 'Chun Miao',
'title': 'department manager'
}, {
'name': 'Yu Tie',
'title': 'department manager'
}]
};
var MIN_ZOOM = 0.25; // Mimimum value for scaling
var defaultMatrix = [1, 0, 0, 1, 0, 0]; // Chart at normal scaling and position
var prevMatrix = defaultMatrix;
var prevPosition = { x: 0, y: 0 };
var parseNumber = function (str) {
return parseFloat(str.replace(/[^\d\.\-]/g, ""));
}
var getTransformMatrix = function () {
var transform = $(".orgchart").css("transform");
if (transform !== 'none') {
var tokens = transform.split(",");
var matrix = [];
for (var i = 0; i < tokens.length; i++) {
matrix.push(parseNumber(tokens[i]));
}
return matrix;
} else {
return null;
}
};
var setTransformMatrix = function (matrix) {
$(".orgchart").css("transform", "matrix(" + matrix.join(",") + ")");
prevMatrix = matrix;
};
var getMousePosition = function (event) {
var rect = $(".orgchart")[0].getBoundingClientRect();
return {
x: event.clientX - rect.left - rect.width / 2,
y: event.clientY - rect.top - rect.height / 2
}
};
$("#btnReset").click(function () {
setTransformMatrix(defaultMatrix);
});
$("#chart-container").orgchart({
'data': datascource,
'nodeContent': 'title',
'pan': true,
'zoom': true
}).on("touchmove", function (event) {
event.preventDefault();
}).on("mousemove", function (event) {
// Remember transform matrix and mouse position
prevMatrix = getTransformMatrix() || prevMatrix;
prevPosition = getMousePosition(event);
}).on("wheel", function (event) {
// In my tests, this event is triggered after processing has been done by OrgChart
// If not the case, the following code can be wrapped in setTimeout(fn, 0) call
var $this = $(this);
var matrix = getTransformMatrix();
if (matrix) {
var $orgchart = $(".orgchart");
// Prevent scaling below minimum zoom
matrix[0] = Math.max(matrix[0], MIN_ZOOM);
matrix[3] = Math.max(matrix[3], MIN_ZOOM);
var position = getMousePosition(event);
// Calculate expected mouse position with new scaling
// corresponding to previous mouse position with old scaling
var expectedPosition = {
x: prevPosition.x * matrix[0] / prevMatrix[0],
y: prevPosition.y * matrix[3] / prevMatrix[3]
};
// Translate chart position to match the expected position
matrix[4] += position.x - expectedPosition.x;
matrix[5] += position.y - expectedPosition.y;
setTransformMatrix(matrix);
prevPosition = expectedPosition;
}
});
});
})(jQuery);
#btnReset
{
position: absolute;
left: 16px;
top: 16px;
z-index: 1000;
}
<link href="https://cdn.rawgit.com/FortAwesome/Font-Awesome/master/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://dabeng.github.io/OrgChart/css/style.css" rel="stylesheet" />
<link href="https://dabeng.github.io/OrgChart/css/jquery.orgchart.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script src="https://dabeng.github.io/OrgChart/js/jquery.orgchart.js"></script>
<button id="btnReset">Reset</button>
<div id="chart-container">
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With