I am trying to add size limits on image resize using KineticJS library. HTML5 Canvas Tutorial provides the method to resize the image: http://www.html5canvastutorials.com/labs/html5-canvas-drag-and-drop-resize-and-invert-images/
But I want the user not to be able to resize the image to less than 50px x 50px or greater than 200 x 200.
I have tried a lot manage the controls by following code. But it shows very strange results
dragBoundFunc: function(pos) {
var newX = '';
var image_width = group.get(".darthVaderImg")[0].getWidth();
var image_height = group.get(".darthVaderImg")[0].getHeight();
var image_position = group.get(".darthVaderImg")[0].getPosition();
if((image_width>50 && image_width< 200) ){
newX = pos.x;
}else{
newX = image_position.x+image_width+80;
}
if((image_height>50 && image_height< 200) ){
newY = pos.y;
}else{
newY = image_position.y+100;
}
return {
x: newX ,
y: newY,
};
}
Any example or idea that how I can do it
http://jsfiddle.net/e4uyG/4/ gets you pretty close to what you are asking for.
Basically, you have an update() function which redraws the images, so just limit it to a certain amount of resizing
function update(group, activeAnchor) {
var topLeft = group.get(".topLeft")[0];
var topRight = group.get(".topRight")[0];
var bottomRight = group.get(".bottomRight")[0];
var bottomLeft = group.get(".bottomLeft")[0];
var image = group.get(".image")[0];
// update anchor positions
switch (activeAnchor.getName()) {
case "topLeft":
topRight.attrs.y = activeAnchor.attrs.y;
bottomLeft.attrs.x = activeAnchor.attrs.x;
break;
case "topRight":
topLeft.attrs.y = activeAnchor.attrs.y;
bottomRight.attrs.x = activeAnchor.attrs.x;
break;
case "bottomRight":
bottomLeft.attrs.y = activeAnchor.attrs.y;
topRight.attrs.x = activeAnchor.attrs.x;
break;
case "bottomLeft":
bottomRight.attrs.y = activeAnchor.attrs.y;
topLeft.attrs.x = activeAnchor.attrs.x;
break;
}
image.setPosition(topLeft.attrs.x, topLeft.attrs.y);
var width = topRight.attrs.x - topLeft.attrs.x;
var height = bottomLeft.attrs.y - topLeft.attrs.y;
if(height > 50 && height < 200) // Limit the height
image.setHeight(height);
if(width > 50 && width < 200) // Limit the width
image.setWidth(width);
}
Related
Writing a pure JS tooltip library and have made it work really, really well. No big bells and whistles, just a super lightweight super utilitarian easy-to-customize tooltip. That said, I'm having an issue with updating the position; specifically when the tooltip is detected to be out of bounds.
And it works! It does. Issue is that when I'm hovered over the target element, which is against the right side of the page which causes the tooltip to be out of bounds, it will flicker between the default bottom-right position and the correct bottom-left position. Upon further inspection, it seems to only register out of bounds on every other hair I move the cursor. For instance, when I enter the element, it will display properly; move the cursor a hair in any direction and it will seemingly reset to bottom-right, not seeing that it's out of bounds. Move it one hair further and it will figure out it's out of bounds again, correcting itself to bottom-left. I'm not sure what assumptions to make here, but I'll let you guys be the judge of it.
updateTooltip(event) {
const mouseX = event.pageX,
mouseY = event.pageY;
const adjustment = 15;
let position = (this.element.getAttribute(this.selector + '-pos') || '').split(' ');
if (position.length !== 2) position = [ 'bottom', 'right' ];
var isOut = this.checkBounds();
if (isOut.top) { position[0] = 'bottom'; }
if (isOut.left) { position[1] = 'right'; }
if (isOut.bottom) { position[0] = 'top'; }
if (isOut.right) { position[1] = 'left'; }
let vertical, horizontal;
switch (position[0]) {
case 'top':
vertical = -adjustment - this.tooltip.offsetHeight;
break;
case 'center':
vertical = 0 - (this.tooltip.offsetHeight / 2);
break;
default:
vertical = adjustment;
}
switch (position[1]) {
case 'left':
horizontal = -adjustment - this.tooltip.offsetWidth;
break;
case 'center':
horizontal = 0 - (this.tooltip.offsetWidth / 2);
break;
default:
horizontal = adjustment;
}
this.tooltip.style.top = mouseY + vertical + 'px';
this.tooltip.style.left = mouseX + horizontal + 'px';
}
checkBounds() {
if (!this.tooltip) return;
const bounds = this.tooltip.getBoundingClientRect();
let out = {};
out.top = bounds.top < 0;
out.left = bounds.left < 0;
out.bottom = bounds.bottom > (window.innerHeight || document.documentElement.clientHeight);
out.right = bounds.right > (window.innerWidth || document.documentElement.clientWidth);
out.any = out.top || out.left || out.bottom || out.right;
out.all = out.top && out.left && out.bottom && out.right;
return out;
}
I have an Angular application that loads multiple images on to the page at random locations by utilizing the following code:
HTML:
<div ng-repeat="s in selectedImages" class="container">
<img ng-src="{{s.img}}" class="sImage" ng-style="s.pos"/>
</div>
CSS:
.wordImage {
position:absolute;
width:100px;
}
JS Controller:
function loadImages() {
$scope.myImages = ['img1.png', 'img2.png', 'img3.png', 'img4.png', 'img5.png']
$scope.selectedImages = [];
for (i in $scope.myImages) {
$scope.selectedImages.push(addRandomLocationToImage($scope.myImages[i]));
}
}
function addRandomLocationToImage(image) {
image.pos = {};
var preTop = getRandomHeight(); // get Height for this image
var preLeft = getRandomWidth(); // get Width for this image
image.pos = {top:preTop,
left:preLeft};
return image; // returns the same image object but contains pos{} for ng-style
}
function getRandomHeight() {
var imgHeight = 100;
var winHeight = $(window).height();
var randomH = Math.random() * (winHeight - 100); // subtract 100 for the header. and also footer padding
if (randomH < 150) {
randomH += 150; // add to keep it out of the header
}
if(winHeight - randomH < 100) { // if image will be on bottom edge of page
randomW -= imgHeight; // subtract 100 because that is the height of the images, this will prevent them from being partially off the page
}
return randomH;
}
function getRandomWidth() {
var imgWidth = 100;
var winWidth = $(window).width();
var randomW = Math.random() * winWidth;
if (randomW < 0) { // make sure it is not less than zero, then assign new number until it is greater than zero
while (randomW < 0) {
randomW = Math.random() * winWidth;
}
}
if (winWidth - randomW < 100) { // if image will be on right edge of page
randomW -= imgWidth; // subtract 100 because that is the width of the images, this will prevent them from being partially off the page
}
return randomW;
}
loadImages();
This definitely generates random images on a page...but they overlap very easily. My question is, how can I prevent them from overlapping? Here is some code that I have been working on.
var newLeft = currentImage.pos.left;
var newTop = currentImage.pos.top;
for (i in $scope.selectedImages) {
var originalLeft = $scope.selectedImages[i].pos.left;
var originalTop = $scope.selectedImages[i].pos.top;
if ((originalLeft - newLeft < 100 && originalLeft - newLeft > -100) && // could overlap horizontally
(originalTop - newTop < 100 && originalTop - newTop > -100)) { // could overlap vertically
//do something to select a new random location.
}
}
Basically you have to check a image position with every other image. You can use Array.some for this:
Considering that you store the image position in the image object as
x and y properties
function checkCollision(testImage) {
return $scope.myImages.some(function(img) {
if (img == testImage)
return false;
if (!img.x || !img.y) // Image has no position yet
return false;
return
testImage.x < img.x + imgWidth &&
testImage.x + imgWidth > img.x &&
testImage.y < img.y + imgHeight &&
testImage.y + imgHeight > img.y;
});
}
You have to be aware that depending of the available space and image sizes there might be a situation where is not possible to find a suitable position for a image.
I made a functional example.
I'm trying my hands at some simple game programming in Javascript and have come to realize I need to change the way I handle sprites. The only question is, "how"?
I have a hero that moves around with the arrow keys and fires laser rays with WASD. This is how I define rays:
function Ray (x, y, width, height, direction, index) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.direction = direction;
this.index = index;
this.speed = 512;
this.disabled = false;
}
The index just indicates where in an array of rays (heh) it is being stored. I currently have a hard-coded limit of 5 simultaneous rays, although the other restrictions (screen size, ray size, speed, hero size etc) shouldn't allow for more than 4:
var rays = [];
var numberOfRays = 0;
var rayLimit = 5;
var shotClock = 300;
And so, in the update() function that gets called by the game loop, I have listeners for the WASD keys. They look like this:
// D
if (68 in keysDown && numberOfRays <= rayLimit && Date.now() - lastShootTime > shotClock) {
lastShootTime = Date.now();
var newRayIndex = findFreeRay();
rays[newRayIndex] = new Ray(hero.x + hero.width + 12, hero.y + hero.height / 2, rayImage.width, rayImage.height, 'right', newRayIndex);
numberOfRays++;
}
(findFreeRay() just returns the lowest unused or disabled (off the screen) index in rays[])
Earlier in the update() method (I have also tried putting it later) I have the logic for updating ray movement:
rays.forEach(function(ray) {
if (ray != null && !ray.disabled) {
switch(ray.direction) {
case 'right':
ray.x += ray.speed * modifier;
break;
case 'left':
ray.x -= ray.speed * modifier;
break;
case 'up':
ray.y -= ray.speed * modifier;
break;
case 'down':
ray.y += ray.speed * modifier;
break;
}
}
});
Finally, there is the image for the ray (actually, one for horizontal rays and another one for vertical rays). Currently, I am using one Image object of each globally, that the existing rays share. But I have also tried, without much luck, to create individual image objects for every ray.
// Ray images
var rayReady = false;
var rayImage = new Image();
rayImage.onload = function() {
rayReady = true;
};
rayImage.src = "images/ray.png";
var rayVertReady = false;
var rayVertImage = new Image();
rayVertImage.onload = function() {
rayVertReady = true;
};
rayVertImage.src = "images/ray_vert.png";
And here is how they get drawn:
if (rayReady && rayVertReady && numberOfRays > 0) {
rays.forEach(function(ray) {
if (ray.x > canvas.width
|| ray.x + ray.width < 0
|| ray.y > canvas.height
|| ray.y + ray.height < 0) {
numberOfRays--;
ray.disabled = true;
}
else if (ray.direction == 'right' || ray.direction == 'left'){
ctx.drawImage(rayImage, ray.x, ray.y);
}
else {
ctx.drawImage(rayVertImage, ray.x, ray.y);
}
});
}
The problem
After shooting only a few rays, new ones start to either flicker and disappear, or stay invisible altogether. They actually exist as gameplay objects though, as they can hit targets.
What likely causes this flickering?
(credit to Matt Hackett for the base of this code)
fiddle: http://jsfiddle.net/Vr3MW/
I'm writing a simple game in javascript and I'm wondering what the best way to handle collisions between the player and the world objects.
<script>
var isJumping = false;
var isFalling = false;
var w = 1;
var recwidth = 400;
var recheight = 400;
var xpos = 50;
var ypos = 279;
window.onload = function() {
var FPS = 30;
var ground = new myObject();
setInterval(function() {
clear();
draw();
ground.draw(0, 325);
ground.draw(125,325)
}, 1000/FPS);
};
function myObject(){
this.draw = function drawground(groundx, groundy){
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d');
//context.fillRect(xpos,ypos,100,100);
var img=new Image()
img.src="ground.png"
img.onload = function() {
context.drawImage(img,groundx,groundy)}
}
};
function jump()
{
var t=.1;
isJumping=true;
var jumpint= setInterval(function() {
yup = 12*t-(5*t*t);
ypos= ypos - yup;
t = t + .1
if(yup < 0)
{
isJumping = false;
isFalling = true;
clearInterval(jumpint);
jumpint = 0;
fall();
return;
}
}, 20);
}
function fall()
{
t=.10
var fallint= setInterval(function() {
ydown = (5*t*t);
ypos= ypos + ydown;
t = t + .1
if(ypos > 275)
{
isFalling == false;
clearInterval(fallint);
fallint = 0;
return;
}
}, 20);
}
function changex(x){
xpos = xpos + (x);
//clear();
//draw();
}
function changey(y){
ypos = ypos + (y);
//clear();
//draw();
}
function draw(){
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d');
var img=new Image()
img.src="character.png"
img.onload = function() {
context.drawImage(img,xpos,ypos)}
}
function clear(){
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d');
context.clearRect(0,0, canvas.width, canvas.height);
}
document.onkeydown = function(event) {
var keyCode;
if(event == null)
{
keyCode = window.event.keyCode;
}
else
{
keyCode = event.keyCode;
}
switch(keyCode)
{
// left
case 37:
//left
changex(-5);
break;
// up
case 38:
// action when pressing up key
jump();
break;
// right
case 39:
// action when pressing right key
changex(5);
break;
// down
case 40:
// action when pressing down key
changey(5);
break;
default:
break;
}
}
</script>
So, as you can see I'm creating two objects so far, and the player stops falling at any arbitrary point. I feel collisions at this stage wont be too difficult, but once I start adding more I feel it's going to get more difficult. I'm not going to be using the instance of the object with the same image for each instance of the object, so at some point I'm going to change the myobject function to be able to accept the image as a parameter, and then checking for collisions will be a bit more tricky. I also plan on making this into a side scroller, so once one end the map is hit it changes into the next area, which is going to cause performance issues. If I'm checking for collisions on every single object in the entire game every interval I imagine things are going to get slow. What is going to be the best way to limit the number of collisions checked? Obviously, if the object isn't on screen there is no need to check it, but is there a way to limit that. I'm thinking of making an array for every frame of the game, and filling that array with it's objects. Then, only check the array the of the frame the player is currently in. Is this feasible or still going to cause too many issues? Any help is greatly appreciated.
If you want pixel perfect collisions, I have some plain javascript code that worked for me with canvas2d rendering context.
function collide(sprite, sprite2, minOpacity=1) {
// Rectangular bounding box collision
if (sprite.x < sprite2.x + sprite2.width && sprite.x + sprite.width > sprite2.x && sprite.y < sprite2.y + sprite2.height && sprite.y + sprite.height > sprite2.y) {
// Finds the x and width of the overlapping area
var overlapX = (this.rect.x > other.rect.x) ? [this.rect.x, (other.rect.x + other.rect.width) - this.rect.x + 1] : [other.rect.x, (this.rect.x + this.rect.width) - other.rect.x + 1];
// Finds the y and height of the overlapping area
var overlapY = (this.rect.y + this.rect.height > other.rect.y + other.rect.height) ? [this.rect.y, (other.rect.y + other.rect.height) - this.rect.y + 1] : [other.rect.y, (this.rect.y + this.rect.height) - other.rect.y + 1];
// Creates a canvas to draw sprite.image to
var spriteImageCanvas = new OffscreenCanvas(overlapX[0] + overlapX[1], overlapY[0] + overlapY[1]);
var spriteImageCanvasContext = spriteImageCanvas.getContext("2d");
// Draws sprite.image to spriteImageCanvasContext
spriteImageCanvasContext.drawImage(this.image, sprite.x, sprite.y, sprite.width, sprite.height);
// Creates a canvas to draw sprite2.image to
var sprite2ImageCanvas = new OffscreenCanvas(overlapX[0] + overlapX[1], overlapY[0] + overlapY[1]);
var sprite2ImageCanvasContext = otherImageCanvas.getContext("2d");
// Draws sprite2.image to sprite2ImageCanvasContext
sprite2ImageCanvasContext.drawImage(sprite2.image, sprite2.x, sprite2.y, sprite2.width, sprite2.height);
// Loops through the x coordinates in the overlapping area
for (var x = overlapX[0]; x <= overlapX[0] + overlapX[1]; x++) {
// Loops through the y coordinates in the overlapping area
for (var y = overlapY[0]; y <= overlapY[0] + overlapY[1]; y++) {
if (/* Checks if the pixel at [x, y] in the sprite image has an opacity over minOpacity input */ thisImageCanvasContext.getImageData(x, y, 1, 1).data[3] >= minOpacity && /* Checks if the pixel at [x, y] in the sprite2 image has an opacity over minOpacity input */ otherImageCanvasContext.getImageData(x, y, 1, 1).data[3] >= minOpacity) {
return true;
};
};
};
};
}
Or if you just want rectangular collision, use the first if statement in the function.
i have an image with 8 anchor points. Thanks to an example, i've managed to get those on the 4 corners to only scale the picture. But i am having difficulty in making the other 4 to stretch the image ONLY.
The midTop & midBottom anchors shall stretch vertically; the midLeft and midRight anchors shall stretch horizontally. I think it might concern the bounds those anchors can move but i don't know how to proceed.
http://jsfiddle.net/Dppm7/3/ (sorry can't get this to work in jsFiddle)..
The output looks like this.
Please if anyone can help. :)
Some code for the anchors (not all codes for the middle anchors have been implemented):
// Update the positions of handles during drag.
// This needs to happen so the dimension calculation can use the
// handle positions to determine the new width/height.
switch (activeHandleName) {
case "topLeft":
topRight.setY(activeHandle.getY());
midRight.setY(activeHandle.getY());
midTop.setY(activeHandle.getY());
bottomLeft.setX(activeHandle.getX());
midLeft.setX(activeHandle.getX());
midBottom.setX(activeHandle.getX());
break;
case "topRight":
topLeft.setY(activeHandle.getY());
midLeft.setY(activeHandle.getY());
midTop.setY(activeHandle.getY());
bottomRight.setX(activeHandle.getX());
midBottom.setX(activeHandle.getX());
midRight.setX(activeHandle.getX());
break;
case "bottomRight":
bottomLeft.setY(activeHandle.getY());
midBottom.setY(activeHandle.getY());
midLeft.setY(activeHandle.getY());
topRight.setX(activeHandle.getX());
midTop.setX(activeHandle.getX());
midRight.setX(activeHandle.getX());
break;
case "bottomLeft":
bottomRight.setY(activeHandle.getY());
midBottom.setY(activeHandle.getY());
midRight.setY(activeHandle.getY());
topLeft.setX(activeHandle.getX());
midTop.setX(activeHandle.getX());
midLeft.setX(activeHandle.getX());
break;
case "midTop":
topRight.setY(activeHandle.getY());
topLeft.setY(activeHandle.getY());
midRight.setY(activeHandle.getY());
midLeft.setY(activeHandle.getY());
break;
case "midBottom":
bottomRight.setY(activeHandle.getY());
bottomLeft.setY(activeHandle.getY());
midRight.setY(activeHandle.getY());
midLeft.setY(activeHandle.getY());
break;
case "midRight":
topRight.setX(activeHandle.getX());
bottomRight.setX(activeHandle.getX());
midTop.setX(activeHandle.getX());
midBottom.setX(activeHandle.getX());
break;
case "midLeft":
topLeft.setX(activeHandle.getX());
bottomLeft.setX(activeHandle.getX());
midTop.setX(activeHandle.getX());
midBottom.setX(activeHandle.getX());
break;
}
// Calculate new dimensions. Height is simply the dy of the handles.
// Width is increased/decreased by a factor of how much the height changed.
newHeight = bottomLeft.getY() - topLeft.getY();
newWidth = image.getWidth() * newHeight / image.getHeight();
// Move the image to adjust for the new dimensions.
// The position calculation changes depending on where it is anchored.
// ie. When dragging on the right, it is anchored to the top left,
// when dragging on the left, it is anchored to the top right.
if (activeHandleName === "topRight" || activeHandleName === "bottomRight") {
image.setPosition(topLeft.getX(), topLeft.getY());
} else if (activeHandleName === "topLeft" || activeHandleName === "bottomLeft") {
image.setPosition(topRight.getX() - newWidth, topRight.getY());
}
imageX = image.getX();
imageY = image.getY();
// Update handle positions to reflect new image dimensions
topLeft.setPosition(imageX, imageY);
topRight.setPosition(imageX + newWidth, imageY);
bottomRight.setPosition(imageX + newWidth, imageY + newHeight);
bottomLeft.setPosition(imageX, imageY + newHeight);
midTop.setPosition(imageX + image.getWidth() / 2, imageY);
midBottom.setPosition(imageX + image.getWidth() / 2, imageY + newHeight);
midRight.setPosition(imageX + image.getWidth(), imageY + image.getHeight() / 2);
midLeft.setPosition(imageX, imageY + image.getHeight() / 2);
// Set the image's size to the newly calculated dimensions
if (newWidth && newHeight) {
image.setSize(newWidth, newHeight);
}
}
<script>
var imWidth;
var imHeight;
var topRight;
var topLeft;
var bottomLeft;
var width;
var height;
var group;
var bottomRight;
var image;
var aspectRatio;
var oldwidth;
var oldheight;
var oldtopleftX;
var oldtopleftY;
var shrinkLimitBound;
function update(activeAnchor) {
group = activeAnchor.getParent();
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
actRatio=imWidth/imHeight;
shrinkLimitBound=100;
height=bottomLeft.getY() - topLeft.getY();
width=topRight.getX() - topLeft.getX();
newRatio=(width)/(height);
width=actRatio*height;
switch (activeAnchor.getName()) {
case 'topLeft':
if(height<shrinkLimitBound)
{
height=shrinkLimitBound;
width=actRatio*height;;
topRight.setY(bottomRight.getY()-height);
}
else
{
if(anchorY < bottomRight.getY())
topRight.setY(anchorY);
else
topRight.setY(bottomRight.getY()-height);
}
topRight.setX(bottomRight.getX());
bottomLeft.setX(bottomRight.getX()-width);
bottomLeft.setY(bottomRight.getY());
topLeft.setX(bottomRight.getX()-width);
topLeft.setY(bottomRight.getY()-height);
break;
case 'topRight':
if(height<shrinkLimitBound)
{
height=shrinkLimitBound;
width=actRatio*height;;
topLeft.setY(bottomLeft.getY()-height);
}
else
{
if(anchorY < bottomLeft.getY()-shrinkLimitBound)
{
topLeft.setY(anchorY)
}
else
{
topLeft.setY(bottomLeft.getY()-height);
}
}
topLeft.setX(bottomLeft.getX());
bottomRight.setX(bottomLeft.getX()+width);
bottomRight.setY(bottomLeft.getY());
topRight.setX(bottomLeft.getX()+width);
topRight.setY(bottomLeft.getY()-height);
break;
case 'bottomRight':
if(height<shrinkLimitBound)
{
height=shrinkLimitBound;
width=actRatio*height;;
bottomLeft.setY(topLeft.getY()+height);
}
else
{
if(anchorY > topLeft.getY()+shrinkLimitBound)
{
bottomLeft.setY(anchorY);
}
else
bottomLeft.setY(topLeft.getY()+height);
}
bottomLeft.setX(topLeft.getX());
topRight.setX(topLeft.getX()+width);
topRight.setY(topLeft.getY());
bottomRight.setX(topLeft.getX()+width);
bottomRight.setY(topLeft.getY()+height);
break;
case 'bottomLeft':
if(height<shrinkLimitBound)
{
height=shrinkLimitBound;
width=actRatio*height;;
bottomRight.setY(topRight.getY()+height);
}
else
{
if(anchorY > topRight.getY())
bottomRight.setY(anchorY);
else
bottomRight.setY(topRight.getY()+height);
}
bottomRight.setX(topRight.getX());
topLeft.setX(topRight.getX()-width);
topLeft.setY(topRight.getY());
bottomLeft.setX(topRight.getX()-width);
bottomLeft.setY(topLeft.getY()+height);
break;
}
image.setPosition(topLeft.getPosition());
if(width>0 && height>0)
{
image.setSize(width,height);
}
oldwidth=width;
oldheight=height;
oldtopleftX=topLeft.getX();
oldtopleftY=topLeft.getY();
}
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 0,
radius: 4,
name: name,
draggable: true,
dragOnTop: false
});
anchor.on('dragmove', function() {
update(this);
layer.draw();
});
anchor.on('mousedown touchstart', function() {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function() {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function() {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function() {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function initStage(images) {
var conWidth = 578; //container Width.
var conHeight = 400; //container Heitgh.
imWidth = images.dressTrailImage.width;
imHeight = images.dressTrailImage.height;
if (imWidth > conWidth)
{
imHeight = (imHeight/imWidth)*conWidth;
imWidth = conWidth;
}
if (imHeight > conHeight)
{
imWidth = (imWidth/imHeight)*conHeight;
imHeight = conHeight;
}
if ((imHeight < conHeight) && (imWidth < conWidth))
{
var diffX = conWidth - imWidth;
var diffY = conHeight - imHeight;
var diffY2 = (imHeight/imWidth)*diffX;
if (diffY2 > diffY)
{
imWidth = (imWidth/imHeight)*conHeight;
imHeight = conHeight;
}
else
{
imHeight = (imHeight/imWidth)*conWidth;
imWidth = conWidth;
}
}
images.UsrTrail.width = imWidth;
images.UsrTrail.height = imHeight;
var stage = new Kinetic.Stage({
container: 'container',
width: imWidth,
height: imHeight
});
var dressTrailImageGroup = new Kinetic.Group({
x: 0,
y: 0,
draggable: true,
//dragBoundFunc: function(pos) {
// console.log(pos);
// // var newX;
// // var newY;
// console.log(topLeft.x+","+bottomRight.y);
// x1=topLeft.x;
// x2=bottomRight.x;
// y1=topLeft.y;
// y2=bottomRight.y;
// x=pos.x;
// y=pos.y;
// var calsign = ((x-x1)*(y-y2))-((y-y1)*(x-x2))
// if (calsign < 0){
// return {
// x : pos.x,
// y : pos.y
// }
// }else {
// return {
// x : 50,
// y : 50
// }
// }
//}
// if (pos.x < ){
// newX=10;
// }
// else if ((pos.x+dressTrailImage.getWidth()) > stage.getWidth()-50){
// newX = stage.getWidth()-dressTrailImage.getWidth()-50;
// }
// else{
// newX = pos.x;
// };
// if(pos.y < 10){
// newY = 10;
// }
// else if((pos.y + dressTrailImage.getHeight()) > stage.getHeight()-50){
// newY = stage.getHeight()-dressTrailImage.getHeight()-50;
// }
// else {
// newY = pos.y;
// }
//console.log("newX:"+newX+", newY:"+newY);
// return {
// x : newX,
// y : newY,
// };
//}
});
// UsrTrail
var UsrTrailImg = new Kinetic.Image({
x: 0,
y: 0,
image: images.UsrTrail,
width: images.UsrTrail.width,
height: images.UsrTrail.height,
name: 'image'
});
var layer = new Kinetic.Layer();
/*
* go ahead and add the groups
* to the layer and the layer to the
* stage so that the groups have knowledge
* of its layer and stage
*/
layer.add(dressTrailImageGroup);
layer.add(UsrTrailImg);
stage.add(layer);
UsrTrailImg.moveToBottom();
intialAspRatio = images.dressTrailImage.width/images.dressTrailImage.height;
console.log("aspectRatio is :"+intialAspRatio);
// dress Trail Image
var inith=200; //set this to the desired height of the dress that shows up initially
var initw=intialAspRatio*inith;
var neck_user_x=50;//from backend
var neck_user_y=20;//from backend
var neck_dress_x=50;//from backend
var neck_dress_y=5;//from backend
//for getting the actual width and height of the User's Image
var UsrImgObjActual= new Image();
UsrImgObjActual.src=sources.UsrTrail;
UsrimgWidth=UsrImgObjActual.width;
UsrimgHeight=UsrImgObjActual.height;
//////////////////////////////////////////
// var UsrimgWidth= 180;
// var UsrimgHeight=270;
console.log("height Should Be 270 and is:"+UsrimgHeight);
console.log("Width Should Be 180 and is:"+UsrimgWidth);
var dressimgWidth=initw;
var dressimgHeight=inith;
console.log("usertrail image width adn height"+images.UsrTrail.width+"::"+images.UsrTrail.height);
console.log("neck user and dress resp"+neck_user_x+","+neck_user_y+','+neck_dress_x+','+neck_dress_y);
var x_draw=((neck_user_x*UsrimgWidth)-(neck_dress_x*dressimgWidth));
var y_draw=((neck_user_y*UsrimgHeight)-(neck_dress_y*dressimgHeight));
x_draw=x_draw/100;
y_draw=y_draw/100;
console.log("xdraw and ydraw:"+x_draw+','+y_draw);
//top left corner coordinates of the dress image.
var initx=x_draw;
var inity=y_draw;
var dressTrailImage = new Kinetic.Image({
x: initx,
y: inity,
image: images.dressTrailImage,
name: 'image',
width: initw,// images.dressTrailImage.width,
height: inith //images.dressTrailImage.height
});
// dressTrailImage.width = 50;
// dressTrailImage.height = dressTrailImage.width / intialAspRatio;
// console.log(dressTrailImage.height);
dressTrailImageGroup.add(dressTrailImage);
addAnchor(dressTrailImageGroup, initx , inity, 'topLeft');
addAnchor(dressTrailImageGroup, initx + initw , inity , 'topRight');
addAnchor(dressTrailImageGroup, initx + initw , inity + inith, 'bottomRight');
addAnchor(dressTrailImageGroup, initx , inity + inith, 'bottomLeft');
topLeft = dressTrailImageGroup.get('.topLeft')[0];
topRight = dressTrailImageGroup.get('.topRight')[0];
bottomRight = dressTrailImageGroup.get('.bottomRight')[0];
bottomLeft = dressTrailImageGroup.get('.bottomLeft')[0];
image = dressTrailImageGroup.get('.image')[0];
dressTrailImageGroup.on('dragstart', function() {
this.moveToTop();
});
stage.draw();
}
var sources = {
dressTrailImage: "http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg",
UsrTrail: "http://www.html5canvastutorials.com/demos/assets/yoda.jpg"
};
loadImages(sources, initStage);
//function called on clicking the submit button.
function Sunmit_fn(){
//neck positions of the trail dress in percentages (assumed for now!).
neckDressX=50;//in percentage.
neckDressY=5;//in percentage.
//height and width of the user image used in the canvas.
//original here here is refered to the height and width used in the canavs
var originalUserImgWidth = imWidth;
var originalUserImgHeight = imHeight;
var trailDressWidth = image.getWidth();//Final Image Width
var trailDressHeight = image.getHeight();//Final Image Height
imageX=topLeft.getParent().getX()+topLeft.getX()+1;//upper right anchor X Position
imageY=topLeft.getParent().getY()+topLeft.getY()+1;//upper right anchor Y Position
//formula for calculating the final neck positions of the resized and dragged dress
//with respect to the user image in percentages
neckFinalX=(imageX+(trailDressWidth*(neckDressX/100)))/originalUserImgWidth;
neckFinalY=(imageY+(trailDressHeight*(neckDressY/100)))/originalUserImgHeight;
//neck in percentages trail pic neck x,y.
neckFinalX=neckFinalX*100;
neckFinalY=neckFinalY*100;
//Just for testing.
console.log("neck position updated by User:");
console.log("X:"+neckFinalX+", Y:"+neckFinalY+")");
console.log("Resized Size of the dress is:");
console.log("Width:"+trailDressWidth+", Height:"+trailDressHeight);
}
</script>
This Script resizes only along one axis for four points.You can figure out the same for all the points