利用拖拽&html转canvas,实现一个图片生成的小功能

最终效果

演示地址
源码地址

首先从元素拖拽开始,大概包含以下几个步骤

1.设置可拖拽目标(就是右边那两张图),设置它的draggable属性为true,实现元素的可拖拽
2.监听dragstart : 当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖拽的元素上
3.可以为拖拽操作设置反馈图标(可选),setDragImage,我这里图方便,就没有设置
4.监听dragenter:当拖拽元素进入目标元素时候触发(目标元素就是左边的框),这个事件作用于目标元素上
5.然后继续监听dragover:拖拽元素在目标元素上移动的时候触发,也是作用在目标元素上
6.drop事件:被拖拽的元素在目标元素上,并且鼠标松开鼠标时触发,这个作用在目标元素上
7.dragend:当拖拽完成后触发的事件,此事件作用在被拖拽元素上
8.event.preventDefault()方法:阻止默认的某些事件方法执行。在dragover中一定要执行preventDefault(),否则drop事件不会被触发。另外,如果是从其它引用软件或是文件夹中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用document的dragover事件把它干掉
9.enevt.effectAllowed:拖拽的效果

源码如下:

// 图片拖拽功能
var $container = $('#ele');   //目标元素
var $dragItem = $('.drag-item'); // 可以拖动的元素
var eleDrag = null; //缓存当前被拖动的元素
var endPosition = {left : '', top : ''};  // 放开元素时的鼠标坐标,为了给在放开鼠标时定位用

监听拖拽元素

$dragItem.on('selectstart',function(){//拖拽元素不可选择,避免选择到一些文本信息之类的
    return false;
}).on('dragstart',function(ev){
    // 拖拽开始 jquery里面需要使用ev.originalEvent.dataTransfer  原生js使用ev.dataTransfer就行了  
    ev.originalEvent.dataTransfer.effectAllowed = 'move';
    eleDrag = ev.target;//记录当前被拖动的元素
    return true;
}).on('dragend',function(ev){
    // 拖拽结束,清空缓存元素
    eleDrag = null;
    return false;
});

监听目标元素

$container.on('dragover',function(ev){
    ev.preventDefault();
    return true;
}).on('dragenter',function(ev){
    // 给目标元素设置边框效果,提示元素进入
    $(this).toggleClass('active');
    return true;
}).on('drop',function(ev){
    // 记录当前的坐标,为拖拽结束时,拉伸框定位用
    endPosition.left = ev.originalEvent.x;
    endPosition.top = ev.originalEvent.y;
    if(eleDrag){
        setHtml(eleDrag)
    }
    $(this).toggleClass('active');
});

// 这里是把拖拽元素,加上一些编辑效果,然后加入到目标元素里面
function setHtml(eleDrag){
    // 这里用的是attr拿图片地址
    // 其实也可以用  src = ev.originalEvent.dataTransfer.getData('url')  getData来拿拖拽元素的url,不过这个就要放到drop事件里面才能拿到了
    // https://developer.mozilla.org/zh-CN/docs/Web/API/DataTransfer/getData
    var src = $(eleDrag).attr('src');
    var $img = $('<img>');
    var $dragEle = $('<div>');
    var directionBtn = $('.cacheEle').html();
    $img.attr('src',$(eleDrag).attr('src')).attr('data-type','drag');
    $dragEle.addClass('drag').attr('data-type','drag').html($img).append(directionBtn);
    
    $dragEle.css({
        'left' : endPosition.left - (100/2),
        'top' : endPosition.top - (100/2),
    });
    $container.append($dragEle);
}

拖拽的效果到这里就结束了

接着说说图片移动,拉伸的实现

其实这个地方实现这个外框就行了,里面的图片根据外框拉伸


首先是布局,就是需要一个框,然后8个点,后面控制这8个点来进行拉伸。其实我们是没有必要为4个顶角单独来写方法,我们只需要同时调用左右移动&上下移动的方法就行了,所以这里只需要两个方法(左右移动,上下移动),详细的解释在源码里面有标示出来

最后就是把我们刚才做出来的效果,生成图片并且上传了

这个地方我使用了html2canvas这个库,它会先把dom节点转换成canvas,然后我们通过canvas的toDataURL返回包含图片展示的 data URI。并且这个方法还支持压缩,不过只能转换为jpeg的时候生效
然后我们就可以把这个data URI上传给后台了,下面是php的代码

$file = $_POST['base64'];


    $tmp  = base64_decode($file);
    $randStr = getRandChar(5);

    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)){
      $type = $result[2];
      $new_file = "./upload/".$randStr.".{$type}";//这里要注意upload文件夹的权限
      if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $file)))){
        echo '新文件保存成功:', $new_file;
      }

    }

    function getRandChar($length){
       $str = null;
       $strPol = "0123456789abcdefghijklmnopqrstuvwxyz";
       $max = strlen($strPol)-1;

       for($i=0;$i<$length;$i++){
        $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
       }

       return $str;
      }

参考资料:
HTML5 drag & drop 拖拽与拖放简介
JS原生拖拽拖放事件
原生 JavaScript 图片裁剪效果
dataTransfer in jquery

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,273评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,349评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,709评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,520评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,515评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,158评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,755评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,660评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,203评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,287评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,427评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,122评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,801评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,272评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,393评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,808评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,440评论 2 359

推荐阅读更多精彩内容

  • 之前写过一篇浏览器事件的相关操作和事件运行的原理——JavaScript浏览器事件解析。这一篇主要写一些常用的事件...
    faremax阅读 1,624评论 0 0
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,264评论 25 707
  • 有人说,青春是灰色的。整天在辅导书、试卷中埋头苦学,看不见前方的道路……有人说,青春是红色的。整天吃喝玩乐,醉生梦...
    1望天涯1阅读 579评论 0 3
  • 人,总在安静时,想的很多。或许,生活中遭遇了冷落或挫折,浮躁纠结,但一个人的时候,在闭上眼睛的瞬间,你总能听到心的...
    茉言心语阅读 363评论 0 2
  • 妇女节画个美好的姑娘~
    赵莲贵阅读 643评论 0 4