Искажающая сфера в элементе canvas HTML5

В данном уроке мы сделаем искажающую сферу, которая перемещается по изображению в бесконечном цикле. Эффект можно использовать для фоновых изображений на сайте.

demosourse

 

Разметка HTML

Для формирования эффекта создаем два объекта canvas : один для оригинального изображения, а другой - для искажающей сферы.

<div class="container">
    <canvas id="slideshow" width="1024" height="630"></canvas>
    <canvas id="obj" width="256" height="256"></canvas>
</div>

 

CSS

Объект для искаженной сферы должен находиться поверх оригинального изображения:

.container {
    height: 630px;
    margin: 50px auto;
    position: relative;
    width: 1024px;
    z-index: 1;
}
#obj {
    position: absolute;
    z-index: 2;
}

 

JavaScript

При инициализации скрипт подготавливает два объекта canvas и два объекта context . Затем происходит загрузка фонового изображения и вывод его в первом контексте. Затем подготавливается хэш таблица для трансформаций сферы: aMap (с помощью функции mathTwirl). В конце запускается таймер, который обновляет сцену. Функция updateScene обновляет координаты объекта сферы и выводит ее во втором контексте.

var canvas, ctx;
var canvasObj, ctxObj;
var iDstW = 256;
var iDstH = 256;
var iXSpeed = 4;
var iYSpeed = 3;
var iLastX = iDstW / 2;
var iLastY = iDstH / 2;
var oImage;
var aMap = [];
var aMapT = [];
var aBitmap;

var mathTwirl = function(px,py) {
    var x = px - iDstW / 2;
    var y = py - iDstH / 2;
    var r = Math.sqrt(x * x + y * y);
    var maxR = iDstW / 2;
    if (r > maxR) return {'x':px, 'y':py, 't': 1};

    var a = Math.atan2(y, x);
    a -= 1 - r / maxR;

    var dx = Math.cos(a) * r;
    var dy = Math.sin(a) * r;

    return {'x': dx+iDstW/2, 'y': dy+iDstH/2, 't': 1.5}
}

window.onload = function(){

    // Загружаем фоновое изображение
    oImage = new Image();
    oImage.src = 'images/bg.jpg';
    oImage.onload = function () {

        // Создаем объекты canvas и context objects
        canvas = document.getElementById('slideshow');
        ctx = canvas.getContext('2d');
        canvasObj = document.getElementById('obj');
        ctxObj = canvasObj.getContext('2d');

        // Очищаем контекст
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

        // Выводим исходное изобаржение
        ctx.drawImage(oImage, 0, 0);

        aBitmap = ctx.getImageData(0, 0, iDstW, iDstH);
        for (var y = 0; y < iDstH; y++) {
            for (var x = 0; x < iDstW; x++) {
                var t = mathTwirl(x, y);
                aMap[(x + y * iDstH) * 2 + 0] = Math.max(Math.min(t.x, iDstW - 1), 0);
                aMap[(x + y * iDstH) * 2 + 1] = Math.max(Math.min(t.y, iDstH - 1), 0);
                aMapT[(x + y * iDstH)] = t.t;
            }
        }

        // Обновляем сцену
        updateScene();
    };

    function updateScene() {

        // Обновляем последние координаты
        iLastX = iLastX + iXSpeed;
        iLastY = iLastY + iYSpeed;

        // Реверс скорости
        if (iLastX + 1 > ctx.canvas.width - iDstW/2) {
            iXSpeed = -4;
        }
        if (iLastX - 1 < iDstW/2) {
            iXSpeed = 4;
        }
        if (iLastY + 1 > ctx.canvas.height - iDstH/2) {
            iYSpeed = -3;
        }
        if (iLastY - 1 < iDstH/2) {
            iYSpeed = 3;
        }

        // Сдвигаем второй объект
        canvasObj.style.left = iLastX - Math.floor(iDstW / 2) + 'px';
        canvasObj.style.top = iLastY - (Math.floor(iDstH / 2)) + 'px';

        // Выводим искажающую сферу
        var aData = ctx.getImageData(iLastX - Math.ceil(iDstW / 2), iLastY - Math.ceil(iDstH / 2), iDstW, iDstH + 1);
        for (var j = 0; j < iDstH; j++) {
            for (var i = 0; i < iDstW; i++) {
                var u = aMap[(i + j * iDstH) * 2];
                var v = aMap[(i + j * iDstH) * 2 + 1];
                var t = aMapT[(i + j * iDstH)];
                var x = Math.floor(u);
                var y = Math.floor(v);
                var kx = u - x;
                var ky = v - y;
                for (var c = 0; c < 3; c++) {
                    aBitmap.data[(i + j * iDstH) * 4 + c] =
                      (aData.data[(x + y * iDstH) * 4 + c] * (1 - kx) + aData.data[((x + 1) + y * iDstH) * 4 + c] * kx) * (1-ky) * t +
                      (aData.data[(x + (y + 1) * iDstH) * 4 + c] * (1 - kx) + aData.data[((x + 1) + (y + 1) * iDstH) * 4 + c] * kx) * (ky) * t;
                }
            }
        }
        ctxObj.putImageData(aBitmap,0,0);

        // Обновляем таймер
        setTimeout(updateScene, 16);
    }
};

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.script-tutorials.com/html5-canvas-twirl-sphere/
Перевел: Сергей Фастунов
Урок создан: 3 Мая 2012
Просмотров: 22883
Правила перепечатки


5 последних уроков рубрики "HTML и DHTML"

^ Наверх ^