0

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

スケーラブルなキャンバスをやりたいです。2 つの円 (円弧) と 1 つの線を作成しました。円をクリックして移動すると、線が追従して位置が変わります。問題は、サイズ変更のコードを追加したときです。

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変更されます (そのため、クリック オプションは失敗します)。それを修正する方法は?

4

1 に答える 1

1

ライブデモ

基本的に、キャンバスの実際の寸法とそのようなcss寸法を考慮したスケーラー値が必要です

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

そして、ウィンドウのサイズが変更されるたびに、スケーラーの値を更新する必要があります。

function OnResizeCalled() {

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

clientX正しい座標を取得するには、すべてのマウス イベントでとclientYスケーラーを掛ける必要があります

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();
于 2012-12-12T21:40:18.660 に答える