avalon js实现仿微博拖动图片排序


Posted in Javascript onAugust 14, 2015

下文针对仿微博图片随意拖动,调整图片的顺序,讲解的很详细,文章肯定还有欠缺的地方,欢迎提出批评改正。废话不多说了,看具体内容吧。

点击此处进入源码下载

什么是拖动图片排序?

就像微博这种,上传后允许用户通过拖动图片,调整几张图片的顺序。

avalon js实现仿微博拖动图片排序

可以看到微博在这里把每张图片固定了尺寸,稍微严谨点的话,就需要像上一篇文章那样,外面是响应式的等高等宽的若干div容器,里面则是等比例缩放的响应式图片。

下面说下要求。

1.当然首先图片要可以拖动。

2.图片移出其原本的位置,拖动到目标位置并且未松开鼠标完成拖动前,需要在目标位置设置占位符,让用户预览拖动完成后的效果。

3.响应式。尺寸改变后,仍然可以完成上面要求。

4.尽可能兼容更多的浏览器。实际上,写上一篇文章就是为这篇做铺垫的,所以这里也是兼容到ie7.

最终效果

chrome

avalon js实现仿微博拖动图片排序

ie8

avalon js实现仿微博拖动图片排序

ie7

avalon js实现仿微博拖动图片排序

首先是拖动。

这里用的代理,即在原本的布局中多了个div,实际拖动的对象就是这个div.具体的,

<div id='wrap' ms-controller='drag_sort' class='ms-controller'>
 <ul ms-mousemove='drag_move($event)'>
 <li ms-repeat='photo_list'>
 <div ms-mousedown='start_drag($event,$index,el)'>
  <div class="dummy"></div>
  <p ms-attr-id='wrap_img{{$index}}'><img ms-attr-src="el.src"><i></i></p>
 </div>
 </li>
 </ul>
 <div id='drag_proxy'></div>
 </div>

对每个单元格绑定mousedown,触发start_drag时,把单元格里的img放到代理<div id='drag_proxy'></div>里面,同时获取图片的大小,记下当前鼠标点击的位置,并以点击位置为代理div矩形(图片)的中心点,显示代理,隐藏点击的图片。

avalon js实现仿微博拖动图片排序

start_drag:function(e,i,el){
 var img=$('wrap_img'+i).firstChild,target_img_width=img.clientWidth,target_img_height=img.clientHeight;
 drag_sort.cell_size=$('wrap_img0').clientWidth;
 var xx=e.clientX-target_img_width/2,yy=e.clientY-target_img_height/2,offset=avalon($(drag_sort.container)).offset(),target=e.target.parentNode.parentNode.parentNode; 
 $('drag_proxy').style.top=yy+avalon(window).scrollTop()-offset.top+'px';
 $('drag_proxy').style.left=xx-offset.left+'px';
 $('drag_proxy').style.width=target_img_width+'px';
 $('drag_proxy').style.height=target_img_height+'px';
 if(target&&target.nodeName=='LI'){
  ori_src=el;
  // $('drag_proxy').innerHTML=target.querySelector('p').innerHTML;
  $('drag_proxy').innerHTML=$('wrap_img'+i).innerHTML;
  $('drag_proxy').style.display='block';
  drag_sort.target_index=i;
  drag_flag=true;
 }
 if(isIE)
  target.setCapture();
 avalon.bind(document,'mouseup',function(){
  up(target);
 });
 e.stopPropagation();
 e.preventDefault();
 }

注意几点:

1.drag_sort.cell_size记录当前单元格的尺寸,这里宽高比是1:1,因为布局是响应式,所以需要记录。后面可以看到这个怎么用。

2.事件的target需要判断是不是img标签触发的,因为有可能点击位置是单元格与图片间的空白区域。

3.ori_src用来保存当前单元格的图片,因为后面mousemove的时候会删除图片原本位置的单元格。

4.drag_sort.target_index记录当前单元格的index,后面会比较这个index和代理移动到的单元格的index.

5.drag_flag表示是否可以mousemove了。

6.对于ie,必须target.setCapture();,否则

avalon js实现仿微博拖动图片排序

可以看到拖动的时候会执行浏览器的默认行为。

7.event.preventDefault();也必须加上,否则也会出现浏览器的默认行为,比如firefox拖动图片时,会打开新标签页,显示图片。

然后是mousemove,这里绑定在ul标签上。像mousemove,mouseup事件通常都绑定在若干需要触发元素的公共父元素上,这样就减少了事件绑定的对象了。

具体的

drag_move:function(e){
 if(drag_flag){
  var xx=e.clientX,yy=e.clientY,offset=avalon($(drag_sort.container)).offset();
  var x=xx-offset.left,y=avalon(window).scrollTop()+yy-offset.top;
  var x_index=Math.floor(x/drag_sort.cell_size),y_index=Math.floor(y/drag_sort.cell_size),move_to=3*y_index+x_index;
  $('drag_proxy').style.top=y-drag_sort.cell_size/2+'px';
  $('drag_proxy').style.left=x-drag_sort.cell_size/2+'px';
  if(move_to!=drag_sort.target_index){
  drag_sort.photo_list.removeAt(drag_sort.target_index);
  drag_sort.photo_list.splice(move_to,0,{src:'1.jpg'});
  drag_sort.target_index=move_to;
  }
 }
 e.stopPropagation();
 }

几点说明

1.drag_flag保证必须先触发mousedown后,才可以触发mousemove.

2.drag_sort.container是整个布局的根元素,这里是<div id='wrap'></div>.

#wrap{
 position: relative;
 max-width: 620px;
 font-size: 0;
 }
 #drag_proxy{
 position: absolute;
 border:1px solid #009be3;
 z-index: 100;
 display: none;
 }

后面计算的时候要把根元素的left,top减掉。

3.计算时avalon(window).scrollTop()浏览器的竖直滚动条也要考虑。

4.每个单元格的尺寸始终是一样的,所以直接光标移动到的位置除以行数,列数,取整,得到目标单元格的index.

5.move_to!=drag_sort.target_index当前光标移到的单元格不是图片原本所在的单元格,删除图片原本位置的单元格,在目标单元格插入占位的单元格,这时拖动的图片还没放进目标单元格,最后更新初始单元格的index.

最后是mouseup

function up(target){
 if(isIE)
 target.releaseCapture();
 var target_index=drag_sort.target_index;
 if(ori_src&&target_index!=-1){
 drag_sort.photo_list.splice(target_index,1);
 drag_sort.photo_list.splice(target_index,0,ori_src);
 }
 drag_holder=null;
 drag_flag=false;
 drag_sort.target_index=-1;
 $('drag_proxy').style.display='none';
 avalon.unbind(document,'mouseup');
 }

判断ori_src&&target_index!=-1目的在于排除在非绑定对象上mouseup这种无效操作。因为是在document上绑定mouseup,就要排除类似于随便在空白处点击这种情况。这时不能对单元格删除,插入。

然后是把各变量设为初始值。

图片效果:

avalon js实现仿微博拖动图片排序

HTML代码:

<div id='post_img' ms-controller='post_img'>
<ul id='post_img_inner' ms-mousemove='onmousemove'>
<li ms-repeat-el="post_img_list" class='inline-block' ms-mousedown='onmousedown($event,$index,el)' ms-attr-id='post_img_item{{$index}}'>
<img ms-src='el' class='uploaded_img'></li>
</ul>
</div>

JS代码:

var drag_holder=null,index=-1,ori_src=null,drag_flag=false;//拖动的代理,原图片,原图片的src
var post_img = avalon.define('post_img', function(vm) {
vm.post_img_list=[];//保存所有图片的src
vm.onmousedown=function(e,i,el){
$('drag_proxy').style.display='block';
var target=e.target.parentNode;
var xx = e.clientX;
var yy = e.clientY;
$('drag_proxy').style.top=yy+'px';
$('drag_proxy').style.left=xx+'px';
if(target&&target.nodeName=='LI'){
ori_src=el;
index=target.getAttribute('id').substring(13);
$('drag_proxy').innerHTML=target.innerHTML;
post_img.post_img_list.splice(i, 1, 'about:blank');
}
drag_flag=true;
};
vm.onmousemove=function(e){
if(drag_flag){//如果点下了图片
var xx = e.clientX;
var yy = e.clientY;
$('drag_proxy').style.top=yy+'px';
$('drag_proxy').style.left=xx+'px';
var x=xx-avalon($('post_img')).offset().left;
var y=yy-avalon($('post_img')).offset().top;
//例子没有考虑滚动条的情况
var x_index=Math.floor(x/100);//图片尺寸100*100
var y_index=Math.floor(y/100);
post_img.post_img_list.splice(index, 1);//删除当前图片的li
var target_index=3*y_index+x_index;//目标图片的位置(3*3)
if(post_img.post_img_list.indexOf('about:blank')!=target_index)
//如果图片数组中没有src=about:blank这个占位置的li
post_img.post_img_list.splice(target_index, 0, 'about:blank');
//添加src=about:blank
index=target_index;
//会触发很多次move,所以触发一次就改动一次
}
};
});
document.onmouseup=function(e){
drag_holder=null;
if(ori_src){
post_img.post_img_list.splice(index, 1);
//删除src=about:blank
post_img.post_img_list.splice(index, 0,ori_src);
//添加原图片
}
$('drag_proxy').style.display='none';
$('drag_proxy').innerHTML='';
drag_flag=false;
};

以上代码实现了avalon js仿微博拖动图片排序的功能,本文写的不好还请见谅。

Javascript 相关文章推荐
javascript的函数
Jan 31 Javascript
jquery提交form表单时禁止重复提交的方法
Feb 13 Javascript
jQuery中:focus选择器用法实例
Dec 30 Javascript
JS扩展方法实例分析
Apr 15 Javascript
利用Angularjs和原生JS分别实现动态效果的输入框
Sep 01 Javascript
javascript字符串对象常用api函数小结(连接,替换,分割,转换等)
Sep 20 Javascript
node.js中实现kindEditor图片上传功能的方法教程
Apr 26 Javascript
js中apply与call简单用法详解
Nov 06 Javascript
微信小程序签到功能
Oct 31 Javascript
ES6 Iterator接口和for...of循环用法分析
Jul 31 Javascript
微信小程序网络请求实现过程解析
Nov 06 Javascript
vue使用prop可以渲染但是打印台报错的解决方式
Nov 13 Javascript
javascript实现显示和隐藏div方法汇总
Aug 14 #Javascript
freemarker判断对象是否为空的方法
Aug 13 #Javascript
数据分析软件之FineReport教程:[5]参数界面JS(全)
Aug 13 #Javascript
在jQuery中使用$而避免跟其它库产生冲突的方法
Aug 13 #Javascript
再JavaScript的jQuery库中编写动画效果的指南
Aug 13 #Javascript
js实现仿网易点击弹出提示同时背景变暗效果
Aug 13 #Javascript
JavaScript生成SQL查询表单的方法
Aug 13 #Javascript
You might like
PHP中UNIX时间戳和日期间的转换与计算实例
2014/11/19 PHP
详解PHP数据压缩、加解密(pack, unpack)
2016/12/17 PHP
stripos函数知识点实例分享
2019/02/11 PHP
PHP实现的AES 128位加密算法示例
2019/09/16 PHP
修改发贴的编辑功能
2007/03/07 Javascript
Dreamweaver jQuery智能提示插件,支持版本提示,支持1.6api
2011/07/31 Javascript
javascript学习笔记(十八) 获得页面中的元素代码
2012/06/20 Javascript
js原生appendChild的bug解决心得分享
2013/07/01 Javascript
Extjs4 Treegrid 使用心得分享(经验篇)
2013/07/01 Javascript
把input初始值不写value的具体实现方法
2013/07/04 Javascript
window.showModalDialog()返回值的学习心得总结
2014/01/07 Javascript
简介JavaScript中toUpperCase()方法的使用
2015/06/06 Javascript
分享jQuery封装好的一些常用操作
2016/07/28 Javascript
JS图片放大效果简单实现代码
2016/09/08 Javascript
js实现上传图片预览方法
2016/10/25 Javascript
获取JavaScript异步函数的返回值
2016/12/21 Javascript
微信小程序中实现一对多发消息详解及实例代码
2017/02/14 Javascript
Angular 4 指令快速入门教程
2017/06/07 Javascript
微信小程序下拉刷新PullDownRefresh的使用方法
2018/11/29 Javascript
vue自定义表单生成器form-create使用详解
2019/07/19 Javascript
Vue+Node服务器查询Mongo数据库及页面数据传递操作实例分析
2019/12/20 Javascript
vue 对axios get pust put delete封装的实例代码
2020/01/05 Javascript
JS sort排序详细使用方法示例解析
2020/09/27 Javascript
Python操作列表之List.insert()方法的使用
2015/05/20 Python
200 行python 代码实现 2048 游戏
2018/01/12 Python
Python入门之后再看点什么好?
2018/03/05 Python
python随机数分布random测试
2018/08/27 Python
Python玩转Excel的读写改实例
2019/02/22 Python
windows下python虚拟环境virtualenv安装和使用详解
2019/07/16 Python
python匿名函数的使用方法解析
2019/10/10 Python
shell的种类有哪些
2015/04/15 面试题
商业房地产广告语
2014/03/13 职场文书
山东省召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
关于社会实践的心得体会(2016最新版)
2016/01/25 职场文书
2019年“红色之旅”心得体会1000字(3篇)
2019/09/27 职场文书
python中pandas.read_csv()函数的深入讲解
2021/03/29 Python