css 变换旋转(90deg)后画布中风矩形行为问题

问题描述 投票:0回答:1

首先,我英语不好。谢谢您的理解。

现在让我解释一下我目前遇到的困难。

我目前正在开发一个使用鼠标在画布上绘制矩形的函数(使用

strokeRect
函数)。

正常情况下运行良好,但是点击旋转按钮时出现问题(出现鼠标坐标处未绘制矩形的问题)。

作为参考,当您单击旋转按钮时,它会使用 css

transform = 'rotate(90deg)'
进行旋转,并在
calcCanvasRect
函数中检索画布的大小(使用
getBoundingClientRect
函数)。

我需要一些建议来解决这个问题。帮忙!

供参考,HT结构如下。

<div class="myContainer">
    <div class="rotation-wrapper">
       <div id="canvasParent">
          <canvas id="view_canvas"></canvas>
       </div>
    </div>
</div>

这是完整的源代码。

let mode = 'off';
let wwViewCanvas;
let wwCanvasRect;
let isDown = false;
let mousedown, mouseup, mousemove;
let zoombox;
let post_obj;

function calcCanvasRect() {
    if(wwViewCanvas) {
        let rect = wwViewCanvas.canvas.getBoundingClientRect();
        let scrollY = window.scrollY;


        wwCanvasRect = {
            left: rect.left,
            top: rect.top + scrollY,
            right: rect.right,
            bottom: rect.bottom + scrollY,
            width: rect.width,
            height: rect.height,
        };

        if(mode === '90') {
            //To do anything..
        }
    }
}

function appendViewCanvas() {        
    let width, height;

    if(mode === '90') {
        width = 338;
        height = 600;
    }
    else if(mode === 'off') {
        width = 600;
        height = 338;
    }
    
    $('#canvasParent').append(
        `<canvas id="view_canvas" width="${width}" height="${height}" style="cursor:crosshair; position:absolute; top:0; left:0; z-index:10;">
        </canvas>`
    );
}

function getViewCanvas() {
    let element = document.getElementById('view_canvas');

    if(!element) {
        appendViewCanvas();
        element = document.getElementById('view_canvas');
    }

    return element;
}

function initViewCanvas() {        
    let ctx;
    let canvas = getViewCanvas();
    
    ctx = canvas.getContext('2d');
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#00B0F0';

    wwViewCanvas = {
        canvas: canvas,
        context: ctx,
    };
}

function getEventPosition(event) {
    let eventCoordinateX, eventCoordinateY;                            
    let pageX = event.pageX;
    let pageY = event.pageY;

    if (pageX > wwCanvasRect.right) {
        pageX = wwCanvasRect.right;
    }
    else if (pageX < wwCanvasRect.left) {
        pageX = wwCanvasRect.left;
    }

    if (pageY > wwCanvasRect.bottom) {
        pageY = wwCanvasRect.bottom;
    }
    else if (pageY < wwCanvasRect.top) {
        pageY = wwCanvasRect.top;
    }

    eventCoordinateX = pageX - wwCanvasRect.left;
    eventCoordinateY = pageY - wwCanvasRect.top;

    return {
        x: Math.floor(eventCoordinateX),
        y: Math.floor(eventCoordinateY),
    };
}

function getZoombox(start, end) {
    return {
        width: end.x - start.x,
        height: end.y - start.y,
    };
}

function clearCanvas() {
    wwViewCanvas.context.clearRect(0, 0, wwViewCanvas.canvas.width, wwViewCanvas.canvas.height);        
}

function getCoordinatesBox(center_x, center_y) {
    return {
        Coordinates_box: {
            x: center_x,
            y: center_y,
            box_w: Math.abs(zoombox.width),
            box_h: Math.abs(zoombox.height),
            w: wwCanvasRect.width,
            h: wwCanvasRect.height,
        },
    };
}

function canvasMousedown(event) {
    mousedown = getEventPosition(event);        
    isDown = true;        
}

function canvasMouseup(event) {
    if (!isDown) {
        return;
    }

    mouseup = getEventPosition(event);        
    zoombox = getZoombox(mousedown, mouseup);        

    let center_x, center_y;

    center_x = Math.round(zoombox.width / 2) + mousedown.x;
    center_y = Math.round(zoombox.height / 2) + mousedown.y;

    post_obj = getCoordinatesBox(center_x, center_y);

    
    clearCanvas();
    isDown = false;
}

function canvasMousemove(event) {
    if (!isDown) {            
        return;
    }

    mousemove = getEventPosition(event);
    zoombox = getZoombox(mousedown, mousemove);        
    
    clearCanvas();
    wwViewCanvas.context.strokeRect(mousedown.x, mousedown.y, zoombox.width, zoombox.height);
}

function getTransformHeight(rect) {
    return rect.container_rect.height + (rect.wrapper_rect.width - rect.container_rect.height);
}

function getTranslateValueOfTopBottom(rect) {
    return (rect.wrapper_rect.width - rect.container_rect.height) / 2;            
}


function calcRotationLayoutRect(container, wrapper) {
    return {
        container_rect: container.getBoundingClientRect(),
        wrapper_rect: wrapper.getBoundingClientRect(),        
    };
}


$(document).ready(function() {    
    initViewCanvas();

    wwViewCanvas.canvas.addEventListener('mousedown', canvasMousedown);
    wwViewCanvas.canvas.addEventListener('mouseup', canvasMouseup);
    wwViewCanvas.canvas.addEventListener('mousemove', canvasMousemove);
    

    let myContainer = document.getElementsByClassName('myContainer')[0];
    let rotationWrapper = document.getElementsByClassName('rotation-wrapper')[0];

    rotationLayoutRect = calcRotationLayoutRect(myContainer, rotationWrapper);

    let transformHeight = getTransformHeight(rotationLayoutRect);
    let translateValue = getTranslateValueOfTopBottom(rotationLayoutRect);

    const noTransitionCallback = function () {
        if (mode === 'off') {
            rotationWrapper.style.transform = 'rotate(0deg)';                    
            myContainer.style.height = `${rotationLayoutRect.container_rect.height}px`;

            mode = '90';
        }
        else if (mode === '90') {       
            rotationWrapper.style.transform = `rotate(90deg) translate(${translateValue}px, 0px)`;                    
            myContainer.style.height = `${transformHeight}px`;            

            mode = 'off';
        }

        calcCanvasRect();
    };

    $('#rotation_btn').click(noTransitionCallback);
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <title>canvas rotation</title>
    <style>
        .myContainer{
            background-color: yellowgreen;
        }
        canvas {
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <div class="myContainer" style="width:620px; height:374px">
        <div class="rotation-wrapper">
            <div id="canvasParent" style="width:600px; height:338px;"></div>            
        </div>
    </div>
    <div class="text-center">   
        <button type="button" id="rotation_btn" style="width:64px">
            rotation button
        </button>
    </div> 
</body>
</html>

我尝试使用画布平移和旋转功能,但找不到解决方案。有更好的办法吗?

还是有什么我不知道的事情?

javascript jquery css html5-canvas
1个回答
0
投票

一旦画布旋转,您将需要更新

canvasMousemove
函数以考虑
strokeRect
的不同坐标。

if (mode === '90') {
    wwViewCanvas.context.strokeRect(mousedown.x, mousedown.y, zoombox.width, zoombox.height);
}
else{
    let rect = wwViewCanvas.canvas.getBoundingClientRect();        
    wwViewCanvas.context.strokeRect(mousedown.y, rect.width-mousedown.x, zoombox.height, -1*zoombox.width);
}

下面是完整的运行代码片段,也适用于旋转的画布。

let mode = 'off';
let wwViewCanvas;
let wwCanvasRect;
let isDown = false;
let mousedown, mouseup, mousemove;
let zoombox;
let post_obj;

function calcCanvasRect() {
    if(wwViewCanvas) {
        let rect = wwViewCanvas.canvas.getBoundingClientRect();
        let scrollY = window.scrollY;


        wwCanvasRect = {
            left: rect.left,
            top: rect.top + scrollY,
            right: rect.right,
            bottom: rect.bottom + scrollY,
            width: rect.width,
            height: rect.height,
        };

        if(mode === '90') {
            //To do anything..
        }
    }
}

function appendViewCanvas() {        
    let width, height;

    if(mode === '90') {
        width = 338;
        height = 600;
    }
    else if(mode === 'off') {
        width = 600;
        height = 338;
    }
    
    $('#canvasParent').append(
        `<canvas id="view_canvas" width="${width}" height="${height}" style="cursor:crosshair; position:absolute; top:0; left:0; z-index:10;">
        </canvas>`
    );
}

function getViewCanvas() {
    let element = document.getElementById('view_canvas');

    if(!element) {
        appendViewCanvas();
        element = document.getElementById('view_canvas');
    }

    return element;
}

function initViewCanvas() {        
    let ctx;
    let canvas = getViewCanvas();
    
    ctx = canvas.getContext('2d');
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#00B0F0';

    wwViewCanvas = {
        canvas: canvas,
        context: ctx,
    };
}

function getEventPosition(event) {
    let eventCoordinateX, eventCoordinateY;                            
    let pageX = event.pageX;
    let pageY = event.pageY;

    if (pageX > wwCanvasRect.right) {
        pageX = wwCanvasRect.right;
    }
    else if (pageX < wwCanvasRect.left) {
        pageX = wwCanvasRect.left;
    }

    if (pageY > wwCanvasRect.bottom) {
        pageY = wwCanvasRect.bottom;
    }
    else if (pageY < wwCanvasRect.top) {
        pageY = wwCanvasRect.top;
    }

    eventCoordinateX = pageX - wwCanvasRect.left;
    eventCoordinateY = pageY - wwCanvasRect.top;

    //console.log(eventCoordinateX);
    //console.log(eventCoordinateY);

    return {
        x: Math.floor(eventCoordinateX),
        y: Math.floor(eventCoordinateY),
    };
}

function getZoombox(start, end) {
    return {
        width: end.x - start.x,
        height: end.y - start.y,
    };
}

function clearCanvas() {
    wwViewCanvas.context.clearRect(0, 0, wwViewCanvas.canvas.width, wwViewCanvas.canvas.height);        
}

function getCoordinatesBox(center_x, center_y) {
    return {
        Coordinates_box: {
            x: center_x,
            y: center_y,
            box_w: Math.abs(zoombox.width),
            box_h: Math.abs(zoombox.height),
            w: wwCanvasRect.width,
            h: wwCanvasRect.height,
        },
    };
}

function canvasMousedown(event) {
    mousedown = getEventPosition(event);        
    isDown = true;        
}

function canvasMouseup(event) {
    if (!isDown) {
        return;
    }

    mouseup = getEventPosition(event);        
    zoombox = getZoombox(mousedown, mouseup);        

    let center_x, center_y;

    center_x = Math.round(zoombox.width / 2) + mousedown.x;
    center_y = Math.round(zoombox.height / 2) + mousedown.y;

    post_obj = getCoordinatesBox(center_x, center_y);

    
    clearCanvas();
    isDown = false;
}

function canvasMousemove(event) {
    if (!isDown) {            
        return;
    }

    mousemove = getEventPosition(event);
    zoombox = getZoombox(mousedown, mousemove);        
    
    clearCanvas();

    if (mode === '90') {
        wwViewCanvas.context.strokeRect(mousedown.x, mousedown.y, zoombox.width, zoombox.height);
    }
    else{
        let rect = wwViewCanvas.canvas.getBoundingClientRect();        
        wwViewCanvas.context.strokeRect(mousedown.y, rect.width-mousedown.x, zoombox.height, -1*zoombox.width);
    }
    
    
}

function getTransformHeight(rect) {
    return rect.container_rect.height + (rect.wrapper_rect.width - rect.container_rect.height);
}

function getTranslateValueOfTopBottom(rect) {
    return (rect.wrapper_rect.width - rect.container_rect.height) / 2;            
}


function calcRotationLayoutRect(container, wrapper) {
    return {
        container_rect: container.getBoundingClientRect(),
        wrapper_rect: wrapper.getBoundingClientRect(),        
    };
}


$(document).ready(function() {    
    initViewCanvas();

    wwViewCanvas.canvas.addEventListener('mousedown', canvasMousedown);
    wwViewCanvas.canvas.addEventListener('mouseup', canvasMouseup);
    wwViewCanvas.canvas.addEventListener('mousemove', canvasMousemove);
    

    let myContainer = document.getElementsByClassName('myContainer')[0];
    let rotationWrapper = document.getElementsByClassName('rotation-wrapper')[0];

    rotationLayoutRect = calcRotationLayoutRect(myContainer, rotationWrapper);

    let transformHeight = getTransformHeight(rotationLayoutRect);
    let translateValue = getTranslateValueOfTopBottom(rotationLayoutRect);

    const noTransitionCallback = function () {
        if (mode === 'off') {
            rotationWrapper.style.transform = 'rotate(0deg)';                    
            myContainer.style.height = `${rotationLayoutRect.container_rect.height}px`;

            mode = '90';
        }
        else if (mode === '90') {       
            rotationWrapper.style.transform = `rotate(90deg) translate(${translateValue}px, 0px)`;                    
            myContainer.style.height = `${transformHeight}px`;            

            mode = 'off';
        }

        calcCanvasRect();
    };

    $('#rotation_btn').click(noTransitionCallback);
});
.myContainer{
    background-color: yellowgreen;
}
canvas {
    border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class="myContainer" style="width:620px; height:374px">
    <div class="rotation-wrapper">
        <div id="canvasParent" style="width:600px; height:338px;"></div>            
    </div>
</div>
<div class="text-center">   
    <button type="button" id="rotation_btn" style="width:64px">
        rotation button
    </button>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.