3

我试图在 JavaScript 中使用 . 很难描述我的意思,但我会尝试:

当我将鼠标悬停在页面上时,我希望页面上的内容可以移动。后面的东西应该比前面的东西移动得少——通常的视差效果——除非我想使用平面图像来这样做。现在,通常您必须在图像编辑器中剪掉一些东西并替换现在缺少的部分背景等等。但我想我曾经以某种“假”的方式看到过这个:通过稍微拉伸和压缩背景。

不幸的是,我再也找不到这种效果的例子了,但我很确定它与置换贴图有关。

有这种东西的图书馆吗?或者至少有人知道我可以翻译成 JavaScript 的另一种语言的例子吗?

4

2 回答 2

0

不太确定你在问什么。但我已经使用精灵来快速制作视差场景。它确实涉及多个图像层,但它们很容易制作。 http://www.spritely.net/

还有一些其他的视差解决方案,比如这个。这种方法涉及重复相同的图像以创建深度。 http://www.stevefenton.co.uk/cmsfiles/assets/File/imageparallax.html

于 2013-01-16T02:26:16.320 回答
0

乍一看,Phrogz 链接似乎不相关(我之前自己研究时也点击了相同的链接),但当我更深入地研究它时,它正是我想要的。

不幸的是,它真的很慢,所以它不适合我想要的那种动画,尤其是屏幕填充图像。通过做一些微优化,我得到了一些更快的速度,但最终这种事情对于今天的 JavaScript 来说似乎太激烈了。

无论如何,这就是我最终的结果。也许它可以帮助某人,或者也许有人想出如何加速它以便以 30 或 60 fps 使用它(工人?)。代码一点也不漂亮,因为我只是弄乱了一点。以它为起点。

HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="displacement.js"></script>
    </head>
    <body>
        <script>
            (function() {
                'use strict';
                var source, map, target;
                var sourceCtx, mapCtx, targetCtx;
                var loaded = false;
                var x = 0, y = 0;
                var filter;

                function render() {
                    filter = new filters.DisplacementMap(
                            source,
                            map,
                            target,
                            new filters.Point(0, 0),
                            x,
                            y,
                            filters.ColorChannel.RED,
                            filters.ColorChannel.RED);
                    filter.draw();
                }

                (function init() {
                    var img = new Image();

                    function prepareCanvases() {
                        // Create canvases and add them to the document
                        source = document.createElement('canvas');
                        map = document.createElement('canvas');
                        target = document.createElement('canvas');
                        [target, source, map].forEach(function(canvas) {
                            canvas.setAttribute('width', img.width);
                            canvas.setAttribute('height', img.height);
                            document.body.appendChild(canvas);
                        });

                        // Get contexts
                        sourceCtx = source.getContext('2d');
                        mapCtx = map.getContext('2d');
                        targetCtx = target.getContext('2d');
                    }

                    // Load source image
                    (function loadImage() {
                        img.onload = function() {
                            prepareCanvases();
                            sourceCtx.drawImage(img, 0, 0);
                            img.onload = function() {
                                mapCtx.drawImage(img, 0, 0);
                                addEventListeners();
                                loaded = true;
                            };
                            // Put your displacement map here
                            img.src = 'jn-map-small.jpg';
                        };
                        // Put your image here
                        img.src = 'jn-edit-small.jpg';
                    }());

                    // Event listener
                    function addEventListeners() {
                        target.onmousemove = function(e) {
                            x = ((-e.offsetX / source.width) * 10) + 5;
                            y = ((-e.offsetY / source.height) * 10) + 5;
                            render();
                        };
                    }
                }());
            }());
        </script>
    </body>
</html>

位移.js:

/**
 * Based on Romuald Quantin's code
 * @see http://www.soundstep.com/blog/2012/04/25/javascript-displacement-mapping/
 */
var filters = {} || filters;
(function() {

    filters.ColorChannel = {
        RED: 0,
        GREEN: 1,
        BLUE: 2,
        ALPHA: 3
    };

    filters.Point = function(x, y) {
        this.x = x || 0;
        this.y = y || 0;
    };

    filters.DisplacementMap = function(source, map, target, point, scaleX, scaleY, channelX, channelY) {
        this.source = source;
        this.map = map;
        this.target = target;
        this.sourceCtx = this.source.getContext("2d");
        this.mapCtx = this.map.getContext("2d");
        this.targetCtx = this.target.getContext("2d");
        this.point = point || new filters.Point();
        this.scaleX = scaleX || 0;
        this.scaleY = scaleY || 0;
        this.channelX = channelX || filters.ColorChannel.RED;
        this.channelY = channelY || filters.ColorChannel.RED;
        if (this.channelX !== 0 && this.channelX !== 1 && this.channelX !== 2 && this.channelX !== 3)
            this.channelX = filters.ColorChannel.RED;
        if (this.channelY !== 0 && this.channelY !== 1 && this.channelY !== 2 && this.channelY !== 3)
            this.channelY = filters.ColorChannel.RED;
    };

    var p = filters.DisplacementMap.prototype;

    p.draw = function() {
        var sourceData = this.sourceCtx.getImageData(0, 0, this.source.width, this.source.height);
        var mapData = this.mapCtx.getImageData(0, 0, this.map.width, this.map.height);
        var targetDataX = this.sourceCtx.getImageData(0, 0, this.source.width, this.source.height);
        var targetDataY = this.sourceCtx.getImageData(0, 0, this.source.width, this.source.height);
        var pixelsLength = mapData.data.length / 4;
        var colorValue,
                alphaValue,
                ratio,
                ratioWithAlpha,
                pixelShift,
                sourcePosition,
                targetPosition,
                x,
                y;
        var i = 0;
        var map = this.map;
        var point = this.point;
        var channelX = this.channelX;
        var channelY = this.channelY;
        var scaleX = this.scaleX;
        var scaleY = this.scaleY;
        var source = this.source;
        var target = this.target;
        while (i < pixelsLength) {
            x = ((i % map.width) + point.x) | 0;
            y = (((i / map.width) | 0) + point.y) | 0;
//            alphaValue = mapData.data[i * 4 + filters.ColorChannel.ALPHA];
//            ratioWithAlpha = ratio * (alphaValue / 0xFF);
            targetDataX.data = this.setPixels(targetDataX.data, (target.width * y) + x + ((((mapData.data[i * 4 + channelX]) / 0xFF * 2) - 1) * scaleX | 0), sourceData.data, (source.width * y) + x);
            i++;
        }
        i = 0;
        while (i < pixelsLength) {
            x = ((i % map.width) + point.x) | 0;
            y = (((i / map.width) | 0) + point.y) | 0;
//            alphaValue = mapData.data[i * 4 + filters.ColorChannel.ALPHA];
//            ratioWithAlpha = ratio * (alphaValue / 0xFF);
            targetDataY.data = this.setPixels(targetDataY.data, (target.width * (y + ((((mapData.data[i * 4 + channelY]) / 0xFF * 2) - 1) * scaleY | 0))) + x, targetDataX.data, (source.width * y) + x);
            i++;
        }
        this.targetCtx.putImageData(targetDataY, 0, 0);
    };

    p.setPixels = function(target, pos, source, i) {
        i = i * 4;
        pos = pos * 4;
        target[i] = source[pos];
        target[i + 1] = source[pos + 1];
        target[i + 2] = source[pos + 2];
        target[i + 3] = source[pos + 3];
        return target;
    };

})();
于 2013-01-22T17:13:42.043 回答