Javascript拖拽拼图

实现拖拽拼图的思路:

1. 首先将一个大图划分成指定定长宽的小块,生成map数组(为了让效果更富有动感,在生成最终的map之前会先打乱数组的顺序),并绘制在页面中(这里我们采用div+css来布局,如果使用table来布局,在绘制完成后需要将元素的定位方式改变为绝对定位)。

2. 将所有划分的小块绑定拖动事件,在拖动滑块到任意位置的时候计算离拖动滑块最近的块,交换他们在数组中的位置并交换他们在视图中的显示位置:
代码实现:

;(function(){
    var Divider = (function(){
        var container,ops,map,width,perWidth,height,perHeight;
        var defaults = {
            src : '',
            cols : 10,
            rows : 10,
            max : 500,
            gap : 2
        };
        var init = function(params){
            var params = params || {};
            ops = extend(defaults,params);
            if(!ops.src){
                console.error("lack of iamge!");
                return;
            }
            container = document.createDocumentFragment(); 
            map = [];
            particle();
        }
        var particle = function(){
            var max = ops.max,rows = ops.rows,cols = ops.cols,src = ops.src;
            var img = new Image();
            img.src = src;
            img.onload = function(){
                var fix = fixSize(this.width,this.height,max)
                width = fix.width;
                height = fix.height;
                perWidth = Math.round(width/cols);
                perHeight = Math.round(height/rows);
                for(var i=0;i<rows;i++){
                    var offsetY = i * perHeight;
                    for(var j=0;j<cols;j++){
                        var offsetX = (j%cols) * perWidth;
                        map.push({
                            x : offsetX,
                            y : offsetY
                        })
                    }
                }
                map = randomArray(map);
                draw();
            }
        }
        var draw = function(){
            for(var i=0,l=map.length;i<l;i++){ var d = create("div"); d.style.cssText = ";width:"+(perWidth-ops.gap*2)+"px;height:"+(perHeight-ops.gap*2)+"px;background:url("+ops.src+") "+(-map[i].x)+"px "+(-map[i].y)+"px no-repeat;background-size:"+width+"px "+height+"px;border-radius:5px;position:absolute;top:"+map[i].y+"px;left:"+map[i].x+"px"; d.className = "item"; d.index = i; container.appendChild(d); } var d = create("div"); d.style.cssText = "width:"+width+"px;height:"+height+"px;margin:0 auto;position:relative;"; d.appendChild(container); document.body.appendChild(d); DrawSort.init(d,map); } var randomArray = function(arr){ return arr.sort(function(){ return !!(Math.random() > 0.5);
            })
        }
        var create = function(tagname){
            return document.createElement(tagname);
        }
        var fixSize = function(width,height,max){
            if(width<max && height<max){ return { width : width, height : height } } if(width>height){
                if(width>max){
                    var ratio = max/width;
                    return {
                        width : max,
                        height: height * ratio
                    }
                }else{
                    return {
                        width : width,
                        height : height
                    }
                }
            }else{
                if(height>max){
                    var ratio = max/height;
                    return {
                        width : width * ratio,
                        height: max
                    }
                }else{
                    return {
                        width : width,
                        height : height
                    }
                }
            }
        }
        var setCols = function(col){
            cols = col;
        }
        var setRows = function(row){
            rows = row;
        }
        var extend = function(defaults,params){
            for(var index in params){
                if(params.hasOwnProperty(index)){
                    defaults[index] = params[index];
                }
            }
            return defaults;
        }
        return { 
            init : init,
            setCols : setCols,
            setRows : setRows
        }
    })();
    var DrawSort = (function(){
        var container,items,zx,map;
        var init = function(contain,mapx){
            map = mapx || [];
            container = contain;
            items = container.childNodes;
            zx = 0;
            for(var i=0,l=items.length;i<l;i++){
                drap(items[i]);
            }
        }
        var drap = function(obj){
            obj.onmousedown = function(e){
                var oNear = null,ev = e || window.event;
                var disX = ev.pageX- this.offsetLeft - container.offsetLeft;
                var disY = ev.pageY- this.offsetTop - container.offsetTop;
                this.className = 'cur';
                this.style.zIndex = zx++;
                if(obj.setCapture){
                    obj.setCapture();
                }else{
                    window.captureEvents(Event.MOUSEMOVE);
                }
                document.onmousemove = function(e){
                    var ev = e || window.event,
                        w = ev.pageX - disX - container.offsetLeft,
                        h = ev.pageY - disY - container.offsetTop;
                    w < 0 && (w = 0); w >= (container.offsetWidth-obj.offsetWidth) && (w = container.offsetWidth-obj.offsetWidth);
                    h < 0 && (h = 0); h >= (container.offsetHeight-obj.offsetHeight) && (h = container.offsetHeight-obj.offsetHeight);
                    obj.style.top = h + "px";
                    obj.style.left = w + "px";
                    for(var i=0,l=items.length;i<l;i++){
                        items[i].className = "cur";
                    }
                    oNear = findNearest(obj);
                    oNear && (oNear.className="hig");
                }
                document.onmouseup = function(){
                    if(obj.releaseCapture){
                        obj.releaseCapture();
                    }else{
                        window.releaseEvents(Event.MOUSEMOVE||Event.MOUSEUP);
                    }
                    document.onmouseup = null;
                    document.onmousemove = null;
                    for(var i=0,l=items.length;i<l;i++){
                        items[i].className = "";
                    }
                    if(oNear){
                        oNear.style.zIndex = zx ++;
                        startMove(obj,map[oNear.index]);
                        startMove(oNear,map[obj.index]);
                        oNear.index = [obj.index,obj.index=oNear.index][0];
                    }else{
                        startMove(obj,map[obj.index]);
                    }
                }
            }
        }
        var findNearest = function(obj){
            var res,distances = [],elems = [],min = 9999999,minItem;
            for(var i=0,l=items.length;i<l;i++){
                res = isButt(obj,items[i]);
                if(items[i]!=obj && res){
                    distances.push(calDis(obj,items[i]));
                    elems.push(items[i]);
                }
            }
            distances.map(function(item,i){
                if(item<min){ min = item; minItem = elems[i]; } }) return minItem; } var isButt = function(a,b){ var al = a.offsetLeft, at = a.offsetTop, alw = al + a.offsetWidth, ath = at + a.offsetHeight, bl = b.offsetLeft, bt = b.offsetTop, blw = bl + b.offsetWidth, bth = bt + b.offsetHeight; if(al>blw || alw < bl || at > bth || ath < bt){ return false; } return true; } var startMove = function(obj,pos,onEnd) { clearInterval(obj.timer); obj.timer = setInterval(function(){ doMove(obj,pos,onEnd); },30); } var doMove = function(obj,pos,onEnd){ var curL = getStyle(obj,"left"),curT = getStyle(obj,"top"),speedL = (pos.x - curL)/5,speedT = (pos.y-curT)/5; speedL = speedL > 0 ? Math.ceil(speedL) : Math.floor(speedL);
            speedT = speedT > 0 ? Math.ceil(speedT) : Math.floor(speedT);
            if(pos.x==curL && pos.y == curT){
                clearInterval(obj.timer);
                onEnd && onEnd();
            }else{
                obj.style.left = curL + speedL + "px";
                obj.style.top = curT + speedT + "px";
            }
        }
        var getStyle = function(obj,attr){
            return parseFloat(obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj,null)[attr]);
        }
        var calDis = function(a,b){
            return Math.sqrt(Math.pow(a.offsetLeft+a.offsetWidth/2-b.offsetLeft-b.offsetWidth/2,2)+Math.pow(a.offsetTop+a.offsetHeight/2-b.offsetTop-b.offsetHeight/2,2));
        }
        return { init : init }
    })();
    window.Divider  = window.Divider || Divider;
})();

在线demo:http://demo.deanhan.cn/drag-divide/

  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章