JavaScript跳过为饼图数组添加值的函数

JavaScript跳过为饼图数组添加值的函数,javascript,jquery,asynchronous,html5-canvas,setinterval,Javascript,Jquery,Asynchronous,Html5 Canvas,Setinterval,我正在使用.arc()和setInterval()创建一个动画饼图。让piechart设置动画并不是一个问题。阻碍我的问题是,当我为饼图的每个切片设置动画时,当切片完成动画时,其开始值和结束值应该输入到数组中。但是,无论出于何种原因,代码只在第三个实例上开始工作(即将值保存到数组)。这会导致前两个馅饼片合并成一个大的馅饼片,并导致馅饼的颜色变得一团糟。我认为(实际上仍然认为)问题在于我的函数是异步的,但我尝试过的一切,比如使用jquery when().then(),或者将函数嵌入回调函数都不起

我正在使用.arc()和setInterval()创建一个动画饼图。让piechart设置动画并不是一个问题。阻碍我的问题是,当我为饼图的每个切片设置动画时,当切片完成动画时,其开始值和结束值应该输入到数组中。但是,无论出于何种原因,代码只在第三个实例上开始工作(即将值保存到数组)。这会导致前两个馅饼片合并成一个大的馅饼片,并导致馅饼的颜色变得一团糟。我认为(实际上仍然认为)问题在于我的函数是异步的,但我尝试过的一切,比如使用jquery when().then(),或者将函数嵌入回调函数都不起作用

例如:

function1(param1, function(){ function2(); } ); 
以下是主要的功能-有争议的数组是slicesStart[]和slicesEnd[]

//draws the Pie Slice
function drawSlice1(startAngle, endAngle, color) {
    ctx.beginPath();  // starts arc
    ctx.arc(107, 107, 75, startAngle, endAngle); //positions arc on canvas with x,y values, followed by radius, start angle, and end angle
    ctx.lineWidth = 50; // line width
    ctx.strokeStyle = color; //line color
    ctx.stroke(); //fills the arc's width with said width/color
}



//draws the main pie
function drawPie(radius, color) {
    ctx.beginPath();
    ctx.arc(107, 107, radius, 0, 2 * Math.PI);
    ctx.lineWidth = 50;
    ctx.strokeStyle = color;
    ctx.stroke();
}



//draws the base pie (the white border and shadow)
function drawBasePie(radius, color){
    ctx.beginPath();
    ctx.arc(107, 107, radius, 0, 2 * Math.PI);
    ctx.lineWidth = 54;
    ctx.shadowBlur=2; //Sets shadow length
    ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'; // Sets the shadow color
    ctx.strokeStyle = color;
    ctx.stroke();
}



//draws each sliver of a pie slice one by one.  Combined with setInterval() this creates an animation
function drawPieSlice(pievalue, slicecolor, startAngle, numberSlice) {  

    if(typeof pievalue != 'undefined') {    

        if (counter == (pievalue + 1)) {

            startValue = currentEndAngle;

            counter++;


            sStart = startAngle;

            sEnd = currentEndAngle;

            //slicesStart[numberSlice] = startAngle;

            //slicesEnd[numberSlice] = currentEndAngle;

            //document.getElementById(numberSlice).innerHTML = "Slice" + numberSlice + " startangle=" + slicesStart[numberSlice] + " and endangle=" + slicesEnd[numberSlice];




        } else if (counter > (pievalue + 1)) {

            //do nothing, thus ending the setInterval() loop

        } else {

            var beginAngle = startAngle * Math.PI;
            var endAngle = (currentEndAngle) * Math.PI;

            currentEndAngle = currentEndAngle + 0.01;

            var counterClockwise = false;

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

            //draw the base pie, which gives the white border with shadow effect (see bottom of script for function)
            drawBasePie(75, "white");

            //draw the main pie, which uses the "No Category" color as it's base (see bottom of script for function)
            drawPie(75, "#DDDDDD");

            for(var i=1; i<=8; i++){

                if(slicesStart[i] != 1000) {    

                    bangle = slicesStart[i] * Math.PI;

                    eangle = slicesEnd[i] * Math.PI;

                    zed = i - 1;

                    drawSlice1(bangle, eangle, colors[zed]);

                }

            }

            drawSlice1(beginAngle, endAngle, slicecolor);



        }

        counter++;

    }

}   



//function that causes each slice to animate
function sliceWrite(a,b){

    //check if slice value is zero
    if(pievalues[a] == 0) {
        //if 0 do nothing
    } else {
        //set counter to zero for each insance of the drawPieSlice() function
        counter = 0;

        //fire drawPieSlice function including the pievalue(how big it is), the color, and where it starts on the arc 
        pieslice[a] = setInterval(function() { drawPieSlice(pievalues[a], b, startValue, a); }, 15);

        //these are the start and end values of each slice of the pie.  At the end of drawPieSlice() the start and end values are entered into these two arrays.  The next time drawPieSlice() is run, it checks these arrays and if they hold values, draws the previous slice[s].
        slicesStart[a] = sStart;        
        slicesEnd[a] = sEnd;

        document.getElementById('1').innerHTML += "Slice" + a + " startangle = " + slicesStart[a] + " and endangle = " + slicesEnd[a] + " and color = " + colors[a] + "<br><br>";

    }   

}



function animatePie(){

    //the following acts as a for() statement, but with a delay before each instance is run (the delay amount for each instance is stored in the times[] array).
    var x = 1;

    function sliceOrder() {
       setTimeout(function () {
          sliceWrite(x,colors[x]);            
          x++;
          if (x <= 8) {
             sliceOrder();
          }                        
       }, times[x])
    }

    sliceOrder()

}

animatePie();
//绘制饼图切片
函数drawSlice1(星形、端角、颜色){
ctx.beginPath();//启动arc
ctx.arc(107、107、75、startAngle、endAngle);//使用x、y值在画布上定位圆弧,后跟半径、起始角度和结束角度
ctx.lineWidth=50;//线宽
ctx.strokeStyle=color;//线条颜色
ctx.stroke();//用所述宽度/颜色填充弧的宽度
}
//画主饼
函数drawPie(半径、颜色){
ctx.beginPath();
弧(107,107,半径,0,2*Math.PI);
ctx.lineWidth=50;
ctx.strokeStyle=颜色;
ctx.stroke();
}
//绘制基础饼图(白色边框和阴影)
函数(半径、颜色){
ctx.beginPath();
弧(107,107,半径,0,2*Math.PI);
ctx.lineWidth=54;
ctx.shadowBlur=2;//设置阴影长度
ctx.shadowColor='rgba(0,0,0,0.3)';//设置阴影颜色
ctx.strokeStyle=颜色;
ctx.stroke();
}
//逐个绘制饼图切片的每一条。与setInterval()结合使用可创建动画
函数drawPieSlice(pievalue、slicecolor、startAngle、numberSlice){
if(typeof值!=“未定义”){
如果(计数器==(值+1)){
开始值=当前结束角;
计数器++;
sStart=startAngle;
sEnd=currentEndAngle;
//切片开始[numberSlice]=startAngle;
//slicesEnd[numberSlice]=currentEndAngle;
//document.getElementById(numberSlice).innerHTML=“切片”+numberSlice+“startangle=“+slicessstart[numberSlice]+”和endangle=“+slicesEnd[numberSlice]”;
}否则如果(计数器>(值+1)){
//不执行任何操作,从而结束setInterval()循环
}否则{
var beginAngle=startAngle*Math.PI;
var endAngle=(currentEndAngle)*Math.PI;
currentEndAngle=currentEndAngle+0.01;
var逆时针=假;
clearRect(0,0,canvas.width,canvas.height);
//绘制基础饼图,该饼图给出带有阴影效果的白色边框(有关函数,请参见脚本底部)
德拉塞皮(75,“白色”);
//绘制主饼图,该饼图使用“无类别”颜色作为其基础(有关函数,请参见脚本底部)
拉比(75,“#DDDDDD”);

对于(var i=1;i不要难过,但这并没有什么神秘之处。这是一个非常简单、非常糟糕的编程

如果使用setInterval和setTimeout asynchron,则应在setInterval(计数器>20)查找时启动新的setTimeout,如果在setInterval查找之前启动新的setTimeout,则全局变量将显示错误的操作值

你还写道: 您应该注意到,在柱状图下,它表示切片1和切片2的起点和终点角度为0

这也不神秘,因为在将值写入dom时,它们是0

我认为您应该重新编写代码,并在思考中加入更多的结构。

var ctx=PieChart.getContext(“2d”);
var ctx=PieChart.getContext("2d");

//***********************************************************
//-------------------------------------- your drawing methods
//***********************************************************
//draws the Pie Slice
function drawSlice(startAngle, endAngle, color) 
    {
    ctx.beginPath();  // starts arc
    ctx.arc(107, 107, 75, startAngle, endAngle); //positions arc on canvas with x,y values, followed by radius, start angle, and end angle
    ctx.lineWidth = 50; // line width
    ctx.strokeStyle = color; //line color
    ctx.stroke(); //fills the arc's width with said width/color
    }

 //draws the main pie
function drawPie(radius, color) 
    {
    ctx.beginPath();
    ctx.arc(107, 107, radius, 0, 2 * Math.PI);
    ctx.lineWidth = 50;
    ctx.strokeStyle = color;
    ctx.stroke();
    }

//draws the base pie (the white border and shadow)
function drawBasePie(radius, color)
    {
    ctx.beginPath();
    ctx.arc(107, 107, radius, 0, 2 * Math.PI);
    ctx.lineWidth = 54;
    ctx.shadowBlur=2; //Sets shadow length
    ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'; // Sets the shadow color
    ctx.strokeStyle = color;
    ctx.stroke();
    }

//***********************************************************
//-------------------------------------- your drawing methods -- END
//***********************************************************

//************************************************************
//-------------------------------------- Class slice Animation
//************************************************************

//-------- constructor
function sliceAnimation (startAngle, endAngle, color, time, frequency)
    {
    this.startAngle=startAngle;                            //-- start angle
    this.endAngle=endAngle;                                //-- end angle
    this.color=color;                                                                //-- color
    this.currentAngle=startAngle                           //-- current angle
    this.RFPS=(endAngle-startAngle)*1000/(frequency*time); //-- rad forward per step
    this.frequency=frequency                               //-- frequency
    this.timer=null;                                       //-- timer pointer
    this.callback=null;                                    //-- call back method
    this.callback_context=window;                                                    //-- the context of the call back action - where this should point to
    }

//-----------------------------------------------------
//-------- prototype
//-----------------------------------------------------
sliceAnimation.prototype.start=function ()
    {
    this.timer=setInterval (this.ACTION.bind(this),1/this.frequency*1000);    //-- setting the timer and binding slice Animation instance to the ACTION method, because the context of every setInterval or setTimeout call is window and not the instance of this class
    }

 sliceAnimation.prototype.ACTION=function ()
    {
    var currentAngle=this.currentAngle, endAngle=this.endAngle;               //-- quicker references
    var complete=false;
    currentAngle+=this.RFPS;                                                  //-- calculating the currentAngle
    if (currentAngle>endAngle)                                                //-- if endangle reached, clear the interval , set the currentAngle to the exact endAngle, and set complete to true
        {
        currentAngle=endAngle;
        clearInterval(this.timer);
        drawSlice (this.startAngle, currentAngle, this.color);
        complete=true;
        }
    drawSlice (this.startAngle, currentAngle, this.color);                                    //-- draws the slice
    this.currentAngle=currentAngle;                                           //-- sets the currentAngle in the instance
    if (complete && this.callback) this.callback.call (this.callback_context);//-- calls back if the endangle is reached under the callback context
    }
 //-----------------------------------------------------
 //-------- prototype -- END
 //-----------------------------------------------------
//************************************************************
//-------------------------------------- Class slice Animation
//************************************************************


//-- class pieSlice
function pieSlice (startAngle, endAngle, color, time)
    {
    this.startAngle=startAngle; 
    this.endAngle=endAngle;           //-- start angle
    this.color=color;                 //-- slice color
    this.time=time;                   //-- time it takes to animate in ms
    }

 //-- setting the 8 slices
var RF=Math.PI/4;                   //-- rad forward per slice
var CP=0;                           //-- currentPosition
var slices=new Array (
    new pieSlice (CP,CP+=RF, "green",      1000),   //-- startAngle, endAngle, color, time in ms
    new pieSlice (CP,CP+=RF, "blue",       1000),
    new pieSlice (CP,CP+=RF, "red",        1000),
    new pieSlice (CP,CP+=RF, "yellow",     1000),
    new pieSlice (CP,CP+=RF, "lightgreen", 1000),
    new pieSlice (CP,CP+=RF, "purple",     1000),
    new pieSlice (CP,CP+=RF, "brown",      1000),
    new pieSlice (CP,CP+=RF, "grey",       1000));


 function pieAnimation (frequency, delay, slices)
     {
     this.slices=slices;
     this.slicesL=slices.length;
     this.sliceCounter=0;
     this.frequency=frequency;
     this.delay=delay;
     }

 pieAnimation.prototype.start=function ()
    {
    ctx.clearRect (0,0,215,215);        //-- clears the area
    drawBasePie (75,"lightgrey");   //-- draws your backgrounds
    drawPie (75, "#DDDDDD");
    this.ACTION (); 
    }

 pieAnimation.prototype.ACTION=function ()
     {
     var slice, animation;

   if (this.sliceCounter<this.slicesL)   //--- going through all slices
        {
          slice=slices[this.sliceCounter];
          animation=new sliceAnimation (slice.startAngle, slice.endAngle, slice.color, slice.time, this.frequency);  // setting a new slice Animation
          animation.callback=this.ACTION;                                                                            // setting the callback of the sliceAnimation which is this function (instance.ACTION)
          animation.callback_context=this;                                                                           // setting the context to the instance of pieAnimation
          this.sliceCounter++;                                                                                       // increase the sliceCounter
          setTimeout (animation.start.bind (animation), this.delay);                                                 // starts the sliceAnimation
          }
    }

 var animation=new pieAnimation (25,20, slices);                                                                //instance of pieAnimation
 animation.start ();                                                                                            //starts the animation
//*********************************************************** //--------------------------------------你的绘画方法 //*********************************************************** //绘制饼图切片 函数drawSlice(星形、端角、颜色) { ctx.beginPath();//启动arc ctx.arc(107、107、75、startAngle、endAngle);//使用x、y值在画布上定位圆弧,后跟半径、起始角度和结束角度 ctx.lineWidth=50;//线宽 ctx.strokeStyle=color;//线条颜色 ctx.stroke();//用所述宽度/颜色填充弧的宽度 } //画主饼 函数drawPie(半径、颜色) { ctx.beginPath(); 弧(107,107,半径,0,2*Math.PI); ctx.lineWidth=50; ctx.strokeStyle=颜色; ctx.stroke(); } //绘制基础饼图(白色边框和阴影) 函数(半径、颜色) { ctx.beginPath(); 弧(107,107,半径,0,2*Math.PI); ctx.lineWidth=54; ctx.shadowBlur=2;//设置阴影长度 ctx.shadowColor='rgba(0,0,0,0.3)';//设置阴影颜色 ctx.strokeStyle=颜色; ctx.stroke(); } //*********************************************************** //--------------------------------------您的绘图方法--结束 //*********************************************************** //************************************************************ //--------------------------------------类切片动画 //************************************************************ //--------建造师 函数切片动画(startAngle、endAngle、颜色、时间、频率) { 这个.startAngle=startAngle;//--起始角度 此.endAngle=endAngle;/--结束角度 this.color=color;/--color 此.currentAngle=startAngle/--当前角度 此.RFPS=(端角星形缠绕)*1000/(频率*时间);