Canvas在Chrome / Firefox中断断续续,但在Edge上流畅

时间:2016-11-30 12:01:14

标签: javascript css html5 google-chrome canvas

    window.requestAnimFrame = (function() {
    return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(callback, element) {
                    window.setTimeout(callback, 1000 / 30);
            };
    })();

    function getRandomInt(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    var c = document.getElementById('canv'),
            $ = c.getContext('2d'),
            w = c.width = window.innerWidth,
            h = c.height = window.innerHeight,
            minX = 20,
            minY = 20,
            varX = (w / 10) - (minX / 10),
            varY = h - (minY * 2),
            w1 = (w - (minX * 2) - varX) / 4,
            piRatio = Math.PI / 180,
            debug = false,
            clearTheFrame = true,
            tension = 0.5,
            numberOfCurves = 50,
            TimeOnCurve = 1/(numberOfCurves),
            minTime = 8,
            maxTime = 15,
            minDelay = 0,
            maxDelay = 5,
            CurvesArray = [],
            alpha = 1,
            yellowStart = 'hsla(45, 100%, 60%, 0)',
            yellow = 'hsla(45, 100%, 60%, '+ alpha +')',
            red = 'hsla(11, 100%, 50%, '+ alpha +')',
            blue = 'hsla(242, 100%, 50%, '+ alpha +')',
            blueEnd = 'hsla(242, 100%, 50%, 0)',
            gradientArray = [];

    var curve1 = {
            x1: minX,
            y1: minY,
            x2: minX,
            y2: minY + (varY * (4 / 3)),
            x3: minX,
            y3: minY
    }

    var curve2 = {
            x1: minX + w1,
            y1: h - minY,
            x2: minX + w1 + (varX / 2),
            y2: minY - (varY / 2),
            x3: minX + w1 + varX,
            y3: h - minY
    }

    var curve3 = {
            x1: minX + (w1 * 2),
            y1: minY,
            x2: minX + (w1 * 2) + (varX / 2),
            y2: minY + (varY * (4 / 3)),
            x3: minX + (w1 * 2) + varX,
            y3: minY
    }

    var curve4 = {
            x1: minX + (w1 * 3),
            y1: h - minY,
            x2: minX + (w1 * 3) + (varX / 2),
            y2: minY - (varY / 2),
            x3: minX + (w1 * 3) + varX,
            y3: h - minY
    }
    var curve5 = {
            x1: w - minX,
            y1: minY,
            x2: w - minX,
            y2: minY + (varY * (4 / 3)),
            x3: w - minX,
            y3: minY
    }

    $.globalCompositeOperation = "source-over";

    window.addEventListener('resize', function() {
            c.width = window.innerWidth;
            c.height = window.innerHeight;
            ready();
    }, false);

    var ready = function() {
            w = c.width = window.innerWidth,
                    h = c.height = window.innerHeight,
                    varX = (w / 10) - (minX / 10),
                    varY = h - (minY * 2),
                    w1 = (w - (minX * 2) - varX) / 4,

            createGradients();
            curve1.x1 = minX;
            curve1.x2 = minX;
            curve1.x3 = minX;   

            curve2.x1 = minX + w1;
            curve2.x2 = minX + w1 + (varX / 2);
            curve2.x3 = minX + w1 + varX;   

            curve3.x1 = minX + (w1 * 2);
            curve3.x2 = minX + (w1 * 2) + (varX / 2);
            curve3.x3 = minX + (w1 * 2) + varX; 

            curve4.x1 = minX + (w1 * 3);
            curve4.x2 = minX + (w1 * 3) + (varX / 2);
            curve4.x3 = minX + (w1 * 3) + varX; 

            curve5.x1 = w - minX;
            curve5.x2 = w - minX;
            curve5.x3 = w - minX;   
    }

    var clearFrame = function() {

            if (clearTheFrame == true) {
                    $.clearRect((minX-1), 0, (w-(minX*2)+2), h); // only clear the bits we draw on
            }

            //draw quadratic curves that contain the points for the animation
            if (debug == true) { 
                    $.strokeStyle='grey';
                    $.beginPath();
                    $.moveTo(curve1.x1, curve1.y1);
                    $.quadraticCurveTo(curve1.x2, curve1.y2, curve1.x3, curve1.y3);

                    $.moveTo(curve2.x1, curve2.y1);
                    $.quadraticCurveTo(curve2.x2, curve2.y2, curve2.x3, curve2.y3);

                    $.moveTo(curve3.x1, curve3.y1);
                    $.quadraticCurveTo(curve3.x2, curve3.y2, curve3.x3, curve3.y3);

                    $.moveTo(curve4.x1, curve4.y1);
                    $.quadraticCurveTo(curve4.x2, curve4.y2, curve4.x3, curve4.y3);

                    $.moveTo(curve5.x1, curve5.y1);
                    $.quadraticCurveTo(curve5.x2, curve5.y2, curve5.x3, curve5.y3);
                    $.stroke();
                    $.closePath();
            }
    }

    var tweenCurves = function() {
            MainTL = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    repeat: -1
            });

            Curve1TL = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    repeat: -1
            });

            Curve1y1 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve1y1
                    .to(curve1, getRandomInt(minTime, maxTime), {
                            y1: h - minY,
                            ease: Power2.easeInOut
                    })
            Curve1y2 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve1y2
                    .to(curve1, getRandomInt(minTime, maxTime), {
                            y2: minY - (varY / 2),
                            ease: Power2.easeInOut
                    })
            Curve1y3 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve1y3
                    .to(curve1, getRandomInt(minTime, maxTime), {
                            y3: h - minY,
                            ease: Power2.easeInOut
                    });

            Curve1TL
                    .add(Curve1y1, "start")
                    .add(Curve1y2, "start")
                    .add(Curve1y3, "start")

            Curve2TL = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    repeat: -1
            });

            Curve2y1 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve2y1
                    .to(curve2, getRandomInt(minTime, maxTime), {
                            y1: minY,
                            ease: Power2.easeInOut
                    })
            Curve2y2 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve2y2
                    .to(curve2, getRandomInt(minTime, maxTime), {
                            y2: minY + (varY * (4 / 3)),
                            ease: Power2.easeInOut
                    })
            Curve2y3 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve2y3
                    .to(curve2, getRandomInt(minTime, maxTime), {
                            y3: minY,
                            ease: Power2.easeInOut
                    });

            Curve2TL
                    .add(Curve2y1, "start")
                    .add(Curve2y2, "start")
                    .add(Curve2y3, "start")

            Curve3TL = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    repeat: -1
            });

            Curve3y1 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve3y1
                    .to(curve3, getRandomInt(minTime, maxTime), {
                            y1: h - minY,
                            ease: Power2.easeInOut
                    })
            Curve3y2 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve3y2
                    .to(curve3, getRandomInt(minTime, maxTime), {
                            y2: minY - (varY / 2),
                            ease: Power2.easeInOut
                    })
            Curve3y3 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve3y3
                    .to(curve3, getRandomInt(minTime, maxTime), {
                            y3: h - minY,
                            ease: Power2.easeInOut
                    });

            Curve3TL
                    .add(Curve3y1, "start")
                    .add(Curve3y2, "start")
                    .add(Curve3y3, "start")

            Curve4TL = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    repeat: -1
            });

            Curve4y1 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve4y1
                    .to(curve4, getRandomInt(minTime, maxTime), {
                            y1: minY,
                            ease: Power2.easeInOut
                    })
            Curve4y2 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve4y2
                    .to(curve4, getRandomInt(minTime, maxTime), {
                            y2: minY + (varY * (4 / 3)),
                            ease: Power2.easeInOut
                    })
            Curve4y3 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve4y3
                    .to(curve4, getRandomInt(minTime, maxTime), {
                            y3: minY,
                            ease: Power2.easeInOut
                    });

            Curve4TL
                    .add(Curve4y1, "start")
                    .add(Curve4y2, "start")
                    .add(Curve4y3, "start")

            Curve5TL = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    repeat: -1
            });

            Curve5y1 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve5y1
                    .to(curve5, getRandomInt(minTime, maxTime), {
                            y1: h - minY,
                            ease: Power2.easeInOut
                    })
            Curve5y2 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve5y2
                    .to(curve5, getRandomInt(minTime, maxTime), {
                            y2: minY - (varY / 2),
                            ease: Power2.easeInOut
                    })
            Curve5y3 = new TimelineMax({
                    paused: false,
                    yoyo: true,
                    delay: getRandomInt(minDelay, maxDelay),
                    repeat: -1
            });
            Curve5y3
                    .to(curve5, getRandomInt(minTime, maxTime), {
                            y3: h - minY,
                            ease: Power2.easeInOut
                    });

            Curve5TL
                    .add(Curve5y1, "start")
                    .add(Curve5y2, "start")
                    .add(Curve5y3, "start")

            MainTL
                    .add(Curve1TL, "MainStart")
                    .add(Curve2TL, "MainStart")
                    .add(Curve3TL, "MainStart")
                    .add(Curve4TL, "MainStart")
                    .add(Curve4TL, "MainStart")
    }

    function drawCurve(ctx, ptsa, tension, isClosed, numOfSegments, showPoints) {

        showPoints  = showPoints ? showPoints : false;

        ctx.beginPath();

        drawLines(ctx, getCurvePoints(ptsa, tension, isClosed, numOfSegments));

            ctx.stroke();
        ctx.closePath();

        if (showPoints) {
            ctx.stroke();
            ctx.beginPath();
            for(var i=0;i<pts.length-1;i+=2) 
                    ctx.rect(pts[i] - 2, pts[i+1] - 2, 4, 4);
        }
    }

    function getCurvePoints(ptsa, tension, isClosed, numOfSegments) {

        // use input value if provided, or use a default value   
        tension = (typeof tension != 'undefined') ? tension : 0.5;
        isClosed = isClosed ? isClosed : false;
        numOfSegments = numOfSegments ? numOfSegments : 16;

        var _pts = [], res = [],    // clone array
            x, y,           // our x,y coords
            t1x, t2x, t1y, t2y, // tension vectors
            c1, c2, c3, c4,     // cardinal points
            st, t, i;       // steps based on num. of segments

        // clone array so we don't change the original
        _pts = ptsa.slice(0);

        // The algorithm require a previous and next point to the actual point array.
        // Check if we will draw closed or open curve.
        // If closed, copy end points to beginning and first points to end
        // If open, duplicate first points to befinning, end points to end
        if (isClosed) {
            _pts.unshift(ptsa[ptsa.length - 1]);
            _pts.unshift(ptsa[ptsa.length - 2]);
            _pts.unshift(ptsa[ptsa.length - 1]);
            _pts.unshift(ptsa[ptsa.length - 2]);
            _pts.push(ptsa[0]);
            _pts.push(ptsa[1]);
        }
        else {
            _pts.unshift(ptsa[1]);   //copy 1. point and insert at beginning
            _pts.unshift(ptsa[0]);
            _pts.push(ptsa[ptsa.length - 2]); //copy last point and append
            _pts.push(ptsa[ptsa.length - 1]);
        }

        // ok, lets start..

        // 1. loop goes through point array
        // 2. loop goes through each segment between the 2 pts + 1e point before and after
        for (i=2; i < (_pts.length - 4); i+=2) {
            for (t=0; t <= numOfSegments; t++) {

                // calc tension vectors
                t1x = (_pts[i+2] - _pts[i-2]) * tension;
                t2x = (_pts[i+4] - _pts[i]) * tension;

                t1y = (_pts[i+3] - _pts[i-1]) * tension;
                t2y = (_pts[i+5] - _pts[i+1]) * tension;

                // calc step
                st = t / numOfSegments;

                // calc cardinals
                c1 =   2 * Math.pow(st, 3)  - 3 * Math.pow(st, 2) + 1; 
                c2 = -(2 * Math.pow(st, 3)) + 3 * Math.pow(st, 2); 
                c3 =       Math.pow(st, 3)  - 2 * Math.pow(st, 2) + st; 
                c4 =       Math.pow(st, 3)  -     Math.pow(st, 2);

                // calc x and y cords with common control vectors
                x = c1 * _pts[i]    + c2 * _pts[i+2] + c3 * t1x + c4 * t2x;
                y = c1 * _pts[i+1]  + c2 * _pts[i+3] + c3 * t1y + c4 * t2y;

                //store points in array
                res.push(x);
                res.push(y);

            }
        }

        return res;
    }

    function drawLines(ctx, pts) {
        ctx.moveTo(pts[0], pts[1]);
        for(i=2;i<pts.length-1;i+=2) ctx.lineTo(pts[i], pts[i+1]);
    }

    function pointOnLine(time, startx, midx, endx, starty, midy, endy){
        var t = time; // given example value
        var x = (1 - t) * (1 - t) * startx + 2 * (1 - t) * t * midx + t * t * endx;
        var y = (1 - t) * (1 - t) * starty + 2 * (1 - t) * t * midy + t * t * endy;

        return {xVal: x, yVal: y};
    }

    function returnPoints(time) {
            var Points = [];

            var returnVal1 = pointOnLine(time, curve1.x1, curve1.x2, curve1.x3, curve1.y1, curve1.y2, curve1.y3);
            var returnVal2 = pointOnLine(time, curve2.x1, curve2.x2, curve2.x3, curve2.y1, curve2.y2, curve2.y3);
            var returnVal3 = pointOnLine(time, curve3.x1, curve3.x2, curve3.x3, curve3.y1, curve3.y2, curve3.y3);
            var returnVal4 = pointOnLine(time, curve4.x1, curve4.x2, curve4.x3, curve4.y1, curve4.y2, curve4.y3);
            var returnVal5 = pointOnLine(time, curve5.x1, curve5.x2, curve5.x3, curve5.y1, curve5.y2, curve5.y3);

            Points = [returnVal1.xVal,returnVal1.yVal, returnVal2.xVal,returnVal2.yVal, returnVal3.xVal,returnVal3.yVal, returnVal4.xVal,returnVal4.yVal, returnVal5.xVal,returnVal5.yVal]; 

            return Points;
    }



    function createGradients() {
        alpha = 1;
        gradientArray = [];
        for (k=0; k < numberOfCurves; k++) {
                alpha -= 0.019;
                yellow = 'hsla(45, 100%, 60%, '+ alpha +')';
                red = 'hsla(11, 100%, 50%, '+ alpha +')';
                blue = 'hsla(242, 100%, 50%, '+ alpha +')';
                blueEnd = 'hsla(242, 100%, 50%, 0)';
                var gradient=$.createLinearGradient(0,0,(c.width - (minX*2)),0);
                gradient.addColorStop("0",yellowStart);
                gradient.addColorStop("0.1",yellow);
                gradient.addColorStop("0.5",red);
                gradient.addColorStop("0.9",blue);
                gradient.addColorStop("1",blueEnd);
                // Fill array with gradient
                gradientArray[k] = gradient;
            }
    }

    var animate = function() {
            clearFrame();

            $.lineWidth=2;
            $.globalAlpha = 0.4;

            CurvesArray[0] = [curve1.x1,curve1.y1, curve2.x1,curve2.y1, curve3.x1,curve3.y1, curve4.x1,curve4.y1, curve5.x1,curve5.y1];
            for (i=1; i < (numberOfCurves); i++) {
                    CurvesArray[i] = returnPoints(TimeOnCurve*i);
            }
            CurvesArray[numberOfCurves] = [curve1.x3,curve1.y3, curve2.x3,curve2.y3, curve3.x3,curve3.y3, curve4.x3,curve4.y3, curve5.x3,curve5.y3];

            for (j=0; j < CurvesArray.length; j++) {
                $.strokeStyle=gradientArray[j];
                drawCurve($, CurvesArray[j], tension);
            }

            window.requestAnimFrame(animate);
    }
    ready();
    tweenCurves();
    animate();

我使用以下代码在画布上绘图,但是我有滞后问题。代码在Chrome和Firefox中很多,但是Edge中的动画很流畅。可能导致这个问题的原因是什么?

0 个答案:

没有答案