代码之家  ›  专栏  ›  技术社区  ›  Mevia

画布水平旋转img

  •  0
  • Mevia  · 技术社区  · 6 年前

    我正在进行动画优化,我想尝试一下canvas,看看它的表现如何,但我在canvas方面经验不足,我不知道如何准备这种动画的概念。

    这是显示动画旋转方式的gif,如下所示:

    enter image description here

    这是我目前的js代码:

    var cvs = document.getElementById('coin-spin'),
        ctx = cvs.getContext('2d'),
        w = cvs.width = 400,
        h = cvs.height = 400,
        cx = w / 2,
        cy = h / 2,
        a = 0;
    
    var img = new Image();
    
    var loop = function() {
        // BG
        ctx.fillStyle = '#ccc';
        ctx.fillRect(0, 0, w, h);
    
        // draw image
        ctx.save();
        ctx.translate(cx, cy);
        ctx.rotate(Math.PI / 180 * a);
        ctx.translate(-cx, -cy);
        ctx.drawImage(img, cx - (img.width / 2), cy -  (img.height / 2));
        ctx.restore();
    
        // axis
        ctx.strokeStyle = '#000';
    
        ctx.beginPath();
        ctx.moveTo(cx, 0);
        ctx.lineTo(cx, h);
        ctx.stroke();
    
        ctx.beginPath();
        ctx.moveTo(0, cy);
        ctx.lineTo(w, cy);
        ctx.stroke();
    
        //mod angle
        a++;
        window.requestAnimationFrame(loop);
    };
    
    img.onload = function() {
        loop();
    };
    
    img.src = 'https://image.ibb.co/gqkeXx/coin.png';
    

    还有工作 demo 在小提琴上。

    有人能演示如何添加到代码中,使图像像gif一样水平旋转吗?

    编辑----

    我添加了旋转,因为这也是要做的事情,但仍在努力如何旋转它。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Timothy Groote    6 年前

    要解决沿两个轴旋转对象的问题(通过将宽度映射为正弦波来假装一个轴),可以使用屏幕外画布渲染围绕一个轴旋转的硬币,然后应用第二个旋转来渲染该画布;

    //make an offscreen canvas for rendering the coin rotating around one axis
    var offscreenCanvas = document.createElement('canvas');
    
    var cvs = document.getElementById('coin-spin'),
            ctx = cvs.getContext('2d'),
            w = cvs.width = 400,
            h = cvs.height = 400,
            cx = w / 2,
            cy = h / 2,
            a = 0;
    
        var img = new Image();
        var frameCount = 0;
    
        var loop = function() {
        frameCount++;
    
        // BG
        ctx.fillStyle = '#ccc';
        ctx.fillRect(0, 0, w, h);
    
        offscreenContext.fillStyle = '#ccc';
        offscreenContext.fillRect(0, 0, w, h);
    
        //determine how wide to render the offscreen canvas so we can fake
        //rotation around the second axis
        var imgRenderWidth = offscreenCanvas.width * Math.sin(frameCount/10.0)
    
        //render the coin rotating around one axis to the offscreen canvas
        offscreenContext.save();
        offscreenContext.translate(img.width/2, img.height/2);
        offscreenContext.rotate(Math.PI / 180 * a);
        offscreenContext.translate((0-img.width)/2, (0-img.height)/2);
        offscreenContext.drawImage(img, 0,0);
        offscreenContext.restore();
    
            // draw offscreen canvas to the screen with our precalculated width
            ctx.save();
            ctx.drawImage(offscreenCanvas, cx - (imgRenderWidth / 2), cy -  (offscreenCanvas.height / 2), imgRenderWidth, offscreenCanvas.height);
            ctx.restore();
    
            // axis
            ctx.strokeStyle = '#000';
    
            ctx.beginPath();
            ctx.moveTo(cx, 0);
            ctx.lineTo(cx, h);
            ctx.stroke();
    
            ctx.beginPath();
            ctx.moveTo(0, cy);
            ctx.lineTo(w, cy);
            ctx.stroke();
    
            //mod angle
            a++;
            window.requestAnimationFrame(loop);
        };
    
        //once the image has loaded, we know what size our offscreen canvas needs to be
        img.onload = function() {
        offscreenCanvas.width = img.width;
        offscreenCanvas.height = img.height;
    
            loop();
        };
    
        img.src = 'https://image.ibb.co/gqkeXx/coin.png';
    
        //prepare the offscreen context so we can render to it later
        var offscreenContext =  offscreenCanvas.getContext('2d');
    

    https://jsfiddle.net/ay3h5vuo/