I am fetching image & its positions [left(x) & top (y)] from json with help of below code & displaying in html page.... if there is single image in json, than its working fine....
var mask1;
$(document).ready(function()
{
var maskedImageUrla = "";
var coordinates = {
x: 0,
y: 0
};
var width = 0;
var height = 0;
$.getJSON('2images.json', function(json)
{
for (let layer of json.layers)
{
width = layer.width;
height = layer.height;
if (layer.layers && layer.layers.length > 0)
{
for (let temp of layer.layers)
{
if (temp.src) maskedImageUrla = temp.src;
else if (temp.layers)
{
for (let tl of temp.layers)
if (tl.src)
{
maskedImageUrla = 'http://piccellsapp.com:1337/parse/files/PfAppId/' + tl.src;
coordinates.x = temp.x;
coordinates.y = temp.y;
}
}
}
}
}
$(".container").css('width', width + "px").css('height', height + "px").addClass('temp');
var mask1 = $(".container").mask({
maskImageUrl: maskedImageUrla, // get image
onMaskImageCreate: function(img) {
img.css({
"position": "fixed",
"left": coordinates.x + "px", // get x
"top": coordinates.y + "px" // get y
});
}
});
fileupa1.onchange = function() {
mask1.loadImage(URL.createObjectURL(fileupa1.files[0]));
};
});
}); // end of document ready
Requirement :
but if there are multiple images in json, than only one image is fetching, but how to fetch all images [src] & its positions [ x & y ]....
Codepen [ 2 images json ] : https://codepen.io/kidsdial/pen/RdwXpZ
Edit : Below is Code snippet :
var mask1;
$(document).ready(function()
{
var maskedImageUrla = "";
var coordinates = {
x: 0,
y: 0
};
var width = 0;
var height = 0;
var json = {
"name": "newyear collage",
"layers": [
{
"x": 0,
"height": 612,
"layers": [
{
"x": 0,
"y": 0
},
{
"x": 160,
"layers": [
{
"x": 0,
"src": "AX7HBOE.png",
"y": 0,
"name": "mask_image_1"
},
{
"name": "useradd_ellipse1"
}
],
"y": 291,
"name": "user_image_1"
},
{
"x": 25,
"layers": [
{
"x": 0,
"src": "o5P9tdZ.png",
"y": 0,
"name": "mask_image_2"
},
{
"name": "useradd_ellipse_2"
}
],
"y": 22,
"name": "user_image_2"
}
],
"y": 0,
"width": 612,
"name": "newyearcollage08"
}
]
};
for (let layer of json.layers)
{
width = layer.width;
height = layer.height;
if (layer.layers && layer.layers.length > 0)
{
for (let temp of layer.layers)
{
if (temp.src) maskedImageUrla = temp.src;
else if (temp.layers)
{
for (let tl of temp.layers)
if (tl.src)
{
maskedImageUrla = 'https://i.imgur.com/' + tl.src;
coordinates.x = temp.x;
coordinates.y = temp.y;
}
}
}
}
}
$(".container").css('width', width + "px").css('height', height + "px").addClass('temp');
var mask1 = $(".container").mask({
maskImageUrl: maskedImageUrla, // get image
onMaskImageCreate: function(img) {
img.css({
"position": "fixed",
"left": coordinates.x + "px", // get x
"top": coordinates.y + "px" // get y
});
}
});
fileupa1.onchange = function() {
mask1.loadImage(URL.createObjectURL(fileupa1.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));
.temp
{
border: 1px solid #DDDDDD;
display: flex;
background :silver;
}
.container canvas {
display: block;
}
.masked-img {
overflow: hidden;
margin-top: 50px;
position: relative;
}
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
image 1
<input id="fileupa1" type="file" >
<div class="container">
</div>
</head>
let jsonData2 = {
"path" : " newyear collage\/",
"info" : {
"author" : "",
"keywords" : "",
"file" : "newyear collage",
"date" : "sRGB",
"title" : "",
"description" : "Normal",
"generator" : "Export Kit v1.2.8"
},
"name" : "newyear collage",
"layers" : [
{
"x" : 0,
"height" : 612,
"layers" : [
{
"x" : 0,
"color" : "0xFFFFFF",
"height" : 612,
"y" : 0,
"width" : 612,
"shapeType" : "rectangle",
"type" : "shape",
"name" : "bg_rectangle"
},
{
"x" : 160,
"height" : 296,
"layers" : [
{
"x" : 0,
"height" : 296,
"src" : "6b8e734c46539dbc73f51e8f65d29fe3_frame0.png",
"y" : 0,
"width" : 429,
"type" : "image",
"name" : "mask_image_1"
},
{
"radius" : "26 \/ 27",
"color" : "0xACACAC",
"x" : 188,
"y" : 122,
"height" : 53,
"width" : 53,
"shapeType" : "ellipse",
"type" : "shape",
"name" : "useradd_ellipse1"
}
],
"y" : 291,
"width" : 429,
"type" : "group",
"name" : "user_image_1"
},
{
"x" : 25,
"height" : 324,
"layers" : [
{
"x" : 0,
"height" : 324,
"src" : "eb8e531ec340da14688a6343769286c0_frame1.png",
"y" : 0,
"width" : 471,
"type" : "image",
"name" : "mask_image_2"
},
{
"radius" : "26 \/ 27",
"color" : "0xACACAC",
"x" : 209,
"y" : 136,
"height" : 53,
"width" : 53,
"shapeType" : "ellipse",
"type" : "shape",
"name" : "useradd_ellipse_2"
}
],
"y" : 22,
"width" : 471,
"type" : "group",
"name" : "user_image_2"
}
],
"y" : 0,
"width" : 612,
"type" : "group",
"name" : "newyearcollage08"
}
]
};
let jsonData = {
"path": " UNEVENSHAPES\/",
"info": {
"author": "",
"keywords": "",
"file": "UNEVENSHAPES",
"date": "Uncalibrated",
"title": "",
"description": "Normal",
"generator": "Export Kit v1.2.8"
},
"name": "UNEVENSHAPES",
"layers": [{
"x": 0,
"height": 612,
"layers": [{
"x": 0,
"color": "0xFFFFFF",
"height": 612,
"y": 0,
"width": 612,
"shapeType": "rectangle",
"type": "shape",
"name": "rectangle1"
},
{
"x": 20,
"height": 377,
"layers": [{
"x": 0,
"height": 377,
"src": "d15ad70281961be451263b418a07798b_frame0.png",
"y": 0,
"width": 218,
"type": "image",
"name": "mask_pic1"
},
{
"radius": "27 \/ 27",
"color": "0xACACAC",
"x": 52,
"y": 257,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse1"
}
],
"y": 215,
"width": 218,
"type": "group",
"name": "user_pic1"
},
{
"x": 191,
"height": 120,
"layers": [{
"x": 0,
"height": 120,
"src": "2b5d28d0439bc3ce1d856e6c4e5607be_frame1.png",
"y": 0,
"width": 268,
"type": "image",
"name": "mask_pic2"
},
{
"radius": "26 \/ 27",
"color": "0xACACAC",
"x": 115,
"y": 43,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse2"
}
],
"y": 472,
"width": 268,
"type": "group",
"name": "user_pic2"
},
{
"x": 414,
"height": 302,
"layers": [{
"x": 0,
"height": 302,
"src": "52c93b6e0a0ffeeb670d0981f89f7fa5_frame2.png",
"y": 0,
"width": 178,
"type": "image",
"name": "mask_pic3"
},
{
"radius": "26 \/ 27",
"color": "0xACACAC",
"x": 69,
"y": 182,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse3"
}
],
"y": 290,
"width": 178,
"type": "group",
"name": "user_pic3"
},
{
"x": 374,
"height": 377,
"layers": [{
"x": 0,
"height": 377,
"src": "e92f354018aa8f7e6d279601a868a6b2_frame3.png",
"y": 0,
"width": 218,
"type": "image",
"name": "mask_pic4"
},
{
"radius": "26 \/ 27",
"color": "0xACACAC",
"x": 129,
"y": 60,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse4"
}
],
"y": 20,
"width": 218,
"type": "group",
"name": "user_pic4"
},
{
"x": 150,
"height": 120,
"layers": [{
"x": 0,
"height": 120,
"src": "010054750abb290d1bd7fcecfab60524_frame4.png",
"y": 0,
"width": 269,
"type": "image",
"name": "mask_pic5"
},
{
"radius": "27 \/ 27",
"color": "0xACACAC",
"x": 103,
"y": 15,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse5"
}
],
"y": 20,
"width": 269,
"type": "group",
"name": "user_pic5"
},
{
"x": 20,
"height": 302,
"layers": [{
"x": 0,
"height": 302,
"src": "e7a5874b58376883adbeafea7ce5e572_frame5.png",
"y": 0,
"width": 176,
"type": "image",
"name": "mask_pic6"
},
{
"radius": "26 \/ 27",
"color": "0xACACAC",
"x": 50,
"y": 68,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse6"
}
],
"y": 20,
"width": 176,
"type": "group",
"name": "user_pic6"
},
{
"x": 222,
"height": 335,
"layers": [{
"x": 0,
"height": 335,
"src": "591743efa89d8ee936a6d660d52e82b2_frame6.png",
"y": 0,
"width": 265,
"type": "image",
"name": "mask_pic7"
},
{
"radius": "26 \/ 27",
"color": "0xACACAC",
"x": 126,
"y": 114,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse7"
}
],
"y": 123,
"width": 265,
"type": "group",
"name": "user_pic7"
},
{
"x": 123,
"height": 334,
"layers": [{
"x": 0,
"height": 334,
"src": "22997a60cf61d7b59e92620b86ab86d6_frame7.png",
"y": 0,
"width": 264,
"type": "image",
"name": "mask_pic8"
},
{
"radius": "27 \/ 27",
"color": "0xACACAC",
"x": 73,
"y": 167,
"height": 53,
"width": 53,
"shapeType": "ellipse",
"type": "shape",
"name": "useradd_ellipse8"
}
],
"y": 155,
"width": 264,
"type": "group",
"name": "user_pic8"
}
],
"y": 0,
"width": 612,
"type": "group",
"name": "unevenshape04"
}]
};
function getData(data) {
var dataObj = {};
let layer1 = data.layers;
let layer2 = layer1[0].layers;
console.log('New Data');
for (i = 1; i < layer2.length; i++) {
var x = layer2[i].x;
var y = layer2[i].y;
var src = layer2[i].layers[0].src;
console.log(x,y,src);
}
}
getData(jsonData);
getData(jsonData2);
the json part is ok. But after that in
var mask1 = $(".container").mask({
maskImageUrl: maskedImageUrla, // get image
you create only one image, with the last value of maskedImageUrla.
What you can do is store your images in an array and iterate over them, as in :
$.getJSON('2images.json', function(json)
{
const images = [];
for (let layer of json.layers)
...
for (let tl of temp.layers)
if (tl.src) {
images.push({
maskedImageUrla = 'http://piccellsapp.com:1337/parse/files/PfAppId/' + tl.src,
coordinates.x = temp.x,
coordinates.y = temp.y
})
}
...
images.forEach(image => {
var mask1 = $(".container").mask({
maskImageUrl: image.maskedImageUrla, // get image
onMaskImageCreate: function(img) {
img.css({
"position": "fixed",
"left": image.coordinates.x + "px", // get x
"top": image.coordinates.y + "px" // get y
});
}
});
fileupa1.onchange = function() {
mask1.loadImage(URL.createObjectURL(fileupa1.files[0]));
};
});
Related
I'm cropping teeth section (mouth) from face based on x,y co-ordinates received from AWS recognition face API
this code is working and cropping the teeth section like
but I need only teeth section to be cropped.
AWS recognition API image response
[
{
"BoundingBox": {
"Width": 0.4604368805885315,
"Height": 0.7760819792747498,
"Left": 0.28602713346481323,
"Top": 0.07381705939769745
},
"AgeRange": {
"Low": 48,
"High": 66
},
"Smile": {
"Value": true,
"Confidence": 99.91497802734375
},
"Eyeglasses": {
"Value": false,
"Confidence": 98.94174194335938
},
"Sunglasses": {
"Value": false,
"Confidence": 99.84471130371094
},
"Gender": {
"Value": "Male",
"Confidence": 99.57334899902344
},
"Beard": {
"Value": false,
"Confidence": 73.63420867919922
},
"Mustache": {
"Value": false,
"Confidence": 96.08769226074219
},
"EyesOpen": {
"Value": true,
"Confidence": 98.94685363769531
},
"MouthOpen": {
"Value": true,
"Confidence": 99.7721939086914
},
"Emotions": [
{
"Type": "HAPPY",
"Confidence": 99.75701904296875
},
{
"Type": "SURPRISED",
"Confidence": 0.10713297128677368
},
{
"Type": "CONFUSED",
"Confidence": 0.056786004453897476
},
{
"Type": "CALM",
"Confidence": 0.02734198607504368
},
{
"Type": "ANGRY",
"Confidence": 0.020567195490002632
},
{
"Type": "DISGUSTED",
"Confidence": 0.01198340579867363
},
{
"Type": "SAD",
"Confidence": 0.011844608001410961
},
{
"Type": "FEAR",
"Confidence": 0.007329543586820364
}
],
"Landmarks": [
{
"Type": "eyeLeft",
"X": 0.4020455777645111,
"Y": 0.3627050220966339
},
{
"Type": "eyeRight",
"X": 0.6262026429176331,
"Y": 0.379489928483963
},
{
"Type": "mouthLeft",
"X": 0.40419745445251465,
"Y": 0.6104526519775391
},
{
"Type": "mouthRight",
"X": 0.5907381772994995,
"Y": 0.6247860193252563
},
{
"Type": "nose",
"X": 0.49532997608184814,
"Y": 0.48828810453414917
},
{
"Type": "leftEyeBrowLeft",
"X": 0.32399997115135193,
"Y": 0.3045051097869873
},
{
"Type": "leftEyeBrowRight",
"X": 0.38662829995155334,
"Y": 0.27300384640693665
},
{
"Type": "leftEyeBrowUp",
"X": 0.4492948651313782,
"Y": 0.2880849540233612
},
{
"Type": "rightEyeBrowLeft",
"X": 0.578127920627594,
"Y": 0.29742100834846497
},
{
"Type": "rightEyeBrowRight",
"X": 0.6459962725639343,
"Y": 0.29183030128479004
},
{
"Type": "rightEyeBrowUp",
"X": 0.7144292593002319,
"Y": 0.3330812454223633
},
{
"Type": "leftEyeLeft",
"X": 0.3629233241081238,
"Y": 0.3603385388851166
},
{
"Type": "leftEyeRight",
"X": 0.4457237124443054,
"Y": 0.36826738715171814
},
{
"Type": "leftEyeUp",
"X": 0.4013364613056183,
"Y": 0.3494759500026703
},
{
"Type": "leftEyeDown",
"X": 0.40179359912872314,
"Y": 0.37347349524497986
},
{
"Type": "rightEyeLeft",
"X": 0.5811655521392822,
"Y": 0.3783351182937622
},
{
"Type": "rightEyeRight",
"X": 0.6668664813041687,
"Y": 0.38298410177230835
},
{
"Type": "rightEyeUp",
"X": 0.6265660524368286,
"Y": 0.36624279618263245
},
{
"Type": "rightEyeDown",
"X": 0.6238686442375183,
"Y": 0.39007559418678284
},
{
"Type": "noseLeft",
"X": 0.4562915861606598,
"Y": 0.5203639268875122
},
{
"Type": "noseRight",
"X": 0.5394821166992188,
"Y": 0.5265129804611206
},
{
"Type": "mouthUp",
"X": 0.4932428300380707,
"Y": 0.5806143283843994
},
{
"Type": "mouthDown",
"X": 0.48947831988334656,
"Y": 0.6564671397209167
},
{
"Type": "leftPupil",
"X": 0.4020455777645111,
"Y": 0.3627050220966339
},
{
"Type": "rightPupil",
"X": 0.6262026429176331,
"Y": 0.379489928483963
},
{
"Type": "upperJawlineLeft",
"X": 0.28082960844039917,
"Y": 0.37847602367401123
},
{
"Type": "midJawlineLeft",
"X": 0.3077985942363739,
"Y": 0.6443988680839539
},
{
"Type": "chinBottom",
"X": 0.48529136180877686,
"Y": 0.7894702553749084
},
{
"Type": "midJawlineRight",
"X": 0.7061411738395691,
"Y": 0.6732134819030762
},
{
"Type": "upperJawlineRight",
"X": 0.77140212059021,
"Y": 0.4138971269130707
}
],
"Pose": {
"Roll": 3.0064163208007812,
"Yaw": -2.569990634918213,
"Pitch": 8.883845329284668
},
"Quality": {
"Brightness": 76.55046844482422,
"Sharpness": 94.08262634277344
},
"Confidence": 99.99818420410156
}
]
Node Js code for crop using gm ImageMagick library
const init = async () => {
try {
console.info("Process Started");
const size = await getImageSize("passport-photo.jpeg");
console.info("get Image Size: ", size);
const faceDetails = await getFaceDetailsFromImage();
// Uploded image width height
const imageWidth = size.width;
const imageHeight = size.height;
// Face detail width height
const faceDetailWidth = Math.round(faceDetails[0].BoundingBox.Width * imageWidth);
const faceDetailHeight = Math.round(faceDetails[0].BoundingBox.Height * imageHeight);
// Coordinates for the mouth
const faceDetailMouthLeft = faceDetails[0].Landmarks.filter(o => o.Type === "mouthLeft");
const faceDetailMouthRight = faceDetails[0].Landmarks.filter(o => o.Type === "mouthRight");
const faceDetailMouthUp = faceDetails[0].Landmarks.filter(o => o.Type === "mouthUp");
const faceDetailMouthDown = faceDetails[0].Landmarks.filter(o => o.Type === "mouthDown");
// Find x and y point from where the cropping needs to be started
const xPoint = Math.round(faceDetailMouthLeft[0].X * imageWidth);
const yPoint = Math.round(faceDetailMouthUp[0].Y * imageHeight);
// Width height for which image needs to be cut from start index
const width = ((faceDetailMouthRight[0].X - faceDetailMouthLeft[0].X) * imageWidth)
const height = ((faceDetailMouthDown[0].Y - faceDetailMouthUp[0].Y) * imageHeight)
console.log("xPoint:" + xPoint + ", yPoint:" + yPoint + ", faceDetailWidth:" + faceDetailWidth + ", faceDetailHeight:" + faceDetailHeight)
gm('passport-photo.jpeg')
// Invoke crop function
.crop(width, height, xPoint, yPoint, true)
// Process and Write the image
.write("crop5.png", function (err) {
console.error(err);
if (!err) console.log('done');
});
} catch (error){
console.error(error);
}
}
init();
original image
Your calculations for the mouth co-ordinates appear to be correct.
However, I see you are using:
.crop(width, height, xPoint, yPoint, true)
As you say, this "accepts the parameter as a percentage value", which probably isn't what you want.
var b = {
"vertices": [
[{ "x": 15, "y": 5 }, { "x": 28, "y": 2 }, { "x": 37, "y": 49 }, { "x": 24, "y": 51 }],
[{ "x": 106, "y": 5 }, { "x": 252, "y": 3 }, { "x": 252, "y": 36 }, { "x": 106, "y": 38 }],
[{ "x": 16, "y": 40 }, { "x": 296, "y": 41 }, { "x": 296, "y": 100 }, { "x": 16, "y": 99 }],
[{ "x": 26, "y": 123 }, { "x": 255, "y": 124 }, { "x": 255, "y": 239 }, { "x": 26, "y": 238 }],
[{ "x": 106, "y": 376 }, { "x": 255, "y": 375 }, { "x": 255, "y": 393 }, { "x": 106, "y": 394 }]]
};
Polygon draw function for drawing the above coordinates in canvas js:
function drawpolygon() {
for (i = 0; i < ar.vertices.length; i++) {
for (j = 0; j <= 3; j++) {
cx.beginPath();
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
cx.lineTo(ar.vertices[i][1].x, ar.vertices[i][1].y);
cx.lineTo(ar.vertices[i][2].x, ar.vertices[i][2].y);
cx.lineTo(ar.vertices[i][3].x, ar.vertices[i][3].y);
if (j == 3) {
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
}
cx.strokeStyle = "red";
cx.lineWidth = "1.5";
cx.stroke();
cx.closePath();
}
}
}
i have drawn the polygons using the canvas js. How to make these clickable? Hitregion is outdated..
You can leverage CanvasRenderingContext2D.isPointInPath(). It will allow you to determine if a given point is within either the "current" stateful path or if a point is in a Path2D object if you use those instead.
Try clicking within the rendered polygons below.
const canvas = document.getElementById("canvas");
const cx = canvas.getContext("2d");
var ar = {
"vertices": [
[{ "x": 15, "y": 5 }, { "x": 28, "y": 2 }, { "x": 37, "y": 49 }, { "x": 24, "y": 51 }],
[{ "x": 106, "y": 5 }, { "x": 252, "y": 3 }, { "x": 252, "y": 36 }, { "x": 106, "y": 38 }],
[{ "x": 16, "y": 40 }, { "x": 296, "y": 41 }, { "x": 296, "y": 100 }, { "x": 16, "y": 99 }],
[{ "x": 26, "y": 123 }, { "x": 255, "y": 124 }, { "x": 255, "y": 239 }, { "x": 26, "y": 238 }],
[{ "x": 106, "y": 376 }, { "x": 255, "y": 375 }, { "x": 255, "y": 393 }, { "x": 106, "y": 394 }]]
};
function drawpolygon(e) {
let x, y;
// Only try to hit detect if there was a click
if (e) {
// Localize the click to within the canvas
const {clientX, clientY, currentTarget} = e;
const {left, top} = currentTarget.getBoundingClientRect();
x = clientX - left;
y = clientY - top;
}
// Clear the canvas
cx.clearRect(0, 0, canvas.width, canvas.height);
// Iterate all the polygons
for (i = 0; i < ar.vertices.length; i++) {
for (j = 0; j <= 3; j++) {
cx.beginPath();
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
cx.lineTo(ar.vertices[i][1].x, ar.vertices[i][1].y);
cx.lineTo(ar.vertices[i][2].x, ar.vertices[i][2].y);
cx.lineTo(ar.vertices[i][3].x, ar.vertices[i][3].y);
if (j == 3) {
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
}
cx.closePath();
// Paint green if the click was in the path, red otherwise
cx.strokeStyle = cx.isPointInPath(x, y) ? "green" : "red";
cx.lineWidth = "1.5";
cx.stroke();
}
}
}
// Draw immediately for reference
drawpolygon();
// Draw again whenever we click
canvas.addEventListener("click", drawpolygon);
<canvas id="canvas" width="512" height="512"></canvas>
In a Json, there are multiple image sources as "src" : "image.png", , "src" : "image2.png",
For image.png , right now i am fetching X value as "40" [3rd position in below image]
For image2.png , right now i am fetching X value as "100" [6th position in below image]
Requirement :
Instead of that, i need to add 1st (10) + 3rd (40) + 4th (50) positions values and fetch final X value for "src" : "image.png", as 100 [10+40+50] and
"src" : "image1.png" = 1st (10) + 6th (100) + 7th (105) positions & final value of X is 215....
Codepen : https://codepen.io/kidsdial/pen/zbKaEJ
let jsonData = {
"layers" : [
{
"x" : 10,
"layers" : [
{
"x" : 20,
"y" : 30,
"name" : "L2a"
},
{
"x" : 40,
"layers" : [
{
"x" : 50,
"src" : "image.png",
"y" : 60,
"name" : "L2b-1"
},
{
"x" : 70,
"y" : 80,
"name" : "L2b-2"
}
],
"y" : 90,
"name" : "user_image_1"
},
{
"x" : 100,
"layers" : [
{
"x" : 105,
"src" : "image2.png",
"y" : 110,
"name" : "L2C-1"
},
{
"x" : 120,
"y" : 130,
"name" : "L2C-2"
}
],
"y" : 140,
"name" : "L2"
}
],
"y" : 150,
"name" : "L1"
}
]
};
function getData(data) {
var dataObj = {};
let layer1 = data.layers;
let layer2 = layer1[0].layers;
for (i = 1; i < layer2.length; i++) {
var x = layer2[i].x;
var src = layer2[i].layers[0].src;
document.write("src :" + src);
document.write("<br>");
document.write("x:" + x);
document.write("<br>");
}
}
getData(jsonData);
Using a recursive function you can find all the src and its corresponding summed x values.
Below is a crude example. Refactor as you see fit.
let jsonData = {
"layers" : [
{
"x" : 10,
"layers" : [
{
"x" : 20,
"y" : 30,
"name" : "L2a"
},
{
"x" : 40,
"layers" : [
{
"x" : 50,
"src" : "image.png",
"y" : 60,
"name" : "L2b-1"
},
{
"x" : 70,
"y" : 80,
"name" : "L2b-2"
}
],
"y" : 90,
"name" : "user_image_1"
},
{
"x" : 100,
"layers" : [
{
"x" : 105,
"src" : "image2.png",
"y" : 110,
"name" : "L2C-1"
},
{
"x" : 120,
"y" : 130,
"name" : "L2C-2"
}
],
"y" : 140,
"name" : "L2"
}
],
"y" : 150,
"name" : "L1"
}
]
};
function getAllSrc(layers){
let arr = [];
layers.forEach(layer => {
if(layer.src){
arr.push({src: layer.src, x: layer.x});
}
else if(layer.layers){
let newArr = getAllSrc(layer.layers);
if(newArr.length > 0){
newArr.forEach(({src, x}) =>{
arr.push({src, x: (layer.x + x)});
});
}
}
});
return arr;
}
function getData(data) {
let arr = getAllSrc(data.layers);
for (let {src, x} of arr){
document.write("src :" + src);
document.write("<br>");
document.write("x:" + x);
document.write("<br>");
}
}
getData(jsonData);
Here is the CodePen for the same: https://codepen.io/anon/pen/Wmpvre
Hope this helps :)
You can do that using recursion. While going though nested obj you could parent x value each item in layers and check if the element in layers have src property add the previous x value to it.
let jsonData = {
"layers" : [
{
"x" : 10,
"layers" : [
{
"x" : 20,
"y" : 30,
"name" : "L2a"
},
{
"x" : 40,
"layers" : [
{
"x" : 50,
"src" : "image.png",
"y" : 60,
"name" : "L2b-1"
},
{
"x" : 70,
"y" : 80,
"name" : "L2b-2"
}
],
"y" : 90,
"name" : "user_image_1"
},
{
"x" : 100,
"layers" : [
{
"x" : 105,
"src" : "image2.png",
"y" : 110,
"name" : "L2C-1"
},
{
"x" : 120,
"y" : 130,
"name" : "L2C-2"
}
],
"y" : 140,
"name" : "L2"
}
],
"y" : 150,
"name" : "L1"
}
]
};
function changeData(obj,x=0){
if(obj.src) obj.x += x;
if(obj.layers){
for(const item of obj.layers){
changeData(item,x+obj.x || 0);
}
}
}
changeData(jsonData);
function showData(obj){
if(obj.src) document.body.innerHTML += `src:${obj.src}<br>
x:${obj.x}<br>`;
if(obj.layers){
for(let i of obj.layers) showData(i)
}
}
showData(jsonData);
console.log(jsonData);
Here is my solution with recursion and mutation. You can cloneDeep the array before if you don't want to mutate it directly.
// Code
function recursion(obj, currentX = 0) {
if(obj.src) obj.x = currentX
else if(obj.layers) {
obj.layers.forEach(subObj => recursion(subObj, (currentX + subObj.x)))
}
}
// Data
let jsonData = {
"layers" : [
{
"x" : 10,
"layers" : [
{
"x" : 20,
"y" : 30,
"name" : "L2a"
},
{
"x" : 40,
"layers" : [
{
"x" : 50,
"src" : "image.png",
"y" : 60,
"name" : "L2b-1"
},
{
"x" : 70,
"y" : 80,
"name" : "L2b-2"
}
],
"y" : 90,
"name" : "user_image_1"
},
{
"x" : 100,
"layers" : [
{
"x" : 105,
"src" : "image2.png",
"y" : 110,
"name" : "L2C-1"
},
{
"x" : 120,
"y" : 130,
"name" : "L2C-2"
}
],
"y" : 140,
"name" : "L2"
}
],
"y" : 150,
"name" : "L1"
}
]
};
// Use
recursion(jsonData)
console.log(jsonData)
let jsonData = {
"layers": [{
"x": 10,
"layers": [{
"x": 20,
"y": 30,
"name": "L2a"
},
{
"x": 40,
"layers": [{
"x": 50,
"src": "image.png",
"y": 60,
"name": "L2b-1"
},
{
"x": 70,
"y": 80,
"name": "L2b-2"
}
],
"y": 90,
"name": "user_image_1"
},
{
"x": 100,
"layers": [{
"x": 105,
"src": "image2.png",
"y": 110,
"name": "L2C-1"
},
{
"x": 120,
"y": 130,
"name": "L2C-2"
}
],
"y": 140,
"name": "L2"
}
],
"y": 150,
"name": "L1"
}]
};
function getData(data) {
var dataObj = {};
let layer1 = data.layers;
let layer2 = layer1[0].layers;
let y = layer1[0].x;
for (i = 1; i < layer2.length; i++) {
var x = y;
x += layer2[i].x;
x += layer2[i].layers[0].x;
var src = layer2[i].layers[0].src;
document.write("src :" + src);
document.write("<br>");
document.write("x:" + x);
document.write("<br>");
}
}
getData(jsonData);
Here is My Solution. Check this out
let jsonData = {
"layers" : [
{
"x" : 10, //
"layers" : [
{
"x" : 20,
"y" : 30,
"name" : "L2a"
},
{
"x" : 40, //
"layers" : [
{
"x" : 50, //
"src" : "image.png",
"y" : 60,
"name" : "L2b-1"
},
{
"x" : 70,
"y" : 80,
"name" : "L2b-2"
}
],
"y" : 90,
"name" : "user_image_1"
},
{
"x" : 100,
"layers" : [
{
"x" : 105,
"src" : "image2.png",
"y" : 110,
"name" : "L2C-1"
},
{
"x" : 120,
"y" : 130,
"name" : "L2C-2"
}
],
"y" : 140,
"name" : "L2"
}
],
"y" : 150,
"name" : "L1"
}
]
};
var dataObj = [];
var x, src;
function getData(data) {
let layer1 = data.layers;
for(var i = 0; i < layer1.length; i++){
if(x === 0){
x = layer1[i].x;
continue;
}
x = layer1[i].x;
if(typeof layer1[i].layers !== 'undefined')
createOutput(layer1[i].layers);
}
return dataObj;
}
function createOutput(dataArray){
if(typeof dataArray === 'undefined'){
dataObj.push({x: x, src: src});
x = 0;
getData(jsonData);
return;
}
dataArray.forEach(element => {
if(typeof element.layers !== 'undefined' || typeof element.src !== 'undefined'){
x += element.x;
src = element.src;
createOutput(element.layers);
}
})
}
console.log(JSON.stringify(getData(jsonData)));
I am trying to update the existing json Object in the following way without using any functions in plain java script.This is asked in one of the interviews.
Attached is my Input file:
{
"height_c": 534,
"width_c": "800",
"height_h": 1067,
"width_h": "1600",
"height_k": 1366,
"width_k": "2048",
"height_l": "683",
"width_l": "1024",
"height_m": "333",
"width_m": "500",
"height_n": 213,
"width_n": "320",
"height_q": "150",
"width_q": "150",
"height_s": "160",
"width_s": "240",
"height_sq": 75,
"width_sq": 75,
"height_t": "67",
"width_t": "100",
"height_z": "427",
"width_z": "640"
}
Attached is my Expected file:
{
"sizes": {
"c": {
"width": 800,
"height": 534
},
"h": {
"width": 1600,
"height": 1067
},
"k": {
"width": 2048,
"height": 1366
},
"l": {
"width": 1024,
"height": 683
},
"m": {
"width": 500,
"height": 333
},
"n": {
"width": 320,
"height": 213
},
"q": {
"width": 150,
"height": 150
},
"s": {
"width": 240,
"height": 160
},
"q": {
"width": 75,
"height": 75
},
"t": {
"width": 100,
"height": 67
},
"z": {
"width": 640,
"height": 427
}
}
}
Any Help would be appreciated.I am looking for a starting point.
var input = {
"height_c": 534,
"width_c": "800",
"height_h": 1067,
"width_h": "1600",
"height_k": 1366,
"width_k": "2048",
"height_l": "683",
"width_l": "1024",
"height_m": "333",
"width_m": "500",
"height_n": 213,
"width_n": "320",
"height_q": "150",
"width_q": "150",
"height_s": "160",
"width_s": "240",
"height_sq": 75,
"width_sq": 75,
"height_t": "67",
"width_t": "100",
"height_z": "427",
"width_z": "640"
}
var output = {}
for (var key in input) {
var split = key.split('_')
if (!output[split[1]]) output[split[1]] = {};
output[split[1]][split[0]] = input[key];
}
document.body.appendChild(document.createTextNode(JSON.stringify({sizes: output}, null, 4)));
body { white-space: pre; font-family: monospace; }
Following is the script that I am trying to run when the class "skills" is clicked. It only works one time when clicked after that it won't run no matter how many times it's clicked
You can see it in action here: http://jsfiddle.net/tvEC5/
I want to modify it, add scroll functionality and make it only execute once when either clicked or scrolled, it should not execute after that.
Thank you.
var skillsClicked = false; // <---- Add this OUTSIDE of the click function
$('.skills').on('click', function () {
if (skillsClicked === true) return false; // <---- Then add this
skillsClicked = true; // <----- And the final update
var gaugeConfig = {
"canvasHolderId": "HTML",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#2ECC71",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "7.5"
};
var gaugeConfig1 = {
"canvasHolderId": "CSS",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#2ECC71",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "6.5"
};
var gaugeConfig2 = {
"canvasHolderId": "JS",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#27AE60",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "7"
};
var gaugeConfig3 = {
"canvasHolderId": "JQ",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#F1C40F",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "7"
};
var gaugeConfig4 = {
"canvasHolderId": "BT",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#F1C40F",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "8"
};
var gaugeConfig5 = {
"canvasHolderId": "XML",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#F39C12",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "7.5"
};
var gaugeConfig6 = {
"canvasHolderId": "JAVA",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#E67E22",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "9"
};
var gaugeConfig7 = {
"canvasHolderId": "MVC",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#E67E22",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "8.5"
};
var gaugeConfig8 = {
"canvasHolderId": "SP",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#D35400",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "6.5"
};
var gaugeConfig9 = {
"canvasHolderId": "WB",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#E74C3C",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "7"
};
var gaugeConfig10 = {
"canvasHolderId": "SQL",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#E74C3C",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "8"
};
var gaugeConfig11 = {
"canvasHolderId": "HB",
"width": "150",
"height": "150",
"circleColor": "#222",
"arcColor": "#C0392B",
"canvasFillColor": "#333",
"textPosition": "inside",
"skillLevel": "6.5"
};
function drawGauge(gc) {
var W = gc.width;
var H = gc.height;
var degrees = 0;
var new_degrees = 0;
var difference = 0;
var color = gc.arcColor;
var bgcolor = gc.circleColor;
var text = gc.skillLevel;
var animation_loop, redraw_loop;
var me = this;
var canvasHolder = document.getElementById(gc.canvasHolderId);
var canvasCreator = document.createElement("canvas");
canvasCreator.id = _randomId();
canvasCreator.width = gc.width;
canvasCreator.height = gc.height;
canvasHolder.appendChild(canvasCreator);
var canvas = document.getElementById(canvasCreator.id);
function _randomId() {
var d = new Date();
return "canvas" + d.getFullYear() + "" + d.getMonth() + "" + d.getDay() + "" + d.getHours() + "" + d.getSeconds() + "" + d.getMilliseconds() * Math.random();
}
function _init() {
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, W, H);
ctx.beginPath();
ctx.strokeStyle = bgcolor;
ctx.lineWidth = 15;
ctx.arc(W / 2, H / 2, 50, 0, Math.PI * 2, false); //you can see the arc now
ctx.stroke();
var radians = degrees * Math.PI / 180;
ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = 15;
ctx.arc(W / 2, H / 2, 50, 0 - 90 * Math.PI / 180, radians - 90 * Math.PI / 180, false);
ctx.stroke();
ctx.fillStyle = color;
ctx.font = "30px bebas";
text_width = ctx.measureText(text).width;
ctx.fillText(text, W / 2 - text_width / 2, H / 2 + 12);
}
function _animate_to() {
if (degrees == new_degrees) clearInterval(animation_loop);
if (degrees < new_degrees) degrees++;
else degrees--;
_init();
}
function _draw() {
if (typeof animation_loop !== 'undefined') clearInterval(animation_loop);
new_degrees = Math.round((text * 3600) / 100);
difference = new_degrees - degrees;
animation_loop = setInterval(function () {
_animate_to();
}, 1000 / difference);
}
_draw();
}
new drawGauge(gaugeConfig);
new drawGauge(gaugeConfig1);
new drawGauge(gaugeConfig2);
new drawGauge(gaugeConfig3);
new drawGauge(gaugeConfig4);
new drawGauge(gaugeConfig5);
new drawGauge(gaugeConfig6);
new drawGauge(gaugeConfig7);
new drawGauge(gaugeConfig8);
new drawGauge(gaugeConfig9);
new drawGauge(gaugeConfig10);
new drawGauge(gaugeConfig11);
});
Move your on-click code into a function, lets callit "function playGauge(evt)', then add it as handler to each event you want to triger it:
$('.skills).click(playGauge)
$('.skills).hover(playGauge)
//... etc.
Your explanation is really confusion. But I guess what you are trying to say is that the code is working correctly but you want the click to be changed with scroll.
You can copy the click and changed that
$('.skills').on('click', function () {
to this
$(window).scroll(function () {
If you are saying what I think you are saying, you want a single fire of the inner contents, but you want either scroll or click to do it.
var skillsClicked = false; // <---- Add this OUTSIDE of the click function
$('.skills').on('click scroll', function () {
if (skillsClicked === true) return false; // <---- Then add this
skillsClicked = true; // <----- And the final update
//rest of your code
});