0

I need help only having the anchors for rotating. Right now there is five anchors and I don't know how to get rid of all of them except the rotate one. I would also only like the anchors to show when the user hovers over the image

Here is my code

<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<body onmousedown="return false;">
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js">     
</script>
<script>

function update(activeAnchor) {
var group = activeAnchor.getParent();

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 rotateAnchor = group.get('.rotateAnchor')[0];
var image = group.get('Image')[0];

var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
var imageWidth = image.getWidth();
var imageHeight = image.getHeight();

var offsetX = Math.abs((topLeft.getX() + bottomRight.getX() + 10) / 2);
var offsetY = Math.abs((topLeft.getY() + bottomRight.getY() + 10) / 2);

// update anchor positions
switch (activeAnchor.getName()) {
    case 'rotateAnchor':
        group.setOffset(offsetX, offsetY);
        break;
    case 'topLeft':
        topRight.setY(anchorY);
        bottomLeft.setX(anchorX);
        break;
    case 'topRight':
        topLeft.setY(anchorY);
        bottomRight.setX(anchorX);
        break;
    case 'bottomRight':
        topRight.setX(anchorX);
        bottomLeft.setY(anchorY);
        break;
    case 'bottomLeft':
        topLeft.setX(anchorX);
        bottomRight.setY(anchorY);
        break;
}
rotateAnchor.setX(topRight.getX() + 5);
rotateAnchor.setY(topRight.getY() + 20);

image.setPosition((topLeft.getPosition().x + 20), (topLeft.getPosition().y + 20));
var width = topRight.getX() - topLeft.getX() - 30;
var height = bottomLeft.getY() - topLeft.getY() - 30;
if (width && height) {
    image.setSize(width, height);
}
}
function addAnchor(group, x, y, name, dragBound) {
var stage = group.getStage();
var layer = group.getLayer();

var anchor = new Kinetic.Circle({
                                x: x,
                                y: y,
                                stroke: '#666',
                                fill: '#ddd',
                                strokeWidth: 2,
                                radius: 8,
                                name: name,
                                draggable: true,
                                dragOnTop: false
                                });

if (dragBound == 'rotate') {
    anchor.setAttrs({
                    dragBoundFunc: function (pos) {
                    return getRotatingAnchorBounds(pos, group);
                    }
                    });
}

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 getRotatingAnchorBounds(pos, group) {
var topLeft = group.get('.topLeft')[0];
var bottomRight = group.get('.bottomRight')[0];
var topRight = group.get('.topRight')[0];

var absCenterX = Math.abs((topLeft.getAbsolutePosition().x + 5 +     bottomRight.getAbsolutePosition().x + 5) / 2);
var absCenterY = Math.abs((topLeft.getAbsolutePosition().y + 5 + bottomRight.getAbsolutePosition().y + 5) / 2);

var relCenterX = Math.abs((topLeft.getX() + bottomRight.getX()) / 2);
var relCenterY = Math.abs((topLeft.getY() + bottomRight.getY()) / 2);

var radius = distance(relCenterX, relCenterY, topRight.getX() + 5, topRight.getY() + 20);

var scale = radius / distance(pos.x, pos.y, absCenterX, absCenterY);

var realRotation = Math.round(degrees(angle(relCenterX, relCenterY, topRight.getX() + 5, topRight.getY() + 20)));
var rotation = Math.round(degrees(angle(absCenterX, absCenterY, pos.x, pos.y)));
rotation -= realRotation;

group.setRotationDeg(rotation);

return {
y: Math.round((pos.y - absCenterY) * scale + absCenterY),
x: Math.round((pos.x - absCenterX) * scale + absCenterX)
};
}
function radians(degrees) { return degrees * (Math.PI / 180); }
function degrees(radians) { return radians * (180 / Math.PI); }

// Calculate the angle between two points.
function angle(cx, cy, px, py) {
var x = cx - px;
var y = cy - py;
return Math.atan2(-y, -x);
}

// Calculate the distance between two points.
function distance(p1x, p1y, p2x, p2y) {
return Math.sqrt(Math.pow((p2x - p1x), 2) + Math.pow((p2y - p1y), 2));
}

function initStage(images) {
var stage = new Kinetic.Stage({
                              container: 'container',
                              width: 578,
                              height: 400
                              });
var darthVaderGroup = new Kinetic.Group({
                                        x: 270,
                                        y: 100,
                                        draggable: true
                                        });
var yodaGroup = new Kinetic.Group({
                                  x: 100,
                                  y: 110,
                                  draggable: true
                                  });
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(darthVaderGroup);
layer.add(yodaGroup);
stage.add(layer);

// darth vader
var darthVaderImg = new Kinetic.Image({
                                      x: 0,
                                      y: 0,
                                      image: images.darthVader,
                                      width: 200,
                                      height: 138,
                                      name: 'image'
                                      });

darthVaderGroup.add(darthVaderImg);
addAnchor(darthVaderGroup, -20, -20, 'topLeft', 'none');
addAnchor(darthVaderGroup, 220, -20, 'topRight', 'none');
addAnchor(darthVaderGroup, 220, 158, 'bottomRight', 'none');
addAnchor(darthVaderGroup, -20, 158, 'bottomLeft','none');
addAnchor(darthVaderGroup, 225, 0, 'rotateAnchor','rotate');

darthVaderGroup.on('dragstart', function() {
                   this.moveToTop();
                   });
stage.draw();
}

var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'
};
loadImages(sources, initStage);

</script>
</body>
</html>
gikygik
  • 421
  • 9
  • 26

1 Answers1

1

You can use each anchors show/hide methods inside the images mouseenter/mouseleave events to display the anchors when the mouse enters the image:

image.on("mouseleave",function(){ anchor1.hide();  }

image.on("mouseenter",function(){ anchor1.show(); layer.draw(); }

Problem is that since your anchors are partly outside your image, so hiding the anchors when the mouse leaves the image might make the anchors "disappear" when the user intends to use them.

The ideal solution would be to listen for mouseenter/mouseleave events on the group which contains the image but also extends to include the outside part of the anchors. Unfortunately, a Kinetic.Group will not respond to mouseenter/mouseleave events.

A workaround is to create a Kinetic.Rect background to the group which includes the images plus the anchors. The rect will listen for mouseenter/mouseleave events and will show/hide the anchors. If you don't want the background rect to be visible, just set it's opacity to .001. The rect will still listen for events, but will be invisible.

groupBackgroundRect.on("mouseleave",function(){ anchor1.hide();  }

groupBackgroundRect.on("mouseenter",function(){ anchor1.show(); layer.draw(); }

A related note:

With KineticJS, combining rotation with resizing is made more difficult than it needs to be because KineticJS uses offsetX/offsetY as both an object's rotation point and as an offset to its position. Your key to making it work will be to re-center the offset point after resizing so that your rotation takes place around the new centerpoint--not the previous centerpoint. (or reset the offset reference point to any other point that you want to rotate around).

markE
  • 102,905
  • 11
  • 164
  • 176