Image exploader

In this example below you will see how to do a Image exploader with some HTML / CSS and Javascript

Transform image to binary color image, smart split image to squares and totaly explode it. You also may click to image to make some explode

Thumbnail
This awesome code was written by iseeyou911, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright iseeyou911 ©
  • HTML
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Image exploader</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  
  
  
  
</head>

<body>

  <canvas width="600" height="600" id="_canvasMa">

</canvas>
  
  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/iseeyou911/image-exploader-FKAgv */
var ctx, imageObj, processImage, leafFactory, createChilds;
        
        ctx = document.getElementById('_canvasMa').getContext('2d');
        imageObj = new Image();

        /*
            Leaf = {
                children : [] (Leaf*4; top-left, top-right, bottom-left, bottom-right),
                parent : Leaf
            }

           */

            getNeigborhood = function(leaf, root, dir/*l,r,t,b*/) {
                var x, y;
                switch(dir) {
                    case 'l' : {
                        x = leaf.x - 1; 
                        y = leaf.y + 1;
                        break;
                    }
                    case 'r' : {
                        x = leaf.x + leaf.w + 1; 
                        y = leaf.y + 1;
                        break;
                    } 
                    case 'b' : {
                        x = leaf.x + 1; 
                        y = leaf.y + leaf.h + 1;
                        break;
                    } 
                    case 't' : {
                        x = leaf.x + 1; 
                        y = leaf.y - 1;
                        break;
                    } 
                }
                
                return getLeafByCoords(root, x, y);
            };

            getLeafByCoords = function(fromLeaf, x, y) {
                var child, i, result;

                for (i = 0; i < fromLeaf.children.length; i++) {
                    child = fromLeaf.children[i];
                    if (x >= child.x && x <= child.x + child.w && y >= child.y && y <= child.y + child.h) {
                        if (child.children.length === 0) {
                            return child;
                        } else {
                            result = getLeafByCoords(child,x, y);
                            if (result) {
                                return result;
                            }
                        }
                    }
                } 
                return null;
            };

        leafFactory = function(parent, children, w, h, level) {
            return {
                getNeigborhood : function (root, dir) {
                    return getNeigborhood(this, root, dir);
                },
                level : level || 0,
                w : Math.round(w),
                h : Math.round(h),
                x : 0,
                y : 0,
                parent : parent,
                children : children || [],

                setBl : function(value) {
                    value.x = value.parent.x;
                    value.y = value.parent.y + value.h;
                    this.children[1] = value;  
                },
                setBr : function(value) {
                    value.x = value.parent.x + value.w;
                    value.y = value.parent.y + value.h;
                    this.children[3] = value;  
                },
                setTl : function(value) {
                    value.x = value.parent.x;
                    value.y = value.parent.y;
                    this.children[0] = value;  
                },
                setTr : function(value) {
                    value.x = value.parent.x + value.w;
                    value.y = value.parent.y;
                    this.children[2] = value;  
                },

                tr : function() {
                    return this.children[1];  
                },
                br : function() {
                    return this.children[3];  
                },
                tl : function() {
                    return this.children[0];  
                },
                bl : function() {
                    return this.children[2];  
                }
            };
        };

        createChilds = function(parent) {
            parent.setTl(leafFactory(parent, [], parent.w / 2, parent.h / 2, parent.level + 1));
            parent.setTr(leafFactory(parent, [], parent.w / 2, parent.h / 2, parent.level + 1));
            parent.setBl(leafFactory(parent, [], parent.w / 2, parent.h / 2, parent.level + 1));
            parent.setBr(leafFactory(parent, [], parent.w / 2, parent.h / 2, parent.level + 1));
            return parent.children;
        };


        processImage = function() {
            var buildTree, travers, needDivid, root, color, imageData, data, width, height, minWidth, minHeight, i, j, r, g, b, a, leafList;

            minHeight = 0.5;
            minWidth = 0.5;

            width = 600;
            height = 600;

            ctx.drawImage(imageObj, width / 2 - imageObj.width / 2, height / 2 - imageObj.height / 2);
            imageData = ctx.getImageData(0, 0, width, height);
            data = imageData.data;

            squares = [];
            offset = 0;

            root = leafFactory(null, null, 600, 600, 0);
            

            needDivid = function(leaf) {
                var offset, i, j, r, g, b, a, isBlack, isWhite, black; 
                    isBlack = undefined;
                    for (i = leaf.y; i < leaf.y + leaf.h; i++) {
                        for (j = leaf.x; j < leaf.x + leaf.w; j++) {
                            offset = i * height * 4 + j * 4;

                            r = data[offset];
                            g = data[offset + 1];
                            b = data[offset + 2];
                            a = data[offset + 3];

                            black = (r < 200 && g < 200 && b < 200);
                            if ((isBlack === true && !black) || (isBlack === false && black)) {
                                return true;
                            } else {
                                isBlack = black;
                            }
                        }
                    }

                leaf.isBlack = isBlack;
                return false;
            };
            buildTree = function(parent) {
                if (parent.w * 2 >= minWidth && parent.h * 2 >= minHeight) {
                    createChilds(parent).forEach(function(child) {
                        if (needDivid(child)) {
                            buildTree(child);
                        }
                    });
                }
            };

            buildTree(root);

            travers = function(leaf, callback) {
                callback(leaf);
                leaf.children.forEach(function(child) {
                    travers(child, callback);
                }); 
            };

            leafList = [];
            travers(root, function(leaf) {
                var offset, i, j, r, g, b, a, color; 
                if (leaf.children.length !== 0 ||  !leaf.isBlack) {
                    return;
                }

                leafList.push(leaf);

            });

            
           simpleQuadTest = function(leaf, dirArray, callback, walked) {
               var i, _leaf, result;
               i = 0;
               result = [leaf];
               _leaf = leaf;
               while(dirArray.length > i) {
                    _leaf = _leaf.getNeigborhood(root, dirArray[i].side ? dirArray[i].side : dirArray[i]);
                    
                    if (_leaf && walked.indexOf(_leaf) === -1 && _leaf.isBlack && _leaf && _leaf.level === leaf.level - (dirArray[i].lvlAdd || 0)) {
                        result.push(_leaf);
                    } else {
                        return null;
                    }
                    i++;
               }
               callback(result);
               return result;
           };

           var squares = [];
           group = function(list) {
               var walked, process, merge;
               walked = [];


               process = function(array) {
                   walked = walked.concat(array);
               };
               merge = function(array) {
                   var newLeaf, x1, y1, x2, y2, lvl;

                   array.forEach(function(leaf) {

                       if (leaf.level <= lvl || lvl === undefined) {
                            lvl = leaf.level;
                        }
                        if (leaf.x <= x1 || x1 === undefined) {
                            x1 = leaf.x;
                        }
                        if (leaf.x + leaf.w >= x2 || x2 === undefined) {
                            x2 = leaf.x + leaf.w;
                        }
                        if (leaf.y <= y1 || y1 === undefined) {
                            y1 = leaf.y;
                        }
                        if (leaf.y + leaf.h >= y2 || y2 === undefined) {
                            y2 = leaf.y + leaf.h;
                        }
                   });

                   
                   newLeaf = leafFactory(null, null, x2 - x1, y2 - y1, lvl);
                   newLeaf.x = x1;
                   newLeaf.y = y1;

                   return newLeaf;
               };
               list.forEach(function(leaf) {
                   var i, pathList, grouped;
                   pathList= [
                       ['l', 'b', 'r'],
                       ['t', 'l', 'b'], 
                       ['l', 'l', 'b', 'b', {side : 'r', lvlAdd : 1}], 
                       ['r', 'r', 't', 't', {side : 'l', lvlAdd : 1}], 
                       ['b', 'b', 'r', 'r', {side : 't', lvlAdd : 1}], 
                       ['b', 'b', 'r', 'r', {side : 't', lvlAdd : 1}] 
                       ];

                   if (leaf.level > 9 || walked.indexOf(leaf) !== -1) {
                        return;
                   }

                   i = 0;
                   grouped = false;

                    while (i < pathList.length && !grouped) {
                        grouped = simpleQuadTest(leaf, pathList[i], process, walked);
                        i++;
                    }

                    if (grouped) {
                        grouped.forEach(function(_leaf) {
                            var index;
                            index = squares.indexOf(_leaf);
                            if (index !== -1) {
                                squares = squares.slice(0, index).concat(squares.slice(index + 1));
                            }
                        });
                        squares.push(merge(grouped));
                    } else {
                        squares.push(leaf);
                    }
               });
           };

           group(leafList);

           squares.forEach(function(leaf) {
                var offset, i, j, r, g, b, a, color; 
               for (i = leaf.y; i < leaf.y + leaf.h; i++) {
                   for (j = leaf.x; j < leaf.x + leaf.w; j++) {
                       offset = i * height * 4 + j * 4;

                       color = i === leaf.y + leaf.h || j === leaf.x + leaf.w || i === leaf.y || j === leaf.x ? 0 : 255 * leaf.level / 10; 

                       data[offset] = color;
                       data[offset + 1] = 0;
                       data[offset + 2] =  0;
                       data[offset + 3] =  255;
                   }
               }

           });

           var impulse = 0.2, lifeTime = 1000, t = 0, center; 
           center = [
               {x: 0, y :0, i : 126, d: 100, lt: 2000, timer : 0},
               {x: 200, y : 50, i : 226, d: 100,  lt: 2000, timer : 0}, 
               {x: 350, y : 550, i :126, d:250, lt: 2000, timer : 0},

                
               {x: 150, y :300, i : 17, d: 1500, lt: 1000, timer : 0}, 
               {x: 250, y : 300, i : 18, d: 210, lt: 1000, timer : 0}, 
               {x: 300, y : 300, i : 18, d:1400, lt: 1000, timer : 0},
               {x: 400, y : 300, i : 118, d:1300, lt: 1000, timer : 0},
               {x: 550, y : 300, i : 224, d:450, lt: 1000, timer : 0}
               
           ];
          window.addEventListener('click' ,function (e){
              console.log(e)
              center.push({x: e.pageX, y :e.pageY, i : 1000 * Math.random(), d: t + 10, lt: 1000, timer : 0});
            });
           setInterval(function explode () {
                ctx.clearRect(0, 0, width, height);

                ctx.beginPath();
                squares.forEach(function(leaf) {
                    var x, y, offset, i, j, r, g, b, a, color, gravity, Fm, r, r2;
                    leaf.xC = leaf.xC === undefined ? leaf.x + leaf.w / 2 : leaf.xC;
                    leaf.yC = leaf.yC === undefined ? leaf.y + leaf.h / 2: leaf.yC;

                    for (i = 0; i < center.length; i++) {
                        if (t < center[i].d || center[i].isEnded) {
                            continue;
                        }

                        r = (Math.pow(center[i].x - leaf.xC, 2) + Math.pow(center[i].y - leaf.yC, 2)); 
                        r2 = (Math.pow(center[i].x - leaf.x, 2) + Math.pow(center[i].y - leaf.y, 2)); 

                        Fm = Math.random() * center[i].i * ((center[i].lt / center[i].timer) / center[i].lt) / r2 / 0.00016 / (12 - leaf.level); 
                        Fm = isFinite(Fm) && !!Fm ? Fm : 0;
                      
                        leaf.xC = leaf.xC + (leaf.xC - center[i].x) / Math.sqrt(r) * Fm;
                        leaf.yC = leaf.yC + (leaf.yC - center[i].y) / Math.sqrt(r) * Fm;
                    }
                    r2 = Math.sqrt((Math.pow(leaf.x + leaf.w / 2 - leaf.xC, 2) + Math.pow(leaf.y + leaf.h / 2 - leaf.yC, 2)));
                    gravity =  (1 - Math.exp(-(r2 < 2 ? 0 : r2 * (12 - leaf.level))));

                    gravity = isFinite(gravity) ? gravity : 0;
                    x = leaf.xC = leaf.xC + (((-leaf.xC + leaf.x + leaf.w / 2) / r2 * gravity) || 0);
                    y = leaf.yC = leaf.yC + (((-leaf.yC + leaf.y + leaf.h / 2) / r2 * gravity) || 0) ;

                    ctx.rect(x - leaf.w / 2, y - leaf.h / 2, leaf.w, leaf.h);
                }); 

                ctx.fillStyle = 'black';
                ctx.fill();
                
                var explCenter;
                for (i = 0; i < center.length; i++) {
                  explCenter = center[i];
                    if (t < explCenter.d) {
                        continue;
                    } else if (explCenter.timer > 0 && !explCenter.isEnded){
                      //ctx.beginPath();
                      //ctx.arc( explCenter.x, explCenter.y, explCenter.i * 0.2 * explCenter.timer / explCenter.lt, 0, 2 * Math.PI);
                      //ctx.fillStyle = 'red';
                      //ctx.fill();
                    }
                  
               
                    if (explCenter.timer <= explCenter.lt) {
                        explCenter.timer += 10;
                    } else {
                        explCenter.isEnded = true;
                    }
                }
                t += 10;
           } ,10);
            
            
          
        }
        
        
        
        imageObj.onload = processImage;
        imageObj.src = 'data:image/png;base64,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';

Comments