【问题标题】:How to rotate object in the canvas如何旋转画布中的对象
【发布时间】:2018-02-02 21:11:06
【问题描述】:

我试图只旋转画布中的一个对象,而不是整个画布。

我的代码如下:

var canvas = document.getElementById('canvas');
var buttons = document.getElementById('buttons');
var img = document.getElementById('photo');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var buttons_shown = false;
var angle = 10;
var rotate_angle = 0;


var original_source = img.src;
img.src = original_source;

function init() {
    img.addEventListener('load', function(){
        canvas.width = img.width;
        canvas.height = img.height;
        canvas.addEventListener('mousedown', mouseDown, false);
        canvas.addEventListener('mouseup', mouseUp, false);
        canvas.addEventListener('mousemove', mouseMove, false);
        document.addEventListener("keydown", keyDownPressed, false);
    });


}

function keyDownPressed(e) {
    var keyCode = e.keyCode;
    var left_arrow = 37;
    var right_arrow = 39;
    var up_arrow = 38;
    var down_arrow = 40;

    if(keyCode === left_arrow) {
        onRotateLeft()
    }

    if(keyCode === right_arrow){
        onRotateRight()
    }
}

function mouseDown(e) {
    rect.startX = e.offsetX;
    rect.startY = e.offsetY;
    drag = true;
    buttons_shown = false;
    buttons.classList.add("hide");
}

function mouseUp() { drag = false; buttons_shown = true; }

function onRemoveSelectionClick(e) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drag = false;
    buttons_shown = false;
    buttons.classList.add("hide");
}

function onRotateLeft(){
    rotate_angle = rotate_angle - angle;
    canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';    
}

function onRotateRight(){
    rotate_angle = rotate_angle + angle;
    canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';
}

function mouseMove(e) {
    if (drag) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        rect.w = (e.pageX - this.offsetLeft) - rect.startX;
        rect.h = (e.pageY - this.offsetTop) - rect.startY;
        ctx.shadowBlur = 5;
        ctx.filter = 'blur(10px)';
        ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
        ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);

    }else{
        if(buttons_shown && buttons.classList.contains("hide")){
            buttons.classList.remove("hide");
        }
    }
}
//
init();
.hide{
    display: none !important;
}

canvas{
  position: absolute;
  left: 0; 
  right: 0; 
  top: 0; 
  bottom: 0; 
  display:inline-block;
  background-color: yellow;
}
<div style="position: relative; overflow: hidden;display:inline-block;">
    <img id="photo" src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg"/>
    <canvas id="canvas"></canvas>
</div>


<div id="buttons" class="hide">
    <button onclick="onRotateLeft()">Rotate Left</button>
    <button onclick="onRotateRight()">Rotate right</button><br />
    <button onclick="onRemoveSelectionClick()">Remove Selection</button>
</div>

因此,如果绘制了一个对象,我会显示向左或向右旋转或删除它的按钮。如果我点击例如Rotate Left 按钮,它将执行下一个代码:

rotate_angle = rotate_angle - angle;
canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';

但这会旋转我的整个画布(黄色背景),但我只想旋转画布内的对象。

有什么想法吗?

【问题讨论】:

    标签: javascript canvas


    【解决方案1】:

    使用画布变换而不是 CSS 变换。

    渲染矩形时需要在画布中应用变换。

    sn-p 是您的代码的副本,有一些更改。

    • 渲染是通过requestAnimationFrame 完成的,以免鼠标移动时出现不必要的渲染。

    • 只要需要更新画布,就会将全局标志 update 设置为 true

    • rectangles 的数组用于存储每个矩形。

    • 矩形对象还存储了它的旋转rect.rotate,这样每个矩形都有一个独立的旋转。

    • 全局变量rect保存当前矩形。

    • 事件更改全局rect 对象并设置update = true 标志,它们不进行任何渲染。

    • 矩形围绕其中心旋转

    • 画布上下文 ctx.rotate 使用弧度而不是度数

    查看代码了解更多信息。

    var canvas = document.getElementById('canvas');
    var buttons = document.getElementById('buttons');
    var img = document.getElementById('photo');
    var ctx = canvas.getContext('2d');
    var rect = {};
    var drag = false;
    var buttons_shown = false;
    var angle = 10 * (Math.PI / 180) ;
    var rotate_angle = 0;
    
    var update = true; // when true updates canvas
    
    
    var original_source = img.src;
    img.src = original_source;
    
    function init() {
        img.addEventListener('load', function(){
            canvas.width = img.width;
            canvas.height = img.height;
            canvas.addEventListener('mousedown', mouseDown, false);
            canvas.addEventListener('mouseup', mouseUp, false);
            canvas.addEventListener('mousemove', mouseMove, false);
            document.addEventListener("keydown", keyDownPressed, false);
        });
        // start the rendering loop
        requestAnimationFrame(updateCanvas);
    
    
    }
    
    // main render loop only updates if update is true
    function updateCanvas(){
      if(update){
          drawCanvas();
          update = false;
      }
    
      requestAnimationFrame(updateCanvas);
    }
    
    // array of rectangles
    const rectangles = [];
    
    // adds a rectangle
    function addRectangle(rect){
       rectangles.push(rect);
       
    }
    
    // draws a rectangle with rotation 
    function drawRect(rect){
       ctx.setTransform(1,0,0,1,rect.startX + rect.w / 2, rect.startY + rect.h / 2);
       ctx.rotate(rect.rotate);
       ctx.beginPath();
       ctx.rect(-rect.w/2, -rect.h/2, rect.w, rect.h);
       ctx.fill();
       ctx.stroke();
    
    
    }
    
    // clears canvas sets filters and draws rectangles
    function drawCanvas(){
        // restore the default transform as rectangle rendering does not restore the transform.
        ctx.setTransform(1,0,0,1,0,0);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.shadowBlur = 5;
        ctx.filter = 'blur(10px)';
        rectangles.forEach(drawRect);
    
    
    }
    
    function keyDownPressed(e) {
        var keyCode = e.keyCode;
        var left_arrow = 37;
        var right_arrow = 39;
        var up_arrow = 38;
        var down_arrow = 40;
    
        if(keyCode === left_arrow) {
            onRotateLeft()
        }
    
        if(keyCode === right_arrow){
            onRotateRight()
        }
    }
    
    // create new rect add to array 
    function mouseDown(e) {
        rect = {
          startX : e.offsetX,
          startY : e.offsetY,
          w : 1,
          h : 1,
          rotate : 0,
        };
        drag = true;
        buttons_shown = false;
        buttons.classList.add("hide");
        addRectangle(rect);
        update = true;
    }
    
    function mouseUp() { drag = false; buttons_shown = true; update = true; }
    
    
    // removes top rectangle and sets next down as current or if none then hides controls
    function onRemoveSelectionClick(e) {
    
        rectangles.pop();
        if(rectangles.length === 0){
          drag = false;
          buttons_shown = false;
          buttons.classList.add("hide");
        }else{
          rect = rectangles[rectangles.length -1];
        }
        update = true;
    }
    
    // rotate current rectangle
    function onRotateLeft(){
        rect.rotate -= angle;
        update = true;
          
    }
    
    function onRotateRight(){
        rect.rotate += angle;
        update = true;
    }
    
    function mouseMove(e) {
        if (drag) {
            rect.w = (e.pageX - this.offsetLeft) - rect.startX;
            rect.h = (e.pageY - this.offsetTop) - rect.startY;
            update = true;
    
        }else{
            if(buttons_shown && buttons.classList.contains("hide")){
                buttons.classList.remove("hide");
            }
        }
    }
    //
    init();
    .hide{
        display: none !important;
    }
    
    canvas{
      position: absolute;
      left: 0; 
      right: 0; 
      top: 0; 
      bottom: 0; 
      display:inline-block;
      background-color: yellow;
    }
    <div style="position: relative; overflow: hidden;display:inline-block;">
        <img id="photo" src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg"/>
        <canvas id="canvas"></canvas>
    </div>
    
    
    <div id="buttons" class="hide">
        <button onclick="onRotateLeft()">Rotate Left</button>
        <button onclick="onRotateRight()">Rotate right</button><br />
        <button onclick="onRemoveSelectionClick()">Remove Selection</button>
    </div>

    【讨论】:

    • 你真是个天才。谢谢一百万。
    【解决方案2】:

    您将需要一个单独的画布来放置对象;在这个单独的画布上绘制对象,然后根据您的实际意图,您可以:

    • 使用context.rotate()结合context.drawImage()在主画布上绘制辅助画布的内容;
    • 使用 CSS 将一个画布叠加到另一个画布之上。

    再一次,也许您可​​以使用 context.rotate() 然后在主画布上绘制,如:HTML5 Canvas Rotate Image

    【讨论】:

      猜你喜欢
      • 2014-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-30
      • 2013-02-23
      • 1970-01-01
      • 2011-02-10
      相关资源
      最近更新 更多