前段时间做的项目,整理一下,大致的功能就是系统需要呈现很多监控图,这些图我们想让用户来自定义数量,大小以及怎么摆放。用户把我们准备好的动态概览图的缩略图拖拽到画布上,并且在画布上任意摆放,摆放完毕后,我们就能给用户呈现自定义的动态概览图了。
原理就是:通过ngDraggable来实现组件拖拽,Packery来实现页面布局,通过iframe嵌套Grafana来实现展示,从而实现用户的个性化需求。
出发点就是摒弃传统图表的排版格式,让用户可以自定义图表的大小和位置,用户可以自定义多套概览模式。
先介绍下用到的各项技术:
Packery: JavaScript布局的一个装箱算法库。Packery布局可以智能排序,元素可以拖动到适合一个理想的地点,很容易创建不同类型的动态网格布局.使用之前需要下载相关类库文件,下载地址:https://download.csdn.net/download/qq_34527715/10320870,也可以去官网下载,官网:https://packery.metafizzy.co/。
另附一个packery的小程序:http://wow.techbrood.com/fiddle/35696
ngDraggable:可以实现元素的拖动,在菜鸟发现一个小例子:http://www.runoob.com/try/try.php?filename=jqueryui-example-droppable-photo-manager。同样使用需要引入相关JS文件,也需要在代码中加入ngDraggable模块。
Grafana:只要用到了仪表盘展示功能,grafana可以提供一个链接,在HTML中用iframe嵌入便可访问。如下:
<iframe src="仪表盘链接地址" frameborder="0" scrolling="no"></iframe>
下面介绍具体代码:
1.拖拽模块
<li ng-drag="true" class="samplechart" ng-drag-data="chart" ng-repeat="chart in charts">
<div class="dashboard-corner-label" ng-click="delDashboardRes($index)"><i class="fa fa-trash"></i></div>
<img ng-src="{{ picUrl + chart.demoPicture}}"
class="checkboximg ui-draggable" style="position: relative;">
</li>
<div id="canvas" class="grid" ng-drop="true" ng-drop-success="dropComplete($index,$data,$event)">
<div class="grid-item" ng-repeat="item in viewLists" title="双击删除图片"
style="position: absolute; height:{{item.style.height}};width:{{item.style.width}};
left:{{item.style.left}};top:{{item.style.top}};" id="{{item.url}}">
<img ng-src="{{item.style.src}}" style="width: 100%; height: 100%;">
</div>
</div>
$scope.dropComplete = function (index, obj) {
.....
};
可拖动元素,ng-drag="true" ng-drag-data。 可放置元素:ng-daop="true",放置后出发方法dropComplete.
2.Packery的使用:
首先初始化packery模块:
$scope.grid = document.querySelector('.grid');
$scope.pckry = new Packery('.grid', {
itemSelector: '.grid-item',
gutter: 7,
columnWidth: 7
});
上面这段代码意思是,凡是在.grid内,class为grid-item的元素,都会添加packery属性。然后我们在元素拖拽完成后,给后来添加的元素赋上packery属性:
function getItemElement(obj) {
var itemElem = document.createElement('div');
var img = new Image();
img.src = $scope.picUrl + obj.demoPicture;
img.style.width = "100%";
img.style.height = "100%";
itemElem.append(img);
itemElem.id = obj.url;
itemElem.title = "双击删除图片";
itemElem.className = 'grid-item ';
itemElem.style.width = obj.width + "%";
itemElem.style.height = obj.height + "%";
return itemElem;
}
function makeItemDraggable(itemElem) {
var draggie = new Draggabilly(itemElem);
$scope.pckry.bindDraggabillyEvents(draggie);
}
$scope.dropComplete = function (index, obj) {
$scope.grid = document.querySelector('.grid');
var itemElems = [
getItemElement(obj);//这个方法是给图片添加样式和对应的grafanaURL
];
// append to grid via document fragment
var fragment = document.createDocumentFragment();
itemElems.forEach(function (itemElem) {
fragment.appendChild(itemElem)
});
$scope.grid.appendChild(fragment);
// add to packery & make draggable
$scope.pckry.appended(itemElems);
itemElems.forEach(makeItemDraggable);
};
3.最后我们通过iframe来嵌套grafana.把动态图展现出来:
<iframe width="100%" height="100%" src="{{item.url | trustAsResourceUrl}}" frameborder="0" scrolling="no"></iframe>
4.还有些图grafana做的不是很完美,我们可以借助hignCharts或者eCharts来画。