www.RoBorg.co.uk - Javascript and PHP Projects :: BuildImage Tutorial - Drag-drop generated layered images

BuildImage Example

Each <img> inside blockContainer can be dragged onto the background image.
Its id will be posted back, along with its top and left coordinates, which are used to generate a new PNG file.

Kitty Sun Cloud
Background - Drag images here


BuildImage Code

You are free to modify and use this code, but please link back to http://www.roborg.co.uk if you do.

You will need to create a directory called "generated" under the directory you place the script in, and give PHP write access to it.

<?php
session_start
();

$background = "background.png";

$imgData = false;

if(
array_key_exists("data", $_POST))
{
    
parse_str($_POST["data"], $data);
    
$imgData = $data["data"];
    
ksort($imgData);
    
$imgData = array_values($imgData);
    
    
//Create the image
    
$size = getimagesize($background);
    
$width = $size[0];
    
$height = $size[1];
    
$img = imagecreatetruecolor($width, $height);
    
    
//Copy the background image
    
$tmp = imgFromFile($background);
    if(!
$tmp) die("Error creating background image");
    
imagealphablending($img, false);
    
imagecopy($img, $tmp, 0, 0, 0, 0, $width, $height);
    
imagealphablending($img, true);
    
imagedestroy($tmp);
    
    
//Add each layer
    
foreach($imgData as $layer)
    {
        
$file = pathinfo($layer["src"]);
        
$tmp = imgFromFile($file["basename"]);
        if(!
$tmp) die("Error creating image ".$layer["src"]);
        
$size = getimagesize($file["basename"]);
        
imagecopy($img, $tmp, $layer["x"], $layer["y"], 0, 0, $size[0], $size[1]);
        
imagedestroy($tmp);
    }
    
    
//Clean out any old files (>24 hours)
    
$d = dir("generated");
    while((
$f = $d->read()) !== false)
    {
        if(
$f{0} == ".")
            continue;
        
        if(!
preg_match("/^".date("d")."_/", $f))
            
unlink("generated/".$f);
    }
    
    
imagepng($img, "generated/".date("d")."_".session_id().".png");
}

function
imgFromFile($img)
{
    if(
preg_match("/\.png/i", $img) && function_exists("imagecreatefrompng")) return imagecreatefrompng($img);
    elseif(
preg_match("/\.gif/i", $img) && function_exists("imagecreatefromgif")) return imagecreatefromgif($img);
    elseif(
preg_match("/\.jpe?g/i", $img) && function_exists("imagecreatefromjpeg")) return imagecreatefromjpeg($img);
    return
false;
}


?><html>
<head>
<style type="text/css">

html, body                        {height:100%;}

#blockContainer                {}
#blockContainer img        {position:absolute; z-index:100; cursor:move;}

#baseImage                        {}

</style>

<script type="text/javascript">
var data = false;
<?php

if($imgData)
{
    
$js = array();
    
$i = 0;
    foreach(
$imgData as $layer)
    {
        
$js[] = "'".addslashes($layer["src"])."':{'x':".$layer["x"].",'y':".$layer["y"].",'z':".$i."}";
        
$i++;
    }
    
    print(
"data = {".implode(",", $js)."};\n");
}

?>

var draggingElm = false;
var maxZ = 100;

window.onload = function()
{
    document.body.onmousemove = mouseMove;
    
    var elms = document.getElementById('blockContainer').getElementsByTagName('img');
    
    //Get the position of the baseImage
    var xOffset = 0;
    var yOffset = 0;
    var o = document.getElementById('baseImage');
    while(o)
    {
        xOffset += o.offsetLeft;
        yOffset += o.offsetTop;
        o = o.offsetParent;
    }

    var x = xOffset;
    var maxHeight = 0;
    var realMaxZ = 0;


    for(var i=0; i<elms.length; i++)
    {
        elms[i].onmousedown = function(e) {startDrag(e, this); return false;}
        elms[i].onmouseup = function() {draggingElm = false;}
        elms[i].ondragstart = function() {return false;}
        
        if(data)
        {
            elms[i].style.left = (xOffset + data[elms[i].src].x) + 'px';
            elms[i].style.top = (yOffset + data[elms[i].src].y) + 'px';
            elms[i].style.zIndex = maxZ + data[elms[i].src].z;
            realMaxZ = Math.max(realMaxZ, maxZ + data[elms[i].src].z);
        }
        else
        {
            elms[i].style.left = x + 'px';
            elms[i].style.zIndex = ++maxZ;
            x += elms[i].offsetWidth + 10;
            maxHeight = Math.max(maxHeight, elms[i].offsetHeight);
        }
    }
    
    if(!data)
        document.getElementById('blockContainer').style.height = (maxHeight + 10) + 'px';
    else
        maxZ = realMaxZ;
}

var draggingElm = false;

function startDrag(e, elm)
{
    var m = getMouse(e);
    
    var xOffset = -m.x;
    var yOffset = -m.y;
    var o = elm;
    while(o)
    {
        xOffset += o.offsetLeft;
        yOffset += o.offsetTop;
        o = o.offsetParent;
    }
    
    draggingElm = {'xOffset':xOffset,'yOffset':yOffset,'elm':elm};
    elm.style.zIndex = ++maxZ;
    
    return false;
}

function mouseMove(e)
{
    if(!draggingElm)
        return;
    
    if(document.selection)
        document.selection.empty();
    
    var m = getMouse(e);
    
    draggingElm.elm.style.left = (m.x + draggingElm.xOffset) + 'px';
    draggingElm.elm.style.top = (m.y + draggingElm.yOffset) + 'px';
    
    window.status = m.x + ',' + m.y;
}

function getMouse(e)
{
    if(typeof e == 'undefined')
    {
        if(document.documentElement) if(document.documentElement.scrollTop)
        {
            var scrollLeft = document.documentElement.scrollLeft;
            var scrollTop = document.documentElement.scrollTop;
        }
        else
        {
            var scrollLeft = document.body.scrollLeft;
            var scrollTop = document.body.scrollTop;
        }
        
        mouseX = event.clientX + scrollLeft;
        mouseY = event.clientY + scrollTop;
    }
    else
    {
        mouseX = e.pageX;
        mouseY = e.pageY;
    }
    
    return {'x':mouseX,'y':mouseY};
}

function setForm(f)
{
    var elms = document.getElementById('blockContainer').getElementsByTagName('img');

    var str = '';
    
    //Get the position of the baseImage
    var xOffset = 0;
    var yOffset = 0;
    var o = document.getElementById('baseImage');
    while(o)
    {
        xOffset += o.offsetLeft;
        yOffset += o.offsetTop;
        o = o.offsetParent;
    }
    
    for(var i=0; i<elms.length; i++)
    {
        str += '&data[' + elms[i].style.zIndex + '][src]=' + elms[i].src;
        str += '&data[' + elms[i].style.zIndex + '][x]=' + (elms[i].offsetLeft - xOffset);
        str += '&data[' + elms[i].style.zIndex + '][y]=' + (elms[i].offsetTop - yOffset);
    }
    
    f.elements['data'].value = str;
}

</script>

<h1>BuildImage Example</h1>

<p>
Each &lt;img&gt; inside blockContainer can be dragged onto the background image.<br>
Its id will be posted back, along with its top and left coordinates, which are used to generate a new PNG file.
</p>


<div id="blockContainer">
<img src="kitty.gif" width="31" height="50" alt="Kitty">
<img src="sun.png" width="20" height="20" alt="Sun">
<img src="cloud.gif" width="34" height="19" alt="Cloud">
</div>

<img src="<?php print($background); ?>" id="baseImage" width="200" height="100" alt="Background - Drag images here">

<form action="<?php print($_SERVER["PHP_SELF"]); ?>" method="post" onsubmit="return setForm(this);">
<div>
<input type="hidden" name="data" value="">
<input type="submit" value="Save" class="butt">
</div>
</form>

<?php

if($imgData)
{
    print(
"<p style=\"text-align:center;\">");
    print(
"<b>Your image</b>: Right click and choose Save As to save!<br>");
    print(
"<img src=\"generated/".date("d")."_".session_id().".png?rand=".rand(0, 99999)."\" alt=\"Your Image\">");
    print(
"</p>\n");
}