Circliful jquery 插件的基于滚动的动画问题

Scroll based animation issue for Circliful jquery plugin

我正在使用一个名为 'Circliful' 的插件根据百分比为半圆制作动画。动画效果很好。我想在屏幕向下滚动到动画点后触发动画。我试过的 HTML 代码如下所示:

<!doctype html>

<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="js/jquery.circliful.js"></script>

<style>
.one {background:black; height:300px; color:white;}
.two {background:green; height:300px; color:white;}

</style>

</head>
<body>
<div class="one">300px Height</div>
<div class="two">300px Height</div>
<div class="one">300px Height</div>

<div id="myStathalf1" data-dimension="250" data-width="30" data-fontsize="38" data-percent="95" data-fgcolor="#fab702" data-bgcolor="#eee" data-type="half" data-icon="fa-task"></div>
<div id="myStathalf2" data-dimension="250" data-width="30" data-fontsize="38" data-percent="90" data-fgcolor="#fab702" data-bgcolor="#eee" data-type="half" data-icon="fa-task"></div>

<script>

$(document).ready (function (){
    $(window).scroll(function(){
        var y=$(this).scrollTop();
        if(y>=100) {                
            $('#myStathalf1').circliful();  
            $('#myStathalf2').circliful();  
        }
    }); 


})
</script>
</body>
</html>

插件代码如下:

"use strict";

(function ($) {

    $.fn.circliful = function (options, callback) {

        var settings = $.extend({
            // These are the defaults.
            startdegree: 0,
            fgcolor: "#000000",
            bgcolor: "#eee",
            fill: false,
            width: 15,
            dimension: 200,
            fontsize: 15,
            percent: 50,
            animationstep: 0.5,
            iconsize: '20px',
            iconcolor: '#999',
            border: 'default',
            complete: null,
            bordersize: 10
        }, options);

        return this.each(function () {

            var customSettings = ["fgcolor", "bgcolor", "fill", "width", "dimension", "fontsize", "animationstep", "endPercent", "icon", "iconcolor", "iconsize", "border", "startdegree", "bordersize"];

            var customSettingsObj = {};
            var icon = '';
            var percent;
            var endPercent = 0;
            var obj = $(this);
            var fill = false;
            var text, info;

            obj.addClass('circliful');

            checkDataAttributes(obj);


                if (obj.data('type') != undefined) {
                    type = $(this).data('type');

                    if (type == 'half') {
                        addCircleText(obj, 'circle-text-half', (customSettingsObj.dimension / 1.45));
                    }
                }  
                if ($(this).data("percent") != undefined) {
                    percent = $(this).data("percent") / 100;
                    endPercent = $(this).data("percent");
                } else {
                    percent = settings.percent / 100;
                }

            var size = customSettingsObj.dimension,
                canvas = $('<canvas></canvas>').attr({
                    width: size,
                    height: size
                }).appendTo($(this)).get(0);

            var context = canvas.getContext('2d');

            var container = $(canvas).parent();
            var x = size / 2;
            var y = size / 2;
            var degrees = customSettingsObj.percent * 360.0;
            var radians = degrees * (Math.PI / 180);
            var radius = size / 2.5;
            var startAngle = 2.3 * Math.PI;
            var endAngle = 0;
            var counterClockwise = true;
            var curPerc = customSettingsObj.animationstep === 0.0 ? endPercent : 0.0;
            var curStep = Math.max(customSettingsObj.animationstep, 0.0);
            var circ = Math.PI * 2;
            var quart = Math.PI / 2;
            var type = '';
            var fireCallback = true;
            if ($(this).data('type') != undefined) {
                type = $(this).data('type');

                if (type == 'half') {
                    startAngle = 2.0 * Math.PI;
                    endAngle = 3.13;
                    circ = Math.PI;
                    quart = Math.PI / 0.996;
                }
            }


            /**
             * adds text to circle
             *
             * @param obj
             * @param cssClass
             * @param lineHeight
             */
            function addCircleText(obj, cssClass, lineHeight) {
                $("<span></span>")
                    .appendTo(obj)
                    .addClass(cssClass)
                    .html(text)
                    .prepend(icon)
                    .css({
                        'line-height': lineHeight + 'px',
                        'font-size': customSettingsObj.fontsize + 'px'
                    });
            }


            /**
             * checks which data attributes are defined
             * @param obj
             */
            function checkDataAttributes(obj) {
                $.each(customSettings, function (index, attribute) {
                    if (obj.data(attribute) != undefined) {
                        customSettingsObj[attribute] = obj.data(attribute);
                    } else {
                        customSettingsObj[attribute] = $(settings).attr(attribute);
                    }

                    if (attribute == 'fill' && obj.data('fill') != undefined) {
                        fill = true;
                    }
                });
            }

            /**
             * animate foreground circle
             * @param current
             */
            function animate(current) {

                context.clearRect(0, 0, canvas.width, canvas.height);

                context.beginPath();
                context.arc(x, y, radius, endAngle, startAngle, false);

                context.lineWidth = customSettingsObj.width + 1;

                context.strokeStyle = customSettingsObj.bgcolor;
                context.stroke();

                context.beginPath();
                context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);

                context.strokeStyle = customSettingsObj.fgcolor;
                context.stroke();               

                if (curPerc < endPercent) {
                    curPerc += curStep;
                    requestAnimationFrame(function () {

                        animate(Math.min(curPerc, endPercent) / 100);
                    }, obj);
                }
            }

            animate(curPerc / 100);

        });
    };
}(jQuery));

这形成了一种无限循环,一直循环直到我滚动并且我明白了其中的原因。 我通过更改插件本身的代码尝试了其他方法,但似乎没有任何效果。

我希望默认出现半圆的灰色背景色,滚动一些像素到达点后开始前景色(橙色)动画。 有谁可以帮助我吗?

好的。

所以我认为你可以做的是添加一个简单的布尔标志,比如名称为 hasCreatedObjects,最初设置为 false,但一旦时机成熟,你就可以设置它true 并使用此布尔值 而不是 添加任何进一步的 circliful() 对象。

jsFiddle中可以找到here和JavaScript,如下:

$(document).ready(function () {
    var hasCreatedObjects = false;
    $(window).scroll(function () {
        var y = $(this).scrollTop();
        if (y >= 100) {
            if (!hasCreatedObjects) {
                hasCreatedObjects = true;
                $('#myStathalf1').circliful();
                $('#myStathalf2').circliful();
            }
        }
    });
});