murri

 
安装
npm install murri —save
 
如果需要drag,需要依赖hammer.js,可以通过js script引入:
 
 
使用
HTML
最少需要class为grid、item、item-content的div,其中grid的作用是自适应布局,item是区分每个元素,item-content用于动画设置;
<div class="grid">
    <div class="item">
        <div class="item-content">
            <!-- Safe zone, enter your custom markup -->
            This can be anything.
            <!-- Safe zone ends -->
        </div>
    </div>
 
    <div class="item">
        <div class="item-content">
        <!-- Safe zone, enter your custom markup -->
            <div class="my-custom-content">
            Yippee!
            </div>
        <!-- Safe zone ends -->
        </div>
    </div>
<div>
 
CSS
grid必须为relative,item必须为block以及absolute;另外item之间可以设置gap
.grid {
    position: relative;
}
.item {
    display: block;
    position: absolute;
    width: 48%;
    height: 200px;
    padding: 5px;
    margin: 10px;
    z-index: 1;
    background: #ccc;
    color: #fff;
}
.item.muuri-item-dragging {
    z-index: 3;
}
.item.muuri-item-releasing {
    z-index: 2;
}
.item.muuri-item-hidden {
    z-index: 0;
}
.item-content {
    position: relative;
    width: 100%;
    height: 100%;
}
 
Javascript
Muuri是一个构造函数,第一个参数接受一个元素或者字符串(内置了querySelector):
var grid = new Muuri('.grid');
如上是最简单的方式,这样就可以看到效果了,如果希望拖拽,可以做如下配置:
var grid = new Muuri('.grid’, {
    dragEnabled: true
});
即Muuri的第二个参数是一个object,默认的dragEnabled为false,所以如果希望拖动,需要设置为true。
 
 
配置
如果不做任何配置,则默认配置为:
{
  // Item elements
  items: '*',
 
  // Default show animation
  showDuration: 300,
  showEasing: 'ease',
 
  // Default hide animation
  hideDuration: 300,
  hideEasing: 'ease',
 
  // Item's visible/hidden state styles
  visibleStyles: {
    opacity: '1',
    transform: 'scale(1)'
  },
  hiddenStyles: {
    opacity: '0',
    transform: 'scale(0.5)'
  },
 
  // Layout
  layout: {
    fillGaps: false,
    horizontal: false,
    alignRight: false,
    alignBottom: false,
    rounding: true
  },
  layoutOnResize: 100,
  layoutOnInit: true,
  layoutDuration: 300,
  layoutEasing: 'ease',
 
  // Sorting
  sortData: null,
 
  // Drag & Drop
  dragEnabled: false,
  dragContainer: null,
  dragStartPredicate: {
    distance: 0,
    delay: 0,
    handle: false
  },
  dragAxis: null,
  dragSort: true,
  dragSortInterval: 100,
  dragSortPredicate: {
    threshold: 50,
    action: 'move'
  },
  dragReleaseDuration: 300,
  dragReleaseEasing: 'ease',
  dragHammerSettings: {
    touchAction: 'none'
  },
 
  // Classnames
  containerClass: 'muuri',
  itemClass: 'muuri-item',
  itemVisibleClass: 'muuri-item-shown',
  itemHiddenClass: 'muuri-item-hidden',
  itemPositioningClass: 'muuri-item-positioning',
  itemDraggingClass: 'muuri-item-dragging',
  itemReleasingClass: 'muuri-item-releasing'
}
 
布局:
layout: {
    fillGaps: false,
    horizontal: false,
    alignRight: false,
    alignBottom: false,
    rounding: true
},
如上配置指定的布局的默认排列方式 - 从左上方开始排还是从右上方开始排、从上往下排还是从左往右排,在这里都是可以指定的;
 
排序:
HTML
    <div class="grid">
        <div class="item" data-sort="4">
            <div class="item-content">
            one
            </div>
        </div>
        <div class="item" data-sort=“3">
            <div class="item-content">
            two
            </div>
        </div>
        <div class="item" data-sort=“2">
            <div class="item-content">
            three
            </div>
        </div>
        <div class="item" data-sort=“1">
            <div class="item-content">
            four
            </div>
        </div>
    </div>
 
Javascript
sortData: {
    foo: function (item, element) {
        let sortId = element.getAttribute('data-sort');
        return Number(sortId);
    }
},
 
grid.sort('foo');
 
如上所示我们可以在item上设置自定义属性data-sort,然后依次作为排序的依据;
 
拖动:
dragStartPredicate: {
    distance: 0,
    delay: 0,
    handle: '.drag-btn'
},
distance表示开始拖动前移动的距离,默认为0;delay表示拖动的延时;handle默认为false,认为整个item都是可以拖动的,但也可以接受一个字符串,使用querySelecor查询,这样我们就可以在每个item右上角设置一个按钮,只有点击这个按钮才能拖动;
 
拖动方向:
dragAxis: ‘x'
表示只能在x方向拖动,也可以设置为’y’,默认为null,表示x和y方向都可以拖动;
 
拖动排序:
dragSort: true,
表示是否允许拖动之后重新排序,默认是true,如果设置为false,那么就只能排序而不能更改位置;
 
拖动排序间隔:
dragSortInterval: 200
默认是200ms,这个值表示拖动之后每隔多少时间进行判断是否能够排序,显然这个时间越长,则排序进行的越缓慢,所以可以设置为0;
 
拖动排序断定:
dragSortPredicate: {
    threshold: 50,
    action: 'swap'
},
默认的action是move,但是对于拖动排序来说这种效果并不好,而swap的效果往往会更好一些 - 比如看板有两列,某列的上下两个元素之间可以直接拖动替换位置,即为swap;而threshold表示交换阈值,取值在0 - 100,这里的50表示当两个item之间交叉的部分超过50%时,就触发swap;
 
拖动释放动画时间:
dragReleaseDuration: 0,
这里的默认值是300,即在拖动释放之后从释放位置到正确位置移动的时间,如果设置为0表示释放之后会立即回到原位,这种效果在交互上也是非常不错的;
 
拖动释放动画:
dragReleaseEasing: 'ease',
就释放拖动之后回到原位的动画效果,默认为’ease’,也可设置为 ‘ease-out’ 等;
 
一些默认的class名称:
containerClass: 'muuri',
itemClass: 'muuri-item',
itemVisibleClass: 'muuri-item-shown',
itemHiddenClass: 'muuri-item-hidden',
itemPositioningClass: 'muuri-item-positioning',
itemDraggingClass: 'muuri-item-dragging',
itemReleasingClass: 'muuri-item-releasing'
这些名称都是可以根据自己的需要进行修改的;
 
我所需要的最终的配置为:
var grid = new Muuri('.grid', {
    layoutDuration: 600,
    sortData: {
        foo: function (item, element) {
            let sortId = element.getAttribute('data-sort');
            return Number(sortId);
        }
    },
    dragEnabled: true,
    dragStartPredicate: {
        distance: 0,
        delay: 0,
        handle: '.drag-btn'
    },
    dragAxis: null,
    dragSort: true,
    dragSortInterval: 0,
    dragSortPredicate: {
        threshold: 50,
        action: 'swap'
    },
    dragReleaseDuration: 200,
    dragReleaseEasing: 'ease',
});
 
grid.sort('foo');
 
 
Grid方法
Grid即通过 new Muuri() 或得到的实例,该实例默认有一些方法可以调用,下面一一介绍:
 
获取grid
var elem = grid.getElement()
获取grid这个element
 
获取item
var allItems = grid.getItems() // 获取到所有的item
 
var activeItems = grid.getItems().filter(function (item) {
  return item.isActive();
}); // 获取到active的item,即显示出来的item,这个active是在配置项中 items 中指定的,默认是 ‘*’
 
var firstItem = grid.getItems()[0]; // 获取到第一个item
 
更新item
grid.refreshItems(); // 更新所有的Item,主要是缓存的维度
grid.refreshItems([0, someElem, someItem]) // 更新特定的Item
 
同步DOM
grid.synchronize()
同步DOM元素,保证DOM的顺序结构和页面显示的顺序结构一致。如果我们使用了排序函数使得item顺序变化,但这时看DOM实际上是没有变的,所以如果希望保持一致就可以使用grid.synchronize()函数;
 
布局
grid.layout() // 根据配置项布局
grid.layout(true) // 根据配置项无动画的直接布局
grid.layout(function (items) {
    console.log(‘layout done');
}); // 布局,并定义回调函数,如果所有item布局结束即调用该回调函数
 
添加Item
Item可以通过grid.add(elements, [options])的方式添加到grid中,添加的过程中默认是添加到最后,添加之后会自动触发grid.layout(),另外如果你希望同步DOM可以使用grid.synchronize()来同步:
grid.add([elemA, elemB]) // 添加两个新的items到grid末尾
grid.add([elemA, elemB], { index: 0 }) // 添加两个新的items到grid开头
grid.add([elemA, elemB], { layout: false }) // 跳过自动layout
 
移除Item
grid.remove(0); // 移除第一个Item,但是该元素保持在DOM中
grid.remove([elemA, elemB], { removeElements: true }); // 移除Items以及相关的元素
grid.remove([elemA, elemB], { layout: false }); // 移除Items,并禁止layout
 
显示和隐藏
grid.show();
grid.hide();
 
过滤Item
grid.filter(function (item) {
    return item.getElement().hasAttribute(‘data-foo');
}); // 展示所有拥有data-foo属性的item
grid.filter(‘[data-foo]’); // 上述简写
grid.filter(‘.good’); // 展示有class为good的Items
 
Items排序
对Items排序, 有三种方式可以对Items进行排序;
//第一种排序方式: Sort items by data-id attribute value (ascending).
grid.sort(function (itemA, itemB) {
  var aId = parseInt(itemA.getElement().getAttribute('data-id'));
  var bId = parseInt(itemB.getElement().getAttribute('data-id'));
  return aId - bId;
});
 
//第二种排序方式  Sort items using the sort data keys (ascending).
grid.sort('foo bar’, {descending: true});
 
//第三种排序方式 Sort items with a presorted array of items.
grid.sort(presortedItems);
 
 
 
移动Items
grid.move(elemA, elemB, {action: ’swap'}); // 将elemA移动到elemB的位置,使用交换的方式
grid.move(0, -1); 将第一个Item移动到最后一个位置
 
移动Items到另外一个grid
gridA.send(0, gridB, -1); // 将gridA中的第一个Item移动到gridB中的最后位置,移动之后将会append到document.body后
 
销毁grid
grid.destroy(); // 销毁grid
grid.destroy(true); // 销毁grid并移除Item元素
 
 
 
Grid事件
在操作grid时会触发各种各样的事件,这里我们需要一一介绍:
 
同步:
在grid.synchronize();调用之后会触发下面的回调函数:
grid.on('synchronize', function () {
    console.log('Synced')
})
 
 
布局开始/结束:
在grid.layout()调用开始和之后触发下面的回调函数:
grid.on('layoutStart', function () {
    console.log('start')
})
grid.on('layoutEnd', function () {
    console.log('end');
});
 
添加Items触发下面的回调函数:
grid.on('add', function (items) {
  console.log(items);
});
 
移除Items触发下面的回调函数:
grid.on('remove', function (items, indices) {
  console.log(items, indices);
});
 
在grid开始show和结束show之后触发回调函数:
grid.on('showStart', function (items) {
  console.log(items);
});
 
grid.on('showEnd', function (items) {
  console.log(items);
});
 
在grid开始hide和结束hide之后触发回调函数:
grid.on('hideStart', function (items) {
  console.log(items);
});
 
grid.on('hideEnd', function (items) {
  console.log(items);
});
 
在grid.filter()函数调用之后触发:
grid.on('filter', function(shownItems, hiddenItems) {
    console.log('shown', shownItems)
    console.log('hidden', hiddenItems)
});
grid.filter('.table');
 
在grid.sort()函数调用之后触发:
grid.on('sort', function (currentOrder, previousOrder) {
    console.log('目前的顺序', currentOrder);
    console.log('之前的顺序', previousOrder);
});
grid.sort('foo');
 
在grid.move()函数调用之后触发:
grid.on('move', function (data) {
  console.log(data);
});
 
与grid.send()函数调用触发的相关事件:
grid.on('send', function (data) {
  console.log(data);
});
grid.on('beforeSend', function (data) {
  console.log(data);
});
grid.on('receive', function (data) {
  console.log(data);
});
grid.on('beforeReceive', function (data) {
  console.log(data);
});
 
 
drag相关事件
 
grid.on('dragInit', function (item, event) {
    console.log('拖拽初始化', event, item);
});
grid.on('dragStart', function (item, event) {
    console.log('拖拽开始', event, item);
});
grid.on('dragMove', function (item, event) {
    console.log('拖拽移动', event, item);
});
grid.on('dragScroll', function (item, event) {
    console.log('拖拽Scroll', event, item);
});
grid.on('dragInit', function (item, event) {
    console.log('拖拽初始化', event, item);
});
grid.on('dragEnd', function (item, event) {
    console.log('拖拽结束', event, item);
});
 
如果要记录拖拽的顺序,下面的事件尤为重要:
 
grid.on('dragStart', function (item, event) {
    console.log('拖拽开始 grid items', grid.getItems());
});
grid.on('dragEnd', function (item, event) {
    console.log('拖拽结束 grid items', grid.getItems());
});
 
drag释放
grid.on('dragReleaseStart', function (item) {
  console.log(item);
});
grid.on('dragReleaseEnd', function (item) {
  console.log(item);
});
 
drag销毁
grid.on('destroy', function () {
  console.log('Muuri is no more...');
});
 
 
Item 方法
每个Item都有相关的方法可以调用,下面一一介绍:
 
获取grid
var grid = item.getGrid();
 
获取Item对应的Element
var elem = item.getElement();
 
获取Item的宽度
var width = item.getWidth();
 
获取Item的高度
var height = item.getHeight();
 
获取Item的margin
var margin = item.getMargin();
 
获取Item相对于container元素的left和top值
var position = item.getPosition();
其中position是一个对象,有left和top属性,都是number类型的数字;
 
判断某个Item是否active
var isActive = item.isActive();
 
判断某个Item是否可见:
var isVisible = item.isVisible();
 
判断某个Item是否正在被拖拽:
var isDragging = item.isDragging();
 
判断某个Item是否已经被释放:
var isReleasing = item.isReleasing();
 
判断某个Item是否被销毁:
var isDestroyed = item.isDestroyed();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
上一篇:c++ Primer 第四版 第一阶段 const总结


下一篇:WinForm 制作一个简单的计算器