【问题标题】:JavaScript shrinking/growing circle transitionJavaScript 缩小/增长循环过渡
【发布时间】:2011-07-18 22:19:10
【问题描述】:

我在这里的第一个问题。 :)

我正在寻找两个图像之间的过渡,其中图像首先缩小为圆形,然后圆圈再次增长,包含另一个图像。这很难解释,而且我可能用错了词,因为我在 Interwebz 上找不到任何关于它的信息。

我说的是像 Loony Toons 结局这样的效果。 http://www.youtube.com/watch?v=ZuYIq-J5l9I

那个缩小到黑色,用 JavaScript/JQuery 能做到吗?

【问题讨论】:

    标签: javascript jquery image transition geometry


    【解决方案1】:

    TL:DR

    - 跨浏览器:[**查看工作演示 这里**](http://jsfiddle.net/lthibodeaux/8DSjz/)。 嗯,主要是工作......和 跨浏览器。可以做得更糟。 ;] - 纯 CSS3 解决方案:[**查看工作演示 这里**](http://jsfiddle.net/lthibodeaux/8DSjz/16/)

    我该如何开始描述这个?如果 CSS 2 剪辑标准支持除“rect”值之外的任何内容,即“circle”或“ellipse”,那就容易多了,但是......因为不存在,我已经尽力拼凑一些东西一起做你所要求的。警告有很多。一个是,如果您希望将图片剪辑到背景,这仅适用于具有纯色背景的东西。另一个原因是,虽然我尝试考虑跨浏览器的 CSS 更新时间,但渲染仍然不是“完美的”。我最初的方法是简单地对要替换的图像上的剪辑进行动画处理,但是由于通过我找到的插件中的缓动功能对剪辑进行更新的方式,这不起作用。最后的方法如下。

    方法

    概念是将图像设置为容器的background-image 属性,如<div>center centerbackground-position,容器的positionrelative,或任何非-静止的。接下来是生成剪辑元素作为容器的子项。第一个是背景颜色的position: absolute 剪裁圆图像,可以是透明的PNG 或GIF(我更喜欢前者),接下来的四个是div,还有absolute 的位置,有left、@987654332 @、topbottom 属性设置为 0,它们将剪裁的每一边。这个想法是动画topleftwidth,和height 的剪辑圆图像,并使用 .animate() 调用的 step 回调选项同步剪辑 div 的宽度和高度通过将它们与当前的 lefttop 值匹配。在动画之间,您将容器的background-image 更改为新图像,然后以相反的方向重新启动动画。

    这需要在 IE7、8 和 Webkit 浏览器中进行一些微调,因为动画在 Firefox 和 IE9 中剪辑得更加清晰。这将是您将在工作演示中看到的 adjust 变量。

    示例代码如下:

    标记

    <div class="imageContainer image1">
        <img class="clip" src="clipCircle.png" />
        <div class="top fill"></div>
        <div class="left fill"></div>
        <div class="right fill"></div>
        <div class="bottom fill"></div>
    </div>
    

    CSS

    div.imageContainer
    {
        background-position: center;
        width: 300px;
        height: 300px;
        position: relative;
    }
    
    img.clip
    {
        width: 100%;
        height: 100%;
        position: absolute;
    }
    
    div.fill
    {
        position: absolute;
        background-color: White;
    }
    
    div.left, div.right
    {
        height: 100%;
        top: 0;
        width: 0;
    }
    
    div.left
    {
        left: 0;
    }
    
    div.right
    {
        right: 0;
    }
    
    div.top, div.bottom
    {
        width: 100%;
        left: 0;
        height: 0;
    }
    
    div.top
    {
        top: 0;
    }
    
    div.bottom
    {
        bottom: 0;
    }
    

    脚本

    var speed = 1000;
    
    $clip = $("img.clip");
    
    $clip.animate({
        top: $clip.parent().height() / 2,
        left: $clip.parent().width() / 2,
        width: 0,
        height: 0
    }, {
        duration: speed,
        step: function(now, fx) {
            switch (fx.prop) {
            case "top":
                $("div.top").css("height", now);
                $("div.bottom").css("height", now + adjust);    
                break;
            case "left":
                $("div.left").css("width", now);
                $("div.right").css("width", now + adjust);
            }
        },
        complete: function() {
            $(this).parent().addClass("image2");
    
            $(this).animate({
                top: 0,
                left: 0,
                width: $clip.parent().width(),
                height: $clip.parent().height()
            }, {
                duration: speed,
                step: function(now, fx) {
                    switch (fx.prop) {
                    case "top":
                        $("div.top").css("height", now);
                        $("div.bottom").css("height", now + adjust);    
                        break;
                    case "left":
                        $("div.left").css("width", now);
                        $("div.right").css("width", now + adjust);
                    }
                },
                complete: function() {
                    $("div.imageContainer > *").removeAttr("style");
                }
            });
        }
    });
    

    编辑:

    CSS3 解决方案

    当跨浏览器兼容性不太重要时,CSS3 是一种选择(尽管我可能会建议看看新的 HTML5 Canvas 可以为这种动画做什么)。有几点需要注意:

    • 图像必须位于容器内,以便我们可以向其中心而不是左上角剪辑。
    • border-radius 属性不会裁剪容器内的子图像。为此,图片必须成为容器的背景图片属性。
    • jQuery 目前不能正确地为边界半径设置动画。您可以替换该属性的当前 jQuery 动画功能或构建自定义边框半径动画对象以使 jQuery 表现得更好。我选择了后者。每个角的边界半径必须单独设置动画。
    • 动画输入或输出由两个单独的段组成,因此“线性”缓动函数可能最适合用于最清晰的结果。

    该方法在下面内联注释:

    标记

    <div class="imageContainer image1">
    </div>
    

    CSS

    div.imageContainer
    {
        background-position: 0px 0px;
        background-repeat: no-repeat;
        width: 300px;
        height: 300px;
        position: absolute;
        top: 0;
        left: 0;
    }
    
    div.image1
    {
        background-image: url(/images/myFirstImage.png);
    }
    
    div.image2
    {
        background-image: url(/images/mySecondImage.png);
    }
    

    脚本

    // Total animation speed in or out will be speed * 1.5
    var speed = 600;
    
    // Store a reference to the object to be clipped
    var $clip = $("div")
    
    // A function to build a mapping object for border radius parameters
    var buildRadiusObj = function(value) {
    
        // Dimension an option object
        var opts = {};
    
        // Use specialized Mozilla CSS attributes when needed
        var attributes = $.browser.mozilla ?
            ["-moz-border-radius-topleft",
             "-moz-border-radius-bottomleft",
             "-moz-border-radius-topright",
             "-moz-border-radius-bottomright"] :
            ["border-top-left-radius",
             "border-bottom-left-radius",
             "border-top-right-radius",
             "border-bottom-right-radius"];
    
        // Build the option object
        $.each(attributes, function(i, key) {
            opts[key] = value;
        });
    
        // Return the result
        return opts;
    }
    
    $clip.animate(buildRadiusObj($clip.width() * 0.5), {    // Animate the border radius until circular
        duration: speed * 0.5,
        easing: "linear"
    }).animate({                                            // Resize and reposition the container
        width: 0,
        left: $clip.width() / 2,
        height: 0,
        top: $clip.height() / 2
    }, {
        duration: speed,
        easing: "linear",
        step: function(now, fx) {                           // Synch up the background-position
            if (fx.prop == "top") {
                $(this).css("background-position", "-" + $(this).css("top") + " -" + $(this).css("left"));
            }
        },
        complete: function() {                              // Swap the image
            $(this).addClass("image2");
        }
    }).animate({                                            // Restore position and size
        width: $clip.width(),
        left: 0,
        height: $clip.height(),
        top: 0
    }, {
        duration: speed,
        easing: "linear",
        step: function(now, fx) {                           // Synch the background-position
            if (fx.prop == "top") {
                $(this).css("background-position", "-" + $(this).css("top") + " -" + $(this).css("left"));
            }
        },
        complete: function() {                              // Remove inline styles but reapply border-radius
            $(this).removeAttr("style").css(buildRadiusObj($clip.width() * 0.5));
        }
    }).animate(buildRadiusObj(0), {                         // Restore border-radius to block
        duration: speed * 0.5,
        easing: "linear",
        complete: function() {
            $(this).removeAttr("style");                    // Remove inline styles
        }
    });
    

    Again, the demo is located here.

    【讨论】:

    • 这看起来很不错,虽然我可能也需要它在背景上工作。我应该提到这一点,但我在发布问题时并不知道。 :-/
    • 但我想我可以将图像放在一个带有 (css3) 圆形边框的 div 中并缩小该 div。即使是圆角,背景图像也会在边框处被截断,对吗?然后我只需要动画那个div的大小和位置以及背景的位置。在 IE 和(其他)较旧的浏览器中,它将动画为正方形,但如果它能让我有可能在背景上使用此动画,我可以忍受。我会尝试弄清楚这个动画是如何工作的,以及如何根据我的需要调整它。感谢您付出的巨大努力。
    • @GolezTrol 好吧,如果您不关心跨浏览器解决方案,这可能会容易得多,因为它的价值。然而,在 IE7/8 的世界里……哦……是的,如果没有 Flash 或类似的东西,这将是一团糟。
    • @GolezTrol 只是为您提供的更新,只需使用 CSS3 标准,我已经为您创建了一个工作演示 here。同样,不是完美无缺,而是一种选择。我将进行编辑以在上述答案中进行解释。
    • @lthibodeaux:做得很好,但是在 Chrome 中,图像在晃动。
    【解决方案2】:

    我尝试了更多,并想出了使用&lt;canvas&gt; 元素的想法。

    请在http://jsfiddle.net/3MG8e/2/查看结果。

    var cv = $('canvas')[0];
    var ctx = cv.getContext('2d');
    ctx.fillStyle = 'black';
    
    var int = null;
    var t = -1;
    var amount = 50;
    var time = 1000;
    var size = 0;
    
    var im = new Image();
    im.src = "http://burzak.com/proj/fxcanvas/docs/images/mario2.png";
    im.onload = function() {
        size = im.width;
        int = setInterval(update, time / amount);
    }
    
    function update() {
        if(++t >= amount) {
            clearInterval(int);
        }
        ctx.fillRect(0, 0, cv.width, cv.height);
        ctx.beginPath();
        ctx.arc(size/2, size/2,
                size/2 - t * (size/2) / amount,
                0, Math.PI*2,
                false);
        ctx.clip();
        ctx.drawImage(im, 0, 0, size, size);
    }
    

    【讨论】:

      【解决方案3】:

      给你。 http://jquery.malsup.com/cycle/查看缩放。圆圈部分可以解决一些问题。

      【讨论】:

      • 是的,我找到了,但这不是我需要的。我不想缩小图像本身,而只是缩小它周围的空间,因此图像的越来越小部分变得可见。
      【解决方案4】:

      我遇到了这个,我希望它很有趣:http://www.netzgesta.de/transm/。一个圈子的转换circles_out 可以完成我认为的工作。

      【讨论】:

      • 看起来不错,虽然我还不能让它工作。今天下午我再试试。
      猜你喜欢
      • 1970-01-01
      • 2015-11-17
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 2021-12-03
      相关资源
      最近更新 更多