簡體   English   中英

畫布可縮放弧位置

[英]Canvas scalable arc position

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發生變化(因此,單擊選項會失敗)。 如何解決?

現場演示

基本上,您只需要一個考慮畫布實際尺寸的縮放器值,以及像這樣的css尺寸

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

然后,每次調整窗口大小時,都需要確保更新縮放器值。

function OnResizeCalled() {

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

要獲得正確的坐標,您需要在所有鼠標事件中將縮放clientY乘以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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM