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 实现模态对话框 源代码大全
May 02 Javascript
JQuery this 和 $(this) 的区别
Aug 23 Javascript
jquery ajax对特殊字符进行转义防止js注入使用示例
Nov 21 Javascript
浅谈 javascript 事件处理
Jan 04 Javascript
纯javascript模仿微信打飞机小游戏
Aug 20 Javascript
纯HTML5制作围住神经猫游戏-附源码下载
Aug 23 Javascript
原生js代码实现图片放大境效果
Oct 30 Javascript
js实现二级导航功能
Mar 03 Javascript
微信小程序画布圆形进度条显示效果
Nov 17 Javascript
Angular设置别名alias的方法
Nov 08 Javascript
详解小程序之简单登录注册表单验证
May 13 Javascript
vue2.0 实现富文本编辑器功能
May 26 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
使用bcompiler对PHP文件进行加密的代码
2010/08/29 PHP
thinkPHP5实现的查询数据库并返回json数据实例
2017/10/23 PHP
PHP示例演示发送邮件给某个邮箱
2019/04/03 PHP
微信公众号实现扫码获取微信用户信息(网页授权)
2019/04/09 PHP
Javascript 调试利器 Firebug使用详解六
2009/07/05 Javascript
javascript 写类方式之二
2009/07/05 Javascript
javascript中IE浏览器不支持NEW DATE()带参数的解决方法
2012/03/01 Javascript
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
ScrollDown的基本操作示例
2013/06/09 Javascript
JavaScript加强之自定义callback示例
2013/09/21 Javascript
jquery插件star-rating.js实现星级评分特效
2015/04/15 Javascript
谈谈JavaScript中function多重理解
2015/08/28 Javascript
javascript实现一个简单的弹出窗
2016/02/22 Javascript
JS生成某个范围的随机数【四种情况详解】
2016/04/20 Javascript
Angular 4依赖注入学习教程之InjectToken的使用(八)
2017/06/04 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
jQuery序列化form表单数据为JSON对象的实现方法
2018/09/20 jQuery
对angularJs中2种自定义服务的实例讲解
2018/09/30 Javascript
jQuery创建折叠式菜单
2019/06/15 jQuery
JavaScript 装逼指南(js另类写法)
2020/05/10 Javascript
win与linux系统中python requests 安装
2016/12/04 Python
python 环境变量和import模块导入方法(详解)
2017/07/11 Python
高考考python编程是真的吗
2020/07/20 Python
html5+css3气泡组件的实现
2014/11/21 HTML / CSS
Nordgreen手表德国官方网站:丹麦极简主义手表
2019/10/31 全球购物
美国眼镜网站:LensCrafters
2020/01/19 全球购物
个人收入证明范本
2014/01/12 职场文书
清洁工岗位职责
2014/01/29 职场文书
实习生求职自荐信
2014/02/07 职场文书
不服从上级领导安排的检讨书
2014/09/14 职场文书
工程技术员岗位职责
2015/04/11 职场文书
感恩教育观后感
2015/06/17 职场文书
公司保洁员管理制度
2015/08/04 职场文书
2016婚礼主持词开场白
2015/11/24 职场文书
2016学校元旦晚会经典开场白台词
2015/12/03 职场文书
Win10玩csgo闪退如何解决?Win10玩csgo闪退的解决方法
2022/07/23 数码科技