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

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

 

Разметка 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);
    }
};

Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/dr0EbWZiPMQ/lessons.php

Читать комменты и комментировать

Добавить комментарий / отзыв



Защитный код
Обновить

Искажающая сфера в элементе canvas HTML5 | | 2012-06-19 11:58:01 | | Статьи Web-мастеру | | В данном уроке мы сделаем искажающую сферу, которая перемещается по изображению в бесконечном цикле. Эффект можно использовать для фоновых изображений на сайте. Разметка HTMLДля формирования эффекта | РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
 
Поделиться с друзьями: