Canvas可伸缩弧形位置

时间:2012-12-12 17:02:43

标签: javascript html html5 animation canvas

http://jsfiddle.net/cs5Sg/11/

我想做可缩放的画布。我创建了两个圆(弧)和一条线,当您单击圆并移动它时,该线将跟随并更改位置。问题是我添加了调整大小的代码:

var canvas = document.getElementById('myCanvas'),
    context = canvas.getContext('2d'),
    radius = 12,
    p = null,
    point = {
        p1: { x:100, y:250 },
        p2: { x:400, y:100 }
    },
    moving = false;

window.addEventListener("resize", OnResizeCalled, false);

function OnResizeCalled() {
    var gameWidth = window.innerWidth;
    var gameHeight = window.innerHeight;
    var scaleToFitX = gameWidth / 800;
    var scaleToFitY = gameHeight / 480;

    var currentScreenRatio = gameWidth / gameHeight;
    var optimalRatio = Math.min(scaleToFitX, scaleToFitY);

    if (currentScreenRatio >= 1.77 && currentScreenRatio <= 1.79) {
        canvas.style.width = gameWidth + "px";
        canvas.style.height = gameHeight + "px";
    }
    else {
        canvas.style.width = 800 * optimalRatio + "px";
        canvas.style.height = 480 * optimalRatio + "px";
    }
}

function init() {
        return setInterval(draw, 10);
}

canvas.addEventListener('mousedown', function(e) {
    for (p in point) {
        var
            mouseX = e.clientX - 1,
            mouseY = e.clientY - 1,
            distance = Math.sqrt(Math.pow(mouseX - point[p].x, 2) + Math.pow(mouseY - point[p].y, 2));

        if (distance <= radius) {
            moving = p;
            break;
        }
    }
});

canvas.addEventListener('mouseup', function(e) {
    moving = false;
});

canvas.addEventListener('mousemove', function(e) {

    if(moving) {
        point[moving].x = e.clientX - 1; 
        point[moving].y = e.clientY - 1;
    }
});


function draw() {
    context.clearRect(0, 0, canvas.width, canvas.height);

    context.beginPath();
    context.moveTo(point.p1.x,point.p1.y);
    context.lineTo(point.p2.x,point.p2.y);

    context.closePath();

    context.fillStyle = '#8ED6FF';
    context.fill();
    context.stroke();

    for (p in point) {
        context.beginPath();
        context.arc(point[p].x,point[p].y,radius,0,2*Math.PI);
        context.fillStyle = 'red';
        context.fill();
        context.stroke();
    }
    context.closePath();
}

init();

画布是可缩放的,但问题在于点(圆圈)。更改窗口大小时,它们在画布区域上的位置仍然相同,但distance更改(因此单击选项失败)。如何解决?

1 个答案:

答案 0 :(得分:1)

<强> Live Demo

基本上你只需要一个考虑画布实际尺寸的缩放器值,以及像这样的css尺寸

var scaledX = canvas.width/ canvas.offsetWidth,
    scaledY = canvas.height/ canvas.offsetHeight;

然后每次调整窗口大小时,都需要确保更新缩放器值。

function OnResizeCalled() {

    scaledX = canvas.width/ canvas.offsetWidth;
    scaledY = canvas.height/ canvas.offsetHeight;
}

要获得正确的坐标,您需要在所有鼠标事件中将clientXclientY乘以缩放器

canvas.addEventListener('mousedown', function(e) {
    for (p in point) {
        var 
            mouseX = e.clientX*scaledX,
            mouseY = e.clientY*scaledY,
            distance = Math.sqrt(Math.pow(mouseX - point[p].x, 2) + Math.pow(mouseY - point[p].y, 2));

        if (distance <= radius) {
            moving = p;
            break;
        }
    }
});


canvas.addEventListener('mousemove', function(e) {
    var mouseX = e.clientX*scaledX,
        mouseY = e.clientY*scaledY;

    if(moving) {
        point[moving].x = mouseX;
        point[moving].y = mouseY;
    }
});

完整代码

var canvas = document.getElementById('myCanvas'),
    context = canvas.getContext('2d'),
    radius = 12,
    p = null,
    point = {
        p1: { x:100, y:250},
        p2: { x:400, y:100}
    },
    moving = false,
    scaledX = canvas.width/ canvas.offsetWidth,
    scaledY = canvas.height/ canvas.offsetHeight;

window.addEventListener("resize", OnResizeCalled, false);

function OnResizeCalled() {
    var gameWidth = window.innerWidth;
    var gameHeight = window.innerHeight;
    var scaleToFitX = gameWidth / 800;
    var scaleToFitY = gameHeight / 480;

    var currentScreenRatio = gameWidth / gameHeight;
    var optimalRatio = Math.min(scaleToFitX, scaleToFitY);

    if (currentScreenRatio >= 1.77 && currentScreenRatio <= 1.79) {
        canvas.style.width = gameWidth + "px";
        canvas.style.height = gameHeight + "px";
    }
    else {
        canvas.style.width = 800 * optimalRatio + "px";
        canvas.style.height = 480 * optimalRatio + "px";
    }

    scaledX = canvas.width/ canvas.offsetWidth;
    scaledY = canvas.height/ canvas.offsetHeight;
}

function init() {
        return setInterval(draw, 10);
}

canvas.addEventListener('mousedown', function(e) {
    for (p in point) {
        var 
            mouseX = e.clientX*scaledX,
            mouseY = e.clientY*scaledY,
            distance = Math.sqrt(Math.pow(mouseX - point[p].x, 2) + Math.pow(mouseY - point[p].y, 2));

        if (distance <= radius) {
            moving = p;
            break;
        }
    }
});

canvas.addEventListener('mouseup', function(e) {
    moving = false;
});

canvas.addEventListener('mousemove', function(e) {
    var mouseX = e.clientX*scaledX,
        mouseY = e.clientY*scaledY;

    if(moving) {
        point[moving].x = mouseX; //1 is the border of your canvas
        point[moving].y = mouseY;
    }
});


function draw() {
    context.clearRect(0, 0, canvas.width, canvas.height);

    context.beginPath();
    context.moveTo(point.p1.x,point.p1.y);
    context.lineTo(point.p2.x,point.p2.y);

    context.closePath();

    context.fillStyle = '#8ED6FF';
    context.fill();
    context.stroke();

    for (p in point) {
        context.beginPath();
        context.arc(point[p].x,point[p].y,radius,0,2*Math.PI);
        context.fillStyle = 'red';
        context.fill();
        context.stroke();
    }
    context.closePath();
}

init();