Upload and drag the image inside a mask image












1












$begingroup$


I am allowing users to upload and drag images with this code. Give me a review of this.



Codepen



<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<input id="fileup" type="file" >

<div class="container">
</div>

<style>

.temp {}

.container {
background: black;
}

.masked-img {
overflow: hidden;
margin-top: 30px;
position: relative;
}
</style>


<script>

var mask;


$(document).ready(function() {

$.getJSON('9images.json', function(data)

{
var width = 0;
var height = 0;

let layer1 = data.layers;
width = layer1[0].width;
height = layer1[0].height;

let layer2 = layer1[0].layers;

for (i = 1; i < layer2.length; i++) {
var x = layer2[i].x;
var y = layer2[i].y;
var src = layer2[i].layers[0].src;
$(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

var mask = $(".container").mask({
maskImageUrl: 'http://piccellsapp.com:1337/parse/files/PfAppId/' + src,
onMaskImageCreate: function(img) {

img.css({
"position": "fixed",
"left": x + "px",
"top": y + "px"
});
}
});

fileup.onchange = function() {
mask.loadImage(URL.createObjectURL(fileup.files[0]));
};
}

});


}); // end of document ready

// jq plugin for mask
(function($) {
var JQmasks = ;
$.fn.mask = function(options) {
// This is the easiest way to have default options.
var settings = $.extend({
// These are the defaults.
maskImageUrl: undefined,
imageUrl: undefined,
scale: 1,
id: new Date().getUTCMilliseconds().toString(),
x: 0, // image start position
y: 0, // image start position
onMaskImageCreate: function(div) {},
}, options);


var container = $(this);

let prevX = 0,
prevY = 0,
draggable = false,
img,
canvas,
context,
image,
timeout,
initImage = false,
startX = settings.x,
startY = settings.y,
div;

container.mousePosition = function(event) {
return {
x: event.pageX || event.offsetX,
y: event.pageY || event.offsetY
};
}

container.selected = function(ev) {
var pos = container.mousePosition(ev);
var item = $(".masked-img canvas").filter(function() {
var offset = $(this).offset()
var x = pos.x - offset.left;
var y = pos.y - offset.top;
var d = this.getContext('2d').getImageData(x, y, 1, 1).data;
return d[0] > 0
});

JQmasks.forEach(function(el) {
var id = item.length > 0 ? $(item).attr("id") : "";
if (el.id == id)
el.item.enable();
else el.item.disable();
});
};

container.enable = function() {
draggable = true;
$(canvas).attr("active", "true");
div.css({
"z-index": 2
});
}

container.disable = function() {
draggable = false;
$(canvas).attr("active", "false");
div.css({
"z-index": 1
});
}

container.onDragStart = function(evt) {
container.selected(evt);
prevX = evt.clientX;
prevY = evt.clientY;
};

container.getImagePosition = function() {
return {
x: settings.x,
y: settings.y,
scale: settings.scale
};
};

container.onDragOver = function(evt) {
if (draggable && $(canvas).attr("active") === "true") {
var x = settings.x + evt.clientX - prevX;
var y = settings.y + evt.clientY - prevY;
if (x == settings.x && y == settings.y)
return; // position has not changed
settings.x += evt.clientX - prevX;
settings.y += evt.clientY - prevY;
prevX = evt.clientX;
prevY = evt.clientY;
container.updateStyle();
}
};

container.updateStyle = function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.globalCompositeOperation = "source-over";
image = new Image();
image.setAttribute('crossOrigin', 'anonymous');
image.src = settings.maskImageUrl;
image.onload = function() {
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0, image.width, image.height);
div.css({
"width": image.width,
"height": image.height
});
};

img = new Image();
img.src = settings.imageUrl;
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function() {
settings.x = settings.x == 0 && initImage ? (canvas.width - (img.width * settings.scale)) / 2 : settings.x;
settings.y = settings.y == 0 && initImage ? (canvas.height - (img.height * settings.scale)) / 2 : settings.y;
context.globalCompositeOperation = 'source-atop';
context.drawImage(img, settings.x, settings.y, img.width * settings.scale, img.height * settings.scale);
initImage = false;
};
}, 0);
};

// change the draggable image
container.loadImage = function(imageUrl) {
if (img)
img.remove();
// reset the code.
settings.y = startY;
settings.x = startX;
prevX = prevY = 0;
settings.imageUrl = imageUrl;
initImage = true;
container.updateStyle();
};

// change the masked Image
container.loadMaskImage = function(imageUrl, from) {
if (div)
div.remove();
canvas = document.createElement("canvas");
context = canvas.getContext('2d');
canvas.setAttribute("draggable", "true");
canvas.setAttribute("id", settings.id);
settings.maskImageUrl = imageUrl;
div = $("<div/>", {
"class": "masked-img"
}).append(canvas);

div.find("canvas").on('touchstart mousedown', function(event) {
if (event.handled === false) return;
event.handled = true;
container.onDragStart(event);
});

div.find("canvas").on('touchend mouseup', function(event) {
if (event.handled === false) return;
event.handled = true;
container.selected(event);
});

div.find("canvas").bind("dragover", container.onDragOver);
container.append(div);
if (settings.onMaskImageCreate)
settings.onMaskImageCreate(div);
container.loadImage(settings.imageUrl);
};
container.loadMaskImage(settings.maskImageUrl);
JQmasks.push({
item: container,
id: settings.id
})
return container;
};
}(jQuery));
</script>









share|improve this question











$endgroup$

















    1












    $begingroup$


    I am allowing users to upload and drag images with this code. Give me a review of this.



    Codepen



    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

    <input id="fileup" type="file" >

    <div class="container">
    </div>

    <style>

    .temp {}

    .container {
    background: black;
    }

    .masked-img {
    overflow: hidden;
    margin-top: 30px;
    position: relative;
    }
    </style>


    <script>

    var mask;


    $(document).ready(function() {

    $.getJSON('9images.json', function(data)

    {
    var width = 0;
    var height = 0;

    let layer1 = data.layers;
    width = layer1[0].width;
    height = layer1[0].height;

    let layer2 = layer1[0].layers;

    for (i = 1; i < layer2.length; i++) {
    var x = layer2[i].x;
    var y = layer2[i].y;
    var src = layer2[i].layers[0].src;
    $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

    var mask = $(".container").mask({
    maskImageUrl: 'http://piccellsapp.com:1337/parse/files/PfAppId/' + src,
    onMaskImageCreate: function(img) {

    img.css({
    "position": "fixed",
    "left": x + "px",
    "top": y + "px"
    });
    }
    });

    fileup.onchange = function() {
    mask.loadImage(URL.createObjectURL(fileup.files[0]));
    };
    }

    });


    }); // end of document ready

    // jq plugin for mask
    (function($) {
    var JQmasks = ;
    $.fn.mask = function(options) {
    // This is the easiest way to have default options.
    var settings = $.extend({
    // These are the defaults.
    maskImageUrl: undefined,
    imageUrl: undefined,
    scale: 1,
    id: new Date().getUTCMilliseconds().toString(),
    x: 0, // image start position
    y: 0, // image start position
    onMaskImageCreate: function(div) {},
    }, options);


    var container = $(this);

    let prevX = 0,
    prevY = 0,
    draggable = false,
    img,
    canvas,
    context,
    image,
    timeout,
    initImage = false,
    startX = settings.x,
    startY = settings.y,
    div;

    container.mousePosition = function(event) {
    return {
    x: event.pageX || event.offsetX,
    y: event.pageY || event.offsetY
    };
    }

    container.selected = function(ev) {
    var pos = container.mousePosition(ev);
    var item = $(".masked-img canvas").filter(function() {
    var offset = $(this).offset()
    var x = pos.x - offset.left;
    var y = pos.y - offset.top;
    var d = this.getContext('2d').getImageData(x, y, 1, 1).data;
    return d[0] > 0
    });

    JQmasks.forEach(function(el) {
    var id = item.length > 0 ? $(item).attr("id") : "";
    if (el.id == id)
    el.item.enable();
    else el.item.disable();
    });
    };

    container.enable = function() {
    draggable = true;
    $(canvas).attr("active", "true");
    div.css({
    "z-index": 2
    });
    }

    container.disable = function() {
    draggable = false;
    $(canvas).attr("active", "false");
    div.css({
    "z-index": 1
    });
    }

    container.onDragStart = function(evt) {
    container.selected(evt);
    prevX = evt.clientX;
    prevY = evt.clientY;
    };

    container.getImagePosition = function() {
    return {
    x: settings.x,
    y: settings.y,
    scale: settings.scale
    };
    };

    container.onDragOver = function(evt) {
    if (draggable && $(canvas).attr("active") === "true") {
    var x = settings.x + evt.clientX - prevX;
    var y = settings.y + evt.clientY - prevY;
    if (x == settings.x && y == settings.y)
    return; // position has not changed
    settings.x += evt.clientX - prevX;
    settings.y += evt.clientY - prevY;
    prevX = evt.clientX;
    prevY = evt.clientY;
    container.updateStyle();
    }
    };

    container.updateStyle = function() {
    clearTimeout(timeout);
    timeout = setTimeout(function() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();
    context.globalCompositeOperation = "source-over";
    image = new Image();
    image.setAttribute('crossOrigin', 'anonymous');
    image.src = settings.maskImageUrl;
    image.onload = function() {
    canvas.width = image.width;
    canvas.height = image.height;
    context.drawImage(image, 0, 0, image.width, image.height);
    div.css({
    "width": image.width,
    "height": image.height
    });
    };

    img = new Image();
    img.src = settings.imageUrl;
    img.setAttribute('crossOrigin', 'anonymous');
    img.onload = function() {
    settings.x = settings.x == 0 && initImage ? (canvas.width - (img.width * settings.scale)) / 2 : settings.x;
    settings.y = settings.y == 0 && initImage ? (canvas.height - (img.height * settings.scale)) / 2 : settings.y;
    context.globalCompositeOperation = 'source-atop';
    context.drawImage(img, settings.x, settings.y, img.width * settings.scale, img.height * settings.scale);
    initImage = false;
    };
    }, 0);
    };

    // change the draggable image
    container.loadImage = function(imageUrl) {
    if (img)
    img.remove();
    // reset the code.
    settings.y = startY;
    settings.x = startX;
    prevX = prevY = 0;
    settings.imageUrl = imageUrl;
    initImage = true;
    container.updateStyle();
    };

    // change the masked Image
    container.loadMaskImage = function(imageUrl, from) {
    if (div)
    div.remove();
    canvas = document.createElement("canvas");
    context = canvas.getContext('2d');
    canvas.setAttribute("draggable", "true");
    canvas.setAttribute("id", settings.id);
    settings.maskImageUrl = imageUrl;
    div = $("<div/>", {
    "class": "masked-img"
    }).append(canvas);

    div.find("canvas").on('touchstart mousedown', function(event) {
    if (event.handled === false) return;
    event.handled = true;
    container.onDragStart(event);
    });

    div.find("canvas").on('touchend mouseup', function(event) {
    if (event.handled === false) return;
    event.handled = true;
    container.selected(event);
    });

    div.find("canvas").bind("dragover", container.onDragOver);
    container.append(div);
    if (settings.onMaskImageCreate)
    settings.onMaskImageCreate(div);
    container.loadImage(settings.imageUrl);
    };
    container.loadMaskImage(settings.maskImageUrl);
    JQmasks.push({
    item: container,
    id: settings.id
    })
    return container;
    };
    }(jQuery));
    </script>









    share|improve this question











    $endgroup$















      1












      1








      1


      1



      $begingroup$


      I am allowing users to upload and drag images with this code. Give me a review of this.



      Codepen



      <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

      <input id="fileup" type="file" >

      <div class="container">
      </div>

      <style>

      .temp {}

      .container {
      background: black;
      }

      .masked-img {
      overflow: hidden;
      margin-top: 30px;
      position: relative;
      }
      </style>


      <script>

      var mask;


      $(document).ready(function() {

      $.getJSON('9images.json', function(data)

      {
      var width = 0;
      var height = 0;

      let layer1 = data.layers;
      width = layer1[0].width;
      height = layer1[0].height;

      let layer2 = layer1[0].layers;

      for (i = 1; i < layer2.length; i++) {
      var x = layer2[i].x;
      var y = layer2[i].y;
      var src = layer2[i].layers[0].src;
      $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

      var mask = $(".container").mask({
      maskImageUrl: 'http://piccellsapp.com:1337/parse/files/PfAppId/' + src,
      onMaskImageCreate: function(img) {

      img.css({
      "position": "fixed",
      "left": x + "px",
      "top": y + "px"
      });
      }
      });

      fileup.onchange = function() {
      mask.loadImage(URL.createObjectURL(fileup.files[0]));
      };
      }

      });


      }); // end of document ready

      // jq plugin for mask
      (function($) {
      var JQmasks = ;
      $.fn.mask = function(options) {
      // This is the easiest way to have default options.
      var settings = $.extend({
      // These are the defaults.
      maskImageUrl: undefined,
      imageUrl: undefined,
      scale: 1,
      id: new Date().getUTCMilliseconds().toString(),
      x: 0, // image start position
      y: 0, // image start position
      onMaskImageCreate: function(div) {},
      }, options);


      var container = $(this);

      let prevX = 0,
      prevY = 0,
      draggable = false,
      img,
      canvas,
      context,
      image,
      timeout,
      initImage = false,
      startX = settings.x,
      startY = settings.y,
      div;

      container.mousePosition = function(event) {
      return {
      x: event.pageX || event.offsetX,
      y: event.pageY || event.offsetY
      };
      }

      container.selected = function(ev) {
      var pos = container.mousePosition(ev);
      var item = $(".masked-img canvas").filter(function() {
      var offset = $(this).offset()
      var x = pos.x - offset.left;
      var y = pos.y - offset.top;
      var d = this.getContext('2d').getImageData(x, y, 1, 1).data;
      return d[0] > 0
      });

      JQmasks.forEach(function(el) {
      var id = item.length > 0 ? $(item).attr("id") : "";
      if (el.id == id)
      el.item.enable();
      else el.item.disable();
      });
      };

      container.enable = function() {
      draggable = true;
      $(canvas).attr("active", "true");
      div.css({
      "z-index": 2
      });
      }

      container.disable = function() {
      draggable = false;
      $(canvas).attr("active", "false");
      div.css({
      "z-index": 1
      });
      }

      container.onDragStart = function(evt) {
      container.selected(evt);
      prevX = evt.clientX;
      prevY = evt.clientY;
      };

      container.getImagePosition = function() {
      return {
      x: settings.x,
      y: settings.y,
      scale: settings.scale
      };
      };

      container.onDragOver = function(evt) {
      if (draggable && $(canvas).attr("active") === "true") {
      var x = settings.x + evt.clientX - prevX;
      var y = settings.y + evt.clientY - prevY;
      if (x == settings.x && y == settings.y)
      return; // position has not changed
      settings.x += evt.clientX - prevX;
      settings.y += evt.clientY - prevY;
      prevX = evt.clientX;
      prevY = evt.clientY;
      container.updateStyle();
      }
      };

      container.updateStyle = function() {
      clearTimeout(timeout);
      timeout = setTimeout(function() {
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.beginPath();
      context.globalCompositeOperation = "source-over";
      image = new Image();
      image.setAttribute('crossOrigin', 'anonymous');
      image.src = settings.maskImageUrl;
      image.onload = function() {
      canvas.width = image.width;
      canvas.height = image.height;
      context.drawImage(image, 0, 0, image.width, image.height);
      div.css({
      "width": image.width,
      "height": image.height
      });
      };

      img = new Image();
      img.src = settings.imageUrl;
      img.setAttribute('crossOrigin', 'anonymous');
      img.onload = function() {
      settings.x = settings.x == 0 && initImage ? (canvas.width - (img.width * settings.scale)) / 2 : settings.x;
      settings.y = settings.y == 0 && initImage ? (canvas.height - (img.height * settings.scale)) / 2 : settings.y;
      context.globalCompositeOperation = 'source-atop';
      context.drawImage(img, settings.x, settings.y, img.width * settings.scale, img.height * settings.scale);
      initImage = false;
      };
      }, 0);
      };

      // change the draggable image
      container.loadImage = function(imageUrl) {
      if (img)
      img.remove();
      // reset the code.
      settings.y = startY;
      settings.x = startX;
      prevX = prevY = 0;
      settings.imageUrl = imageUrl;
      initImage = true;
      container.updateStyle();
      };

      // change the masked Image
      container.loadMaskImage = function(imageUrl, from) {
      if (div)
      div.remove();
      canvas = document.createElement("canvas");
      context = canvas.getContext('2d');
      canvas.setAttribute("draggable", "true");
      canvas.setAttribute("id", settings.id);
      settings.maskImageUrl = imageUrl;
      div = $("<div/>", {
      "class": "masked-img"
      }).append(canvas);

      div.find("canvas").on('touchstart mousedown', function(event) {
      if (event.handled === false) return;
      event.handled = true;
      container.onDragStart(event);
      });

      div.find("canvas").on('touchend mouseup', function(event) {
      if (event.handled === false) return;
      event.handled = true;
      container.selected(event);
      });

      div.find("canvas").bind("dragover", container.onDragOver);
      container.append(div);
      if (settings.onMaskImageCreate)
      settings.onMaskImageCreate(div);
      container.loadImage(settings.imageUrl);
      };
      container.loadMaskImage(settings.maskImageUrl);
      JQmasks.push({
      item: container,
      id: settings.id
      })
      return container;
      };
      }(jQuery));
      </script>









      share|improve this question











      $endgroup$




      I am allowing users to upload and drag images with this code. Give me a review of this.



      Codepen



      <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

      <input id="fileup" type="file" >

      <div class="container">
      </div>

      <style>

      .temp {}

      .container {
      background: black;
      }

      .masked-img {
      overflow: hidden;
      margin-top: 30px;
      position: relative;
      }
      </style>


      <script>

      var mask;


      $(document).ready(function() {

      $.getJSON('9images.json', function(data)

      {
      var width = 0;
      var height = 0;

      let layer1 = data.layers;
      width = layer1[0].width;
      height = layer1[0].height;

      let layer2 = layer1[0].layers;

      for (i = 1; i < layer2.length; i++) {
      var x = layer2[i].x;
      var y = layer2[i].y;
      var src = layer2[i].layers[0].src;
      $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

      var mask = $(".container").mask({
      maskImageUrl: 'http://piccellsapp.com:1337/parse/files/PfAppId/' + src,
      onMaskImageCreate: function(img) {

      img.css({
      "position": "fixed",
      "left": x + "px",
      "top": y + "px"
      });
      }
      });

      fileup.onchange = function() {
      mask.loadImage(URL.createObjectURL(fileup.files[0]));
      };
      }

      });


      }); // end of document ready

      // jq plugin for mask
      (function($) {
      var JQmasks = ;
      $.fn.mask = function(options) {
      // This is the easiest way to have default options.
      var settings = $.extend({
      // These are the defaults.
      maskImageUrl: undefined,
      imageUrl: undefined,
      scale: 1,
      id: new Date().getUTCMilliseconds().toString(),
      x: 0, // image start position
      y: 0, // image start position
      onMaskImageCreate: function(div) {},
      }, options);


      var container = $(this);

      let prevX = 0,
      prevY = 0,
      draggable = false,
      img,
      canvas,
      context,
      image,
      timeout,
      initImage = false,
      startX = settings.x,
      startY = settings.y,
      div;

      container.mousePosition = function(event) {
      return {
      x: event.pageX || event.offsetX,
      y: event.pageY || event.offsetY
      };
      }

      container.selected = function(ev) {
      var pos = container.mousePosition(ev);
      var item = $(".masked-img canvas").filter(function() {
      var offset = $(this).offset()
      var x = pos.x - offset.left;
      var y = pos.y - offset.top;
      var d = this.getContext('2d').getImageData(x, y, 1, 1).data;
      return d[0] > 0
      });

      JQmasks.forEach(function(el) {
      var id = item.length > 0 ? $(item).attr("id") : "";
      if (el.id == id)
      el.item.enable();
      else el.item.disable();
      });
      };

      container.enable = function() {
      draggable = true;
      $(canvas).attr("active", "true");
      div.css({
      "z-index": 2
      });
      }

      container.disable = function() {
      draggable = false;
      $(canvas).attr("active", "false");
      div.css({
      "z-index": 1
      });
      }

      container.onDragStart = function(evt) {
      container.selected(evt);
      prevX = evt.clientX;
      prevY = evt.clientY;
      };

      container.getImagePosition = function() {
      return {
      x: settings.x,
      y: settings.y,
      scale: settings.scale
      };
      };

      container.onDragOver = function(evt) {
      if (draggable && $(canvas).attr("active") === "true") {
      var x = settings.x + evt.clientX - prevX;
      var y = settings.y + evt.clientY - prevY;
      if (x == settings.x && y == settings.y)
      return; // position has not changed
      settings.x += evt.clientX - prevX;
      settings.y += evt.clientY - prevY;
      prevX = evt.clientX;
      prevY = evt.clientY;
      container.updateStyle();
      }
      };

      container.updateStyle = function() {
      clearTimeout(timeout);
      timeout = setTimeout(function() {
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.beginPath();
      context.globalCompositeOperation = "source-over";
      image = new Image();
      image.setAttribute('crossOrigin', 'anonymous');
      image.src = settings.maskImageUrl;
      image.onload = function() {
      canvas.width = image.width;
      canvas.height = image.height;
      context.drawImage(image, 0, 0, image.width, image.height);
      div.css({
      "width": image.width,
      "height": image.height
      });
      };

      img = new Image();
      img.src = settings.imageUrl;
      img.setAttribute('crossOrigin', 'anonymous');
      img.onload = function() {
      settings.x = settings.x == 0 && initImage ? (canvas.width - (img.width * settings.scale)) / 2 : settings.x;
      settings.y = settings.y == 0 && initImage ? (canvas.height - (img.height * settings.scale)) / 2 : settings.y;
      context.globalCompositeOperation = 'source-atop';
      context.drawImage(img, settings.x, settings.y, img.width * settings.scale, img.height * settings.scale);
      initImage = false;
      };
      }, 0);
      };

      // change the draggable image
      container.loadImage = function(imageUrl) {
      if (img)
      img.remove();
      // reset the code.
      settings.y = startY;
      settings.x = startX;
      prevX = prevY = 0;
      settings.imageUrl = imageUrl;
      initImage = true;
      container.updateStyle();
      };

      // change the masked Image
      container.loadMaskImage = function(imageUrl, from) {
      if (div)
      div.remove();
      canvas = document.createElement("canvas");
      context = canvas.getContext('2d');
      canvas.setAttribute("draggable", "true");
      canvas.setAttribute("id", settings.id);
      settings.maskImageUrl = imageUrl;
      div = $("<div/>", {
      "class": "masked-img"
      }).append(canvas);

      div.find("canvas").on('touchstart mousedown', function(event) {
      if (event.handled === false) return;
      event.handled = true;
      container.onDragStart(event);
      });

      div.find("canvas").on('touchend mouseup', function(event) {
      if (event.handled === false) return;
      event.handled = true;
      container.selected(event);
      });

      div.find("canvas").bind("dragover", container.onDragOver);
      container.append(div);
      if (settings.onMaskImageCreate)
      settings.onMaskImageCreate(div);
      container.loadImage(settings.imageUrl);
      };
      container.loadMaskImage(settings.maskImageUrl);
      JQmasks.push({
      item: container,
      id: settings.id
      })
      return container;
      };
      }(jQuery));
      </script>






      javascript jquery css






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 33 mins ago









      Jamal

      30.3k11119227




      30.3k11119227










      asked yesterday









      vickey colorsvickey colors

      1215




      1215






















          1 Answer
          1






          active

          oldest

          votes


















          2












          $begingroup$

          Review



          I understand that you are learning, and this review may be a little harsh, but there has to be a minimum standard and your code and design falls short. That is not to say you have done poorly, for a beginner you have done well. If not a beginner, well...



          All good coders need access to a quality up to date reference. My preference is MDN, its not quite 5 star, but its keeps up with the tech, and missing content can always be found by following the standards links included with every reference.



          A good entry point is MDN javascript reference





          Interface



          The interface design is very unfriendly.



          What this needs




          • Your update and render functions are out of sync with the display which is causing very bad flicker as the image is being dragged.


          • The image is constrained to its edges. This means that if the image is larger than the mask it can not be moved.


          • There is no feedback for both the mouse and touch input. The mouse cursor should show appropriate cursors when mouse is over draggable image. While dragging, mouse over, or on touch, there should be a visible (top layer) outline of the dragged image so the user does not lose it under the mask.


          • The page is not responsive, and the scroll does not behave as expected. The page should scale to fit the visible page and be centered.


          • There is no way to adjust the relative scale of the draggable image.



          Extras



          Some extra features to make the app more usable.




          • Change the background or mask colour.


          • Mirror or rotate the draggable image. Use widget style handles (render in canvas) for mouse, and pinch scale and rotate for touch.


          • Add drag drop for image input.





          Code



          The main problem is that you are not rendering correctly. This means that the code needs to be rewritten from the ground up



          JQuery



          jQuery is unneeded bloat, (both for page load and resources) and is encouraging you into some very bad design. You DON'T need jQuery, modern browsers have very advanced APIs that are much faster than jQuery, using jQuery means you are not keeping up with the state of the art in front end web design.



          Examples of jQuery native equivalents



          /* You had...........................................................*/
          $.getJSON('9images.json', function(data) {

          // becomes
          fetch("9images.json").then(result => result.json().then(function(data) {

          /* You had...........................................................*/
          $(".container")
          // move to function scope and query once
          const container = document.querySelector(".container");

          /* You had...........................................................*/
          $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

          // becomes
          container.style.width = width + "px";
          container.style.height = height + "px";
          container.classList.add("temp");

          // or
          Object.assign(container.style, {width: width + "px", height: height + "px");
          container.classList.add("temp");

          /* You had...........................................................*/
          var settings = $.extend({
          // These are the defaults.
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0, // image start position
          y: 0, // image start position
          onMaskImageCreate: function(div) {},
          }, options);

          // becomes
          const settings = {
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0,
          y: 0,
          onMaskImageCreate: function(div) {},
          ...options,
          };

          /* You had...........................................................*/
          item.length > 0 ? $(item).attr("id") : "";

          // becomes
          item.length ? item[0].id : "";


          /* You had...........................................................*/
          div.css({
          "z-index": 1
          });

          // becomes
          div.style.zIndex = 1;

          /* You had...........................................................*/
          img.css({
          "position": "fixed",
          "left": x + "px",
          "top": y + "px"
          });

          // becomes
          Object.assign(img.style, {
          position : "fixed",
          left: x + "px",
          right: y + "px",
          });


          Rendering



          To stop the flicker you need to use requestAnimationFrame.



          Because mouse and touch events are not synced with the display device the render function needs to run in a polling loop. Mouse and touch events should signal via semaphore that there is need to render. The render function should check the semaphore and render as required.



          Example



          var renderUpdate = true; // semaphore to render content
          const mouse = {x,y,button};
          function mouseMoveListener(event) {
          mouse.x = event.pageX;
          mouse.y = event.pageY;
          renderUpdate = true;
          }
          function mouseOverOutListener(event) { // add to main canvas.
          mouse.cursor = event.type === "mouseover" ? "move" : "default";
          }


          requestAnimationFrame(renderLoop); // starts the loop
          function renderLoop() {
          if (renderUpdate) {
          // call render functions
          renderUpdate = false;
          }
          mainCanvas.cursor = mouse.cursor;
          requestAnimationFrame(renderLoop);
          }


          Compositing



          The DOM is fairly good at compositing, but it is not good at guessing what you want to do.



          Multi layer image editing is best done on a single canvas with the alpha turned off (Not transparent). In your render loop you can then have very fine control over how the compositing is done.



          eg

          // alpha : false. Prevents the DOM from compositing the canvas with the
          // page background, which may not even be visible.
          const ctx = mainCanvas.getContext("2d", {alpha : false}); // do once

          // load images and masks to a single array
          const layers = ;
          function addLayer(imgUrl) {
          const image = new Image;
          image.src = imgURL;
          image.onload = () => { // add image to layers when loaded
          layers.push({image, x : 0, y : 0, scale : 1});
          }
          // To do
          // Add handler for image error
          }

          // only call this from within the requestAnimationFrame callback function
          function renderLayers(layers) {
          // As the canvas is not transparent you need to set the background colour
          ctx.fillStyle = backgroundColor;
          ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

          for (const layer of layers) {
          ctx.drawImage(
          layer.image,
          layer.x, layer.y,
          layer.image.width * layer.scale,
          layer.image.height * layer.scale
          );
          }
          }





          share|improve this answer









          $endgroup$













          • $begingroup$
            Thanks a lot for your valuable time and suggestion , I will really follow it , you are right that sometimes larger images are not dragging , smaller images don't have any problem in dragging.... If you can give me updated code in codepen or in snippet , than it will be really very very helpful for me , when you get free time , please give me full code in codepen or snippet.....
            $endgroup$
            – vickey colors
            yesterday











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214525%2fupload-and-drag-the-image-inside-a-mask-image%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2












          $begingroup$

          Review



          I understand that you are learning, and this review may be a little harsh, but there has to be a minimum standard and your code and design falls short. That is not to say you have done poorly, for a beginner you have done well. If not a beginner, well...



          All good coders need access to a quality up to date reference. My preference is MDN, its not quite 5 star, but its keeps up with the tech, and missing content can always be found by following the standards links included with every reference.



          A good entry point is MDN javascript reference





          Interface



          The interface design is very unfriendly.



          What this needs




          • Your update and render functions are out of sync with the display which is causing very bad flicker as the image is being dragged.


          • The image is constrained to its edges. This means that if the image is larger than the mask it can not be moved.


          • There is no feedback for both the mouse and touch input. The mouse cursor should show appropriate cursors when mouse is over draggable image. While dragging, mouse over, or on touch, there should be a visible (top layer) outline of the dragged image so the user does not lose it under the mask.


          • The page is not responsive, and the scroll does not behave as expected. The page should scale to fit the visible page and be centered.


          • There is no way to adjust the relative scale of the draggable image.



          Extras



          Some extra features to make the app more usable.




          • Change the background or mask colour.


          • Mirror or rotate the draggable image. Use widget style handles (render in canvas) for mouse, and pinch scale and rotate for touch.


          • Add drag drop for image input.





          Code



          The main problem is that you are not rendering correctly. This means that the code needs to be rewritten from the ground up



          JQuery



          jQuery is unneeded bloat, (both for page load and resources) and is encouraging you into some very bad design. You DON'T need jQuery, modern browsers have very advanced APIs that are much faster than jQuery, using jQuery means you are not keeping up with the state of the art in front end web design.



          Examples of jQuery native equivalents



          /* You had...........................................................*/
          $.getJSON('9images.json', function(data) {

          // becomes
          fetch("9images.json").then(result => result.json().then(function(data) {

          /* You had...........................................................*/
          $(".container")
          // move to function scope and query once
          const container = document.querySelector(".container");

          /* You had...........................................................*/
          $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

          // becomes
          container.style.width = width + "px";
          container.style.height = height + "px";
          container.classList.add("temp");

          // or
          Object.assign(container.style, {width: width + "px", height: height + "px");
          container.classList.add("temp");

          /* You had...........................................................*/
          var settings = $.extend({
          // These are the defaults.
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0, // image start position
          y: 0, // image start position
          onMaskImageCreate: function(div) {},
          }, options);

          // becomes
          const settings = {
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0,
          y: 0,
          onMaskImageCreate: function(div) {},
          ...options,
          };

          /* You had...........................................................*/
          item.length > 0 ? $(item).attr("id") : "";

          // becomes
          item.length ? item[0].id : "";


          /* You had...........................................................*/
          div.css({
          "z-index": 1
          });

          // becomes
          div.style.zIndex = 1;

          /* You had...........................................................*/
          img.css({
          "position": "fixed",
          "left": x + "px",
          "top": y + "px"
          });

          // becomes
          Object.assign(img.style, {
          position : "fixed",
          left: x + "px",
          right: y + "px",
          });


          Rendering



          To stop the flicker you need to use requestAnimationFrame.



          Because mouse and touch events are not synced with the display device the render function needs to run in a polling loop. Mouse and touch events should signal via semaphore that there is need to render. The render function should check the semaphore and render as required.



          Example



          var renderUpdate = true; // semaphore to render content
          const mouse = {x,y,button};
          function mouseMoveListener(event) {
          mouse.x = event.pageX;
          mouse.y = event.pageY;
          renderUpdate = true;
          }
          function mouseOverOutListener(event) { // add to main canvas.
          mouse.cursor = event.type === "mouseover" ? "move" : "default";
          }


          requestAnimationFrame(renderLoop); // starts the loop
          function renderLoop() {
          if (renderUpdate) {
          // call render functions
          renderUpdate = false;
          }
          mainCanvas.cursor = mouse.cursor;
          requestAnimationFrame(renderLoop);
          }


          Compositing



          The DOM is fairly good at compositing, but it is not good at guessing what you want to do.



          Multi layer image editing is best done on a single canvas with the alpha turned off (Not transparent). In your render loop you can then have very fine control over how the compositing is done.



          eg

          // alpha : false. Prevents the DOM from compositing the canvas with the
          // page background, which may not even be visible.
          const ctx = mainCanvas.getContext("2d", {alpha : false}); // do once

          // load images and masks to a single array
          const layers = ;
          function addLayer(imgUrl) {
          const image = new Image;
          image.src = imgURL;
          image.onload = () => { // add image to layers when loaded
          layers.push({image, x : 0, y : 0, scale : 1});
          }
          // To do
          // Add handler for image error
          }

          // only call this from within the requestAnimationFrame callback function
          function renderLayers(layers) {
          // As the canvas is not transparent you need to set the background colour
          ctx.fillStyle = backgroundColor;
          ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

          for (const layer of layers) {
          ctx.drawImage(
          layer.image,
          layer.x, layer.y,
          layer.image.width * layer.scale,
          layer.image.height * layer.scale
          );
          }
          }





          share|improve this answer









          $endgroup$













          • $begingroup$
            Thanks a lot for your valuable time and suggestion , I will really follow it , you are right that sometimes larger images are not dragging , smaller images don't have any problem in dragging.... If you can give me updated code in codepen or in snippet , than it will be really very very helpful for me , when you get free time , please give me full code in codepen or snippet.....
            $endgroup$
            – vickey colors
            yesterday
















          2












          $begingroup$

          Review



          I understand that you are learning, and this review may be a little harsh, but there has to be a minimum standard and your code and design falls short. That is not to say you have done poorly, for a beginner you have done well. If not a beginner, well...



          All good coders need access to a quality up to date reference. My preference is MDN, its not quite 5 star, but its keeps up with the tech, and missing content can always be found by following the standards links included with every reference.



          A good entry point is MDN javascript reference





          Interface



          The interface design is very unfriendly.



          What this needs




          • Your update and render functions are out of sync with the display which is causing very bad flicker as the image is being dragged.


          • The image is constrained to its edges. This means that if the image is larger than the mask it can not be moved.


          • There is no feedback for both the mouse and touch input. The mouse cursor should show appropriate cursors when mouse is over draggable image. While dragging, mouse over, or on touch, there should be a visible (top layer) outline of the dragged image so the user does not lose it under the mask.


          • The page is not responsive, and the scroll does not behave as expected. The page should scale to fit the visible page and be centered.


          • There is no way to adjust the relative scale of the draggable image.



          Extras



          Some extra features to make the app more usable.




          • Change the background or mask colour.


          • Mirror or rotate the draggable image. Use widget style handles (render in canvas) for mouse, and pinch scale and rotate for touch.


          • Add drag drop for image input.





          Code



          The main problem is that you are not rendering correctly. This means that the code needs to be rewritten from the ground up



          JQuery



          jQuery is unneeded bloat, (both for page load and resources) and is encouraging you into some very bad design. You DON'T need jQuery, modern browsers have very advanced APIs that are much faster than jQuery, using jQuery means you are not keeping up with the state of the art in front end web design.



          Examples of jQuery native equivalents



          /* You had...........................................................*/
          $.getJSON('9images.json', function(data) {

          // becomes
          fetch("9images.json").then(result => result.json().then(function(data) {

          /* You had...........................................................*/
          $(".container")
          // move to function scope and query once
          const container = document.querySelector(".container");

          /* You had...........................................................*/
          $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

          // becomes
          container.style.width = width + "px";
          container.style.height = height + "px";
          container.classList.add("temp");

          // or
          Object.assign(container.style, {width: width + "px", height: height + "px");
          container.classList.add("temp");

          /* You had...........................................................*/
          var settings = $.extend({
          // These are the defaults.
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0, // image start position
          y: 0, // image start position
          onMaskImageCreate: function(div) {},
          }, options);

          // becomes
          const settings = {
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0,
          y: 0,
          onMaskImageCreate: function(div) {},
          ...options,
          };

          /* You had...........................................................*/
          item.length > 0 ? $(item).attr("id") : "";

          // becomes
          item.length ? item[0].id : "";


          /* You had...........................................................*/
          div.css({
          "z-index": 1
          });

          // becomes
          div.style.zIndex = 1;

          /* You had...........................................................*/
          img.css({
          "position": "fixed",
          "left": x + "px",
          "top": y + "px"
          });

          // becomes
          Object.assign(img.style, {
          position : "fixed",
          left: x + "px",
          right: y + "px",
          });


          Rendering



          To stop the flicker you need to use requestAnimationFrame.



          Because mouse and touch events are not synced with the display device the render function needs to run in a polling loop. Mouse and touch events should signal via semaphore that there is need to render. The render function should check the semaphore and render as required.



          Example



          var renderUpdate = true; // semaphore to render content
          const mouse = {x,y,button};
          function mouseMoveListener(event) {
          mouse.x = event.pageX;
          mouse.y = event.pageY;
          renderUpdate = true;
          }
          function mouseOverOutListener(event) { // add to main canvas.
          mouse.cursor = event.type === "mouseover" ? "move" : "default";
          }


          requestAnimationFrame(renderLoop); // starts the loop
          function renderLoop() {
          if (renderUpdate) {
          // call render functions
          renderUpdate = false;
          }
          mainCanvas.cursor = mouse.cursor;
          requestAnimationFrame(renderLoop);
          }


          Compositing



          The DOM is fairly good at compositing, but it is not good at guessing what you want to do.



          Multi layer image editing is best done on a single canvas with the alpha turned off (Not transparent). In your render loop you can then have very fine control over how the compositing is done.



          eg

          // alpha : false. Prevents the DOM from compositing the canvas with the
          // page background, which may not even be visible.
          const ctx = mainCanvas.getContext("2d", {alpha : false}); // do once

          // load images and masks to a single array
          const layers = ;
          function addLayer(imgUrl) {
          const image = new Image;
          image.src = imgURL;
          image.onload = () => { // add image to layers when loaded
          layers.push({image, x : 0, y : 0, scale : 1});
          }
          // To do
          // Add handler for image error
          }

          // only call this from within the requestAnimationFrame callback function
          function renderLayers(layers) {
          // As the canvas is not transparent you need to set the background colour
          ctx.fillStyle = backgroundColor;
          ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

          for (const layer of layers) {
          ctx.drawImage(
          layer.image,
          layer.x, layer.y,
          layer.image.width * layer.scale,
          layer.image.height * layer.scale
          );
          }
          }





          share|improve this answer









          $endgroup$













          • $begingroup$
            Thanks a lot for your valuable time and suggestion , I will really follow it , you are right that sometimes larger images are not dragging , smaller images don't have any problem in dragging.... If you can give me updated code in codepen or in snippet , than it will be really very very helpful for me , when you get free time , please give me full code in codepen or snippet.....
            $endgroup$
            – vickey colors
            yesterday














          2












          2








          2





          $begingroup$

          Review



          I understand that you are learning, and this review may be a little harsh, but there has to be a minimum standard and your code and design falls short. That is not to say you have done poorly, for a beginner you have done well. If not a beginner, well...



          All good coders need access to a quality up to date reference. My preference is MDN, its not quite 5 star, but its keeps up with the tech, and missing content can always be found by following the standards links included with every reference.



          A good entry point is MDN javascript reference





          Interface



          The interface design is very unfriendly.



          What this needs




          • Your update and render functions are out of sync with the display which is causing very bad flicker as the image is being dragged.


          • The image is constrained to its edges. This means that if the image is larger than the mask it can not be moved.


          • There is no feedback for both the mouse and touch input. The mouse cursor should show appropriate cursors when mouse is over draggable image. While dragging, mouse over, or on touch, there should be a visible (top layer) outline of the dragged image so the user does not lose it under the mask.


          • The page is not responsive, and the scroll does not behave as expected. The page should scale to fit the visible page and be centered.


          • There is no way to adjust the relative scale of the draggable image.



          Extras



          Some extra features to make the app more usable.




          • Change the background or mask colour.


          • Mirror or rotate the draggable image. Use widget style handles (render in canvas) for mouse, and pinch scale and rotate for touch.


          • Add drag drop for image input.





          Code



          The main problem is that you are not rendering correctly. This means that the code needs to be rewritten from the ground up



          JQuery



          jQuery is unneeded bloat, (both for page load and resources) and is encouraging you into some very bad design. You DON'T need jQuery, modern browsers have very advanced APIs that are much faster than jQuery, using jQuery means you are not keeping up with the state of the art in front end web design.



          Examples of jQuery native equivalents



          /* You had...........................................................*/
          $.getJSON('9images.json', function(data) {

          // becomes
          fetch("9images.json").then(result => result.json().then(function(data) {

          /* You had...........................................................*/
          $(".container")
          // move to function scope and query once
          const container = document.querySelector(".container");

          /* You had...........................................................*/
          $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

          // becomes
          container.style.width = width + "px";
          container.style.height = height + "px";
          container.classList.add("temp");

          // or
          Object.assign(container.style, {width: width + "px", height: height + "px");
          container.classList.add("temp");

          /* You had...........................................................*/
          var settings = $.extend({
          // These are the defaults.
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0, // image start position
          y: 0, // image start position
          onMaskImageCreate: function(div) {},
          }, options);

          // becomes
          const settings = {
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0,
          y: 0,
          onMaskImageCreate: function(div) {},
          ...options,
          };

          /* You had...........................................................*/
          item.length > 0 ? $(item).attr("id") : "";

          // becomes
          item.length ? item[0].id : "";


          /* You had...........................................................*/
          div.css({
          "z-index": 1
          });

          // becomes
          div.style.zIndex = 1;

          /* You had...........................................................*/
          img.css({
          "position": "fixed",
          "left": x + "px",
          "top": y + "px"
          });

          // becomes
          Object.assign(img.style, {
          position : "fixed",
          left: x + "px",
          right: y + "px",
          });


          Rendering



          To stop the flicker you need to use requestAnimationFrame.



          Because mouse and touch events are not synced with the display device the render function needs to run in a polling loop. Mouse and touch events should signal via semaphore that there is need to render. The render function should check the semaphore and render as required.



          Example



          var renderUpdate = true; // semaphore to render content
          const mouse = {x,y,button};
          function mouseMoveListener(event) {
          mouse.x = event.pageX;
          mouse.y = event.pageY;
          renderUpdate = true;
          }
          function mouseOverOutListener(event) { // add to main canvas.
          mouse.cursor = event.type === "mouseover" ? "move" : "default";
          }


          requestAnimationFrame(renderLoop); // starts the loop
          function renderLoop() {
          if (renderUpdate) {
          // call render functions
          renderUpdate = false;
          }
          mainCanvas.cursor = mouse.cursor;
          requestAnimationFrame(renderLoop);
          }


          Compositing



          The DOM is fairly good at compositing, but it is not good at guessing what you want to do.



          Multi layer image editing is best done on a single canvas with the alpha turned off (Not transparent). In your render loop you can then have very fine control over how the compositing is done.



          eg

          // alpha : false. Prevents the DOM from compositing the canvas with the
          // page background, which may not even be visible.
          const ctx = mainCanvas.getContext("2d", {alpha : false}); // do once

          // load images and masks to a single array
          const layers = ;
          function addLayer(imgUrl) {
          const image = new Image;
          image.src = imgURL;
          image.onload = () => { // add image to layers when loaded
          layers.push({image, x : 0, y : 0, scale : 1});
          }
          // To do
          // Add handler for image error
          }

          // only call this from within the requestAnimationFrame callback function
          function renderLayers(layers) {
          // As the canvas is not transparent you need to set the background colour
          ctx.fillStyle = backgroundColor;
          ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

          for (const layer of layers) {
          ctx.drawImage(
          layer.image,
          layer.x, layer.y,
          layer.image.width * layer.scale,
          layer.image.height * layer.scale
          );
          }
          }





          share|improve this answer









          $endgroup$



          Review



          I understand that you are learning, and this review may be a little harsh, but there has to be a minimum standard and your code and design falls short. That is not to say you have done poorly, for a beginner you have done well. If not a beginner, well...



          All good coders need access to a quality up to date reference. My preference is MDN, its not quite 5 star, but its keeps up with the tech, and missing content can always be found by following the standards links included with every reference.



          A good entry point is MDN javascript reference





          Interface



          The interface design is very unfriendly.



          What this needs




          • Your update and render functions are out of sync with the display which is causing very bad flicker as the image is being dragged.


          • The image is constrained to its edges. This means that if the image is larger than the mask it can not be moved.


          • There is no feedback for both the mouse and touch input. The mouse cursor should show appropriate cursors when mouse is over draggable image. While dragging, mouse over, or on touch, there should be a visible (top layer) outline of the dragged image so the user does not lose it under the mask.


          • The page is not responsive, and the scroll does not behave as expected. The page should scale to fit the visible page and be centered.


          • There is no way to adjust the relative scale of the draggable image.



          Extras



          Some extra features to make the app more usable.




          • Change the background or mask colour.


          • Mirror or rotate the draggable image. Use widget style handles (render in canvas) for mouse, and pinch scale and rotate for touch.


          • Add drag drop for image input.





          Code



          The main problem is that you are not rendering correctly. This means that the code needs to be rewritten from the ground up



          JQuery



          jQuery is unneeded bloat, (both for page load and resources) and is encouraging you into some very bad design. You DON'T need jQuery, modern browsers have very advanced APIs that are much faster than jQuery, using jQuery means you are not keeping up with the state of the art in front end web design.



          Examples of jQuery native equivalents



          /* You had...........................................................*/
          $.getJSON('9images.json', function(data) {

          // becomes
          fetch("9images.json").then(result => result.json().then(function(data) {

          /* You had...........................................................*/
          $(".container")
          // move to function scope and query once
          const container = document.querySelector(".container");

          /* You had...........................................................*/
          $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

          // becomes
          container.style.width = width + "px";
          container.style.height = height + "px";
          container.classList.add("temp");

          // or
          Object.assign(container.style, {width: width + "px", height: height + "px");
          container.classList.add("temp");

          /* You had...........................................................*/
          var settings = $.extend({
          // These are the defaults.
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0, // image start position
          y: 0, // image start position
          onMaskImageCreate: function(div) {},
          }, options);

          // becomes
          const settings = {
          maskImageUrl: undefined,
          imageUrl: undefined,
          scale: 1,
          id: new Date().getUTCMilliseconds().toString(),
          x: 0,
          y: 0,
          onMaskImageCreate: function(div) {},
          ...options,
          };

          /* You had...........................................................*/
          item.length > 0 ? $(item).attr("id") : "";

          // becomes
          item.length ? item[0].id : "";


          /* You had...........................................................*/
          div.css({
          "z-index": 1
          });

          // becomes
          div.style.zIndex = 1;

          /* You had...........................................................*/
          img.css({
          "position": "fixed",
          "left": x + "px",
          "top": y + "px"
          });

          // becomes
          Object.assign(img.style, {
          position : "fixed",
          left: x + "px",
          right: y + "px",
          });


          Rendering



          To stop the flicker you need to use requestAnimationFrame.



          Because mouse and touch events are not synced with the display device the render function needs to run in a polling loop. Mouse and touch events should signal via semaphore that there is need to render. The render function should check the semaphore and render as required.



          Example



          var renderUpdate = true; // semaphore to render content
          const mouse = {x,y,button};
          function mouseMoveListener(event) {
          mouse.x = event.pageX;
          mouse.y = event.pageY;
          renderUpdate = true;
          }
          function mouseOverOutListener(event) { // add to main canvas.
          mouse.cursor = event.type === "mouseover" ? "move" : "default";
          }


          requestAnimationFrame(renderLoop); // starts the loop
          function renderLoop() {
          if (renderUpdate) {
          // call render functions
          renderUpdate = false;
          }
          mainCanvas.cursor = mouse.cursor;
          requestAnimationFrame(renderLoop);
          }


          Compositing



          The DOM is fairly good at compositing, but it is not good at guessing what you want to do.



          Multi layer image editing is best done on a single canvas with the alpha turned off (Not transparent). In your render loop you can then have very fine control over how the compositing is done.



          eg

          // alpha : false. Prevents the DOM from compositing the canvas with the
          // page background, which may not even be visible.
          const ctx = mainCanvas.getContext("2d", {alpha : false}); // do once

          // load images and masks to a single array
          const layers = ;
          function addLayer(imgUrl) {
          const image = new Image;
          image.src = imgURL;
          image.onload = () => { // add image to layers when loaded
          layers.push({image, x : 0, y : 0, scale : 1});
          }
          // To do
          // Add handler for image error
          }

          // only call this from within the requestAnimationFrame callback function
          function renderLayers(layers) {
          // As the canvas is not transparent you need to set the background colour
          ctx.fillStyle = backgroundColor;
          ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

          for (const layer of layers) {
          ctx.drawImage(
          layer.image,
          layer.x, layer.y,
          layer.image.width * layer.scale,
          layer.image.height * layer.scale
          );
          }
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered yesterday









          Blindman67Blindman67

          8,2601521




          8,2601521












          • $begingroup$
            Thanks a lot for your valuable time and suggestion , I will really follow it , you are right that sometimes larger images are not dragging , smaller images don't have any problem in dragging.... If you can give me updated code in codepen or in snippet , than it will be really very very helpful for me , when you get free time , please give me full code in codepen or snippet.....
            $endgroup$
            – vickey colors
            yesterday


















          • $begingroup$
            Thanks a lot for your valuable time and suggestion , I will really follow it , you are right that sometimes larger images are not dragging , smaller images don't have any problem in dragging.... If you can give me updated code in codepen or in snippet , than it will be really very very helpful for me , when you get free time , please give me full code in codepen or snippet.....
            $endgroup$
            – vickey colors
            yesterday
















          $begingroup$
          Thanks a lot for your valuable time and suggestion , I will really follow it , you are right that sometimes larger images are not dragging , smaller images don't have any problem in dragging.... If you can give me updated code in codepen or in snippet , than it will be really very very helpful for me , when you get free time , please give me full code in codepen or snippet.....
          $endgroup$
          – vickey colors
          yesterday




          $begingroup$
          Thanks a lot for your valuable time and suggestion , I will really follow it , you are right that sometimes larger images are not dragging , smaller images don't have any problem in dragging.... If you can give me updated code in codepen or in snippet , than it will be really very very helpful for me , when you get free time , please give me full code in codepen or snippet.....
          $endgroup$
          – vickey colors
          yesterday


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214525%2fupload-and-drag-the-image-inside-a-mask-image%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          404 Error Contact Form 7 ajax form submitting

          How to know if a Active Directory user can login interactively

          Refactoring coordinates for Minecraft Pi buildings written in Python