문제

I have a kineticjs canvas with image upload and text input, both functions are working fine but I can't get the image resize anchors to show... I need to get the image resize anchors to show "onClick" of the image.

any help is much appreciated :) thanks in advance.

here is the js

var stage = new Kinetic.Stage({
    container: 'container',
    width: 375,
    height: 200
});

var layer = new Kinetic.Layer();

//image loader
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);

function handleImage(e){
    var reader = new FileReader();
    reader.onload = function(event){
        var img = new Image();
        img.onload = function(){
            layer.add(new Kinetic.Image({
                x: 100,
                y: 50,
                image: img,
                width: 200,
                height: 130,
                draggable: true
            }));
            text.moveToTop();
            stage.draw();
        };
        console.log(event);
        img.src = event.target.result;
    };
    reader.readAsDataURL(e.target.files[0]);     
}

// parameters
var resizerRadius = 3;
var rr = resizerRadius * resizerRadius;

// constant
var pi2 = Math.PI * 2;

function draw(img, withAnchors, withBorders) {
    // clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // draw the image
    var view = img.view;
    ctx.drawImage(img, 0, 0, img.width, img.height, view.left, view.top, view.width, view.height);

    // optionally draw the draggable anchors
    if (withAnchors) {
        drawDragAnchor(view.left, view.top);
        drawDragAnchor(view.left + view.width, view.top);
        drawDragAnchor(view.left + view.width, view.top + view.height);
        drawDragAnchor(view.left, view.top + view.height);
    }

    // optionally draw the connecting anchor lines
    if (withBorders) {
        ctx.beginPath();
        ctx.rect(view.left, view.top, view.width, view.height);
        ctx.stroke();
    }
    drawText();
}

function drawDragAnchor(x, y) {
    ctx.beginPath();
    ctx.arc(x, y, resizerRadius, 0, pi2, false);
    ctx.closePath();
    ctx.fill();
}

function drawText(){
    var x = 40,
        y = 100;
    ctx.font = "bold 20px sans-serif";
    ctx.fillStyle = "black";
    ctx.fillText($("#textBox").val(), x, y);
}

// -------------------------------------------
//        -        Hit Testing        -
// -------------------------------------------

// return 0,1,2, or 3 if (x,y) hits the respective anchor
//   of the given view.
// return -1 if no anchor hit.
function anchorHitTest(view, x, y) {
    var dx, dy;
    x -= view.left;
    y -= view.top;
    // top-left
    dx = x;
    dy = y;
    if (dx * dx + dy * dy <= rr) return (0);
    // top-right
    dx = x - view.width;
    dy = y;
    if (dx * dx + dy * dy <= rr) return (1);
    // bottom-right
    dx = x - view.width;
    dy = y - view.height;
    if (dx * dx + dy * dy <= rr) return (2);
    // bottom-left
    dx = x;
    dy = y - view.height;
    if (dx * dx + dy * dy <= rr) return (3);
    return (-1);
}

// return true if (x,y) lies within the view
function hitImage(view, x, y) {
    x -= view.left;
    y -= view.top;
    return (x > 0 && x < view.width && y > 0 && y < view.height);
}

// -------------------------------------------
//        -        Mouse        -
// -------------------------------------------

var mousePos = {
    x: 0,
    y: 0
};
var draggingImage = false;
var startX, startY;
var isDown = false;

var currentImg = null;

var draggingResizer;

function updateMousePos(e) {
    var canvasOffset = $("#canvas").offset();
    var offsetX = canvasOffset.left;
    var offsetY = canvasOffset.top;
    updateMousePos = function (e) {
        mousePos.x = parseInt(e.clientX - offsetX);
        mousePos.y = parseInt(e.clientY - offsetY);
    };
    return updateMousePos(e);
}


function handleMouseDown(e) {
    updateMousePos(e);
    // here you could make a loop to see which image / anchor was clicked
    draggingResizer = anchorHitTest(img.view, mousePos.x, mousePos.y);
    draggingImage = draggingResizer < 0 && hitImage(img.view, mousePos.x, mousePos.y);
    // 
    if (draggingResizer<0 && !draggingImage) return;
    startX = mousePos.x;
    startY = mousePos.y;
    currentImg = img;
}

function handleMouseUp(e) {
    if (!currentImg) return;
    draggingResizer = -1;
    draggingImage = false;
    draw(currentImg, true, false);
    currentImg = null;
}

function handleMouseOut(e) {
    handleMouseUp(e);
}

function handleMouseMove(e) {
    if (!currentImg) return;
    updateMousePos(e);

    var view = currentImg.view;
    if (draggingResizer > -1) {
        var oldView = {
            left: view.left,
            top: view.top,
            width: view.width,
            height: view.height
        };
        // resize the image
        switch (draggingResizer) {
            case 0:
                cl('ttoo');
                //top-left
                view.left = mousePos.x;
                view.top = mousePos.y;
                view.width = oldView.left + oldView.width - mousePos.x;
                view.height = oldView.top + oldView.height - mousePos.y;
                break;
            case 1:
                //top-right
                // view.left  unchanged             
                view.top = mousePos.y;
                view.width = mousePos.x - oldView.left;
                view.height = oldView.top + oldView.height - mousePos.y;
                break;
            case 2:
                //bottom-right
                view.width = mousePos.x - oldView.left;
                view.height = mousePos.y - oldView.top;
                break;
            case 3:
                //bottom-left
                view.left = mousePos.x;
                view.width = oldView.left + oldView.width - mousePos.x;
                view.height = mousePos.y - (oldView.top);
                break;
        }

        if (view.width < 25) view.width = 25;
        if (view.height < 25) view.height = 25;

        // redraw the image with resizing anchors
        draw(currentImg, true, true);

    } else if (draggingImage) {
        imageClick = false;

        // move the image by the amount of the latest drag
        var dx = mousePos.x - startX;
        var dy = mousePos.y - startY;
        view.left += dx;
        view.top += dy;
        // reset the startXY for next time
        startX = mousePos.x;
        startY = mousePos.y;

        // redraw the image with border
        draw(currentImg, false, true);
    }
}



var text = new Kinetic.Text({
    x: 20,
    y: 30,
    text: '',
    fontSize: '30',
    fontFamily: 'Calibri',
    fill: 'black',
    draggable: true
});

stage.add(layer);
layer.add(text);

document.getElementById("textBox").addEventListener("keyup", function () {
    text.setText(this.value);
    layer.draw();
}, true);

document.getElementById("textSize").addEventListener("change", function () {
    var size = this.value;
    text.fontSize(size);
    layer.draw();
}, true);

document.getElementById("fontFamily").addEventListener("change", function () {
    var font = this.value;
    text.fontFamily(font);
    layer.draw();
}, true);

document.getElementById("fontStyle").addEventListener("change", function () {
    var style = this.value;
    text.fontStyle(style);
    layer.draw();
}, true);

document.getElementById("fill").addEventListener("change", function () {
    var colour = this.value;
    text.fill(colour);
    layer.draw();
}, true);



$("#canvas").mousedown(function (e) {
    handleMouseDown(e);
});
$("#canvas").mousemove(function (e) {
    handleMouseMove(e);
});
$("#canvas").mouseup(function (e) {
    handleMouseUp(e);
});
$("#canvas").mouseout(function (e) {
    handleMouseOut(e);
});

// utility
function cl() {
    console.log.apply(console, arguments);
}

can provide jsFiddle if needed :)

도움이 되었습니까?

해결책

You're trying to mix KineticJS with html canvas drawing commands.

That combination doesn't work because KineticJS does its magic by taking over the canvas--leaving no ability to call native canvas commands like context.beginPath.

// these 2 don't play together

... new Kinetic.Image ...

... ctx.beginPath ...

Anyway, Here's the answer to your question (in case you choose KineticJS for your project)

Kinetic.Image can be asked to execute a function when the image is clicked like this:

var image=new Kinetic.Image({
    x: 100,
    y: 50,
    image: img,
    width: 200,
    height: 130,
    draggable: true
}));
image.on("click",function(){

    // The image was clicked
    // Show your anchors now

});
layer.add(image);

[ Addition: Example of Kinetic.Image resizing ]

I don't like the overhead and complexity of maintaining anchors to resize Kinetic.Images.

Here's an example that lets you drag on the right side of the image to scale it proportionally:

http://jsfiddle.net/m1erickson/p8bpC/

You could modify this code to add cosmetic resizing grabbers (the grabbers are not necessary, but if you prefer the "anchor" look, you can add them).

다른 팁

You can refer to this question, the answers are guided and constructive, and contain a jsfiddle with the exact same behavior that you need. Kinetic JS - how do you hide all the anchors for a given group ID

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top