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开发包大全整理
Dec 22 Javascript
浅析XMLHttpRequest的缓存问题
Dec 13 Javascript
js精美的幻灯片画集特效代码分享
Aug 29 Javascript
七个不允许错过的jQuery小技巧
Dec 21 Javascript
indexedDB bootstrap angularjs之 MVC DOMO (应用示例)
Jun 20 Javascript
javascript之IE版本检测超简单方法
Aug 20 Javascript
JS生成一维码(条形码)功能示例
Jan 19 Javascript
简单实现js放大镜效果
Jul 24 Javascript
3种vue路由传参的基本模式
Feb 22 Javascript
基于vue.js中事件修饰符.self的用法(详解)
Feb 23 Javascript
vue实现弹幕功能
Oct 25 Javascript
ztree+ajax实现文件树下载功能
May 18 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
用Zend Encode编写开发PHP程序
2006/10/09 PHP
15种PHP Encoder的比较
2007/04/17 PHP
sourcesafe管理phpproj文件的补充说明(downmoon)
2009/04/11 PHP
PHP投票系统防刷票判断流程分析
2012/02/04 PHP
php7 安装yar 生成docker镜像
2017/05/09 PHP
JQuery与Ajax常用代码实现对比
2009/10/03 Javascript
某人初学javascript的时候写的学习笔记
2010/12/30 Javascript
javascript学习笔记(十九) 节点的操作实现代码
2012/06/20 Javascript
用Javascript来生成ftp脚本的小例子
2013/07/03 Javascript
JavaScript数据类型检测代码分享
2015/01/26 Javascript
javascript实现网页屏蔽Backspace事件,输入框不屏蔽
2015/07/21 Javascript
js实现按钮颜色渐变动画效果
2015/08/20 Javascript
javascript中SetInterval与setTimeout的定时器用法
2015/08/24 Javascript
jQuery实现文本框邮箱输入自动补全效果
2015/11/17 Javascript
noty ? jQuery通知插件全面解析
2016/05/18 Javascript
JavaScript基于activexobject连接远程数据库SQL Server 2014的方法
2017/07/12 Javascript
动态统计当前输入内容的字节、字符数的实例详解
2017/10/27 Javascript
关于vuejs中v-if和v-show的区别及v-show不起作用问题
2018/03/26 Javascript
vue axios 给生产环境和发布环境配置不同的接口地址(推荐)
2018/05/08 Javascript
vue中使用axios post上传头像/图片并实时显示到页面的方法
2018/09/27 Javascript
js中offset,client , scroll 三大元素知识点总结
2019/09/11 Javascript
python网络爬虫采集联想词示例
2014/02/11 Python
Python删除指定目录下过期文件的2个脚本分享
2014/04/10 Python
聊聊Python中的pypy
2018/01/12 Python
简单了解python调用其他脚本方法实例
2020/03/26 Python
详解Pymongo常用查询方法总结
2021/01/29 Python
详解css3 object-fit属性
2018/07/27 HTML / CSS
美国家喻户晓的保健品品牌:Vitamin World(维他命世界)
2016/08/19 全球购物
澳大利亚快时尚鞋类市场:Billini
2018/05/20 全球购物
HQhair美国/加拿大:英国化妆品、美容及美发产品商城
2019/04/15 全球购物
FragranceNet中文网:北美健康美容线上零售商
2020/08/26 全球购物
企业治理工作自我评价
2013/09/26 职场文书
班级入场式解说词
2014/02/01 职场文书
WebRTC记录音视频流(web技术分享)
2022/02/24 Javascript
世界十大儿童漫画书排名,法国国宝漫画排第五,第二是轰动日本连环
2022/03/18 欧美动漫
python实现对doc、txt、xls等文档的读写操作
2022/04/02 Python