Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
绘制和删除圆弧-使用JavaScript或CSS绘制圆弧动画_Javascript_Css_Canvas_Svg_Html5 Canvas - Fatal编程技术网

绘制和删除圆弧-使用JavaScript或CSS绘制圆弧动画

绘制和删除圆弧-使用JavaScript或CSS绘制圆弧动画,javascript,css,canvas,svg,html5-canvas,Javascript,Css,Canvas,Svg,Html5 Canvas,我有一个例子,我想画3条弧线,然后把它们擦掉 首先,应逐步绘制弧CA,然后逐步擦除弧CA。然后绘制并擦除弧AB,然后绘制并擦除弧BC。然后重复 我的方法: 使用画布和JS: 我从canvas开始,但是抗锯齿在这里不起作用。所以我觉得SVG可能会更好 var currentEndAngle=0; var currentStartAngle=0; var currentColor='黑色'; var-lineRadius=300; var线宽=5; 设置间隔(绘制,5); 函数draw(){ v

我有一个例子,我想画3条弧线,然后把它们擦掉

首先,应逐步绘制弧CA,然后逐步擦除弧CA。然后绘制并擦除弧AB,然后绘制并擦除弧BC。然后重复

我的方法:

使用画布和JS:

我从canvas开始,但是抗锯齿在这里不起作用。所以我觉得SVG可能会更好

var currentEndAngle=0;
var currentStartAngle=0;
var currentColor='黑色';
var-lineRadius=300;
var线宽=5;
设置间隔(绘制,5);
函数draw(){
var can=document.getElementById('canvas1');//获取画布
var canvas=document.getElementById(“canvas1”);
var context=canvas.getContext(“2d”);
var x=画布宽度/2;
变量y=画布高度/2;
变异半径;
var宽度;
var startAngle=currentStartAngle*Math.PI;
var endAngle=(currentEndAngle)*Math.PI;
currentStartAngle=currentEndAngle-0.01;
currentEndAngle=currentEndAngle+0.01;
if(数学楼层(当前StarTangle/2)%2){
currentColor=“白色”;
半径=线半径-1;
宽度=线宽+3;
}否则{
currentColor=“黑色”;
半径=线半径;
宽度=线宽;
}
var逆时针=假;
context.beginPath();
弧(x,y,半径,星形,端角,逆时针);
context.lineWidth=宽度;
//线条颜色
context.strokeStyle=currentColor;
stroke();
/************************************************/
}
正文{
文本对齐:居中;
背景:蓝色;
} 
#游说{
宽度:500px;
高度:500px;
保证金:0自动;
}

您实际上不想修改
笔划dashoffset
,因为这只会使虚线图案围绕圆圈移动

无论如何,您都必须修改虚线阵列值,因此您可以通过设置虚线阵列中的值的动画来完成这一切

你的圆的半径是40,所以周长是251.33。这意味着三条弧的长度都是83.78

对于这三个阶段中的每一个阶段,我们将破折号的“开”部分从0增加到83.78。然后我们再次缩小差距,同时将之前的差距从83.78扩大到167.55。这是因为尾巴会被推到末端

这适用于前两个步骤,但由于破折号模式在3点钟位置开始和结束(并且没有穿过该点),我们必须在开始时使用额外的空破折号对来完成最后一个阶段的尾部推送。我们将差距从0扩大到83.78

圆圈{
填充:透明;
笔画:黑色;
笔画宽度:2;
动画:旋转5s线性无限;
}
@关键帧旋转{
0%{数组:0 0 83.78 0 83.78 0 83.78;}
16.7%{数组:0 0 83.78 83.78 0 83.78;}
33.3%{数组:0 0 167.55 0 0 83.78;}
50%{数组:0 0 0 83.78 0 83.78 83.78 0;}
66.6%{数组:0 0 83.78 0 167.55 0;}
83.3%{数组:0 0 83.78 0 83.78 0 83.78;}
100%{stroke dasharray:083.78083.78083.78;}
}

对于画布版本,如注释中所述,抗锯齿问题在于在同一像素上反复重画

为了避免这种情况,请清除每一帧的整个画布并重新绘制所有内容


对于所请求的动画,必须同时存储开始角度和结束角度。然后一个接一个地递增,当超过分区大小阈值时进行切换

这里有一个带注释的片段,我希望它能让事情变得更清楚

//设置
var分区=3;
var持续时间=3000;//在ms中
var canvas=document.getElementById(“canvas1”);
var context=canvas.getContext(“2d”);
var x=画布宽度/2;
变量y=画布高度/2;
变量半径=(画布宽度/7)*2;
context.lineWidth=4;
//初始化
var currentSplit=0;
var splitAngle=(Math.PI*2)/divisions;
var splitTime=(持续时间/(分段*2));//每端每分裂多少时间
变量角度=[0,0];//在这里,我们存储开始和结束角度
无功电流=0;
var startTime=performance.now();
draw();
函数绘制(当前时间){
//首先将经过的时间转换为角度
var timedAngle=((当前时间-开始时间)/拆分时间)*拆分角度;
//将当前端设置为该定时角度+圆上的当前位置
角度[当前]=时间悬挂+(拆分角度*当前拆分);
如果(timedAngle>=splitAngle){//为此端执行一次拆分
//它不应超过阈值
角度[当前]=(拆分角度*(当前拆分+1));
current=+(!current)//切换应该移动哪一端
startTime=currentTime;//重置计时器
如果(!current){//我们回到起点
currentSplit=(currentSplit+1)%divisions;//增加拆分索引
}
}
如果(angles[1]>Math.PI*2){//我们完成了一次完整的旋转
角度[0]=角度[1]=当前值=0;//重置所有内容
}
//每一帧我们都会清除一切
clearRect(0,0,canvas.width,canvas.height);
//重新绘制
context.beginPath();
弧(x,y,半径,角度[0],角度[1],真);
stroke();
requestAnimationFrame(draw);//以屏幕刷新率循环
}
正文{
文本对齐:居中;
}
#游说{
宽度:250px;
高度:150像素;
}
Javascript扩展HTML
<div class="segmentedProgress"></div>
<!-- showing defaults as above element will be setup -->
<div class="segmentedProgress" 
      data-angle-steps = 3      <!-- number of segments. (integers only) -->
      data-speed = 1000         <!-- Time per segment in ms -->
      data-easing = "1.2"       <!-- easing power -->
      data-line-width = "0.1"   <!-- as fraction of radius -->
      data-radial-size = "0.33" <!-- as fraction of shortest dimension -->
      data-color = "black"      <!-- colour of line -->
></div>
document.addEventListener("load", function(){
    var elements = [...document.body.querySelectorAll(".segmentedProgress")];
    if(elements.length === 0){  // exit if nothing found
        return;
    }
    // singleton to isolate from onload 
    (function(){
        const error = 0.01; // Math too perfect causes zero len arc to draw nothing. Error makes sure there is always some length in the drawn arc
        const items = [];  // array of progress items

        // each progress item defaults
        var defaults = {
            angleSteps : 3,  // number of segments. (integers only)
            speed : 1000,  // Time per segment in ms
            easing : 1.2, // easing power where 1 = no easing 2 = normal quadratic easing 1/2= inverse quadratic easing
            lineWidth : 0.1, // as fraction of radius
            radialSize : 0.33,// as fraction of shortest dimension
            color : "black",  // colour of line
            complete : false, // not used
            resize () { // resize the canvas and set size dependent vars
                this.bounds = this.element.getBoundingClientRect();
                this.w = this.canvas.width = this.bounds.width;
                this.h = this.canvas.height = this.bounds.height;
                this.canvas.style.top = (this.bounds.top + scrollY) + "px";  
                this.canvas.style.left = (this.bounds.left + scrollX) + "px";
                this.pos = { x : this.w / 2, y : this.h / 2}; // position of circle 
                this.radius = Math.min(this.w, this.h) * this.radialSize;    // radius of circle

                // set canvas state constants
                this.ctx.lineCap = "round";    
            },    
            update (time) { // updates and renders
                var segStart, segProgress, pp, ctx, ang;

                ctx = this.ctx; // alias to this.ctx

                // clear the canvas
                ctx.clearRect(0, 0, this.w, this.h);

                // get current selment angle
                ang = Math.PI * 2 / this.angleSteps, // Radians per segment

                // set the time at the correct speed
                time /= this.speed;

                // get the segment start position in radians
                segStart = Math.floor(time % this.angleSteps) * ang;

                // get the unit progress of this stage doubled for grow and shrink stages
                var segProgress = (time % 1) * 2;
                var pp = segProgress % 1;  // pp partial progress
                pp = (pp ** this.easing) / ((pp ** this.easing) + (1 - pp) ** this.easing); // add some easing

                ctx.beginPath();

                // first half of progress is growth
                if(segProgress <= 1){
                    ctx.arc(this.pos.x, this.pos.y, this.radius, segStart, segStart + pp * ang + error);
                }else{
                    // second half of progress is shrink
                    ctx.arc(this.pos.x, this.pos.y, this.radius, segStart + pp * ang - error, segStart + ang);
                }
                ctx.strokeStyle = this.color;
                ctx.lineWidth  = this.radius * this.lineWidth;
                ctx.stroke();   
            }
        }

        // create prgress item for each found element
        elements.forEach(element => {
            var pItem = {...defaults}; // progress item
            pItem.element = element;
            // get any element setting that overwrite the defaults
            Object.keys(defaults).forEach(key => {
                if(typeof defaults[key] !== "function"){
                    if(element.dataset[key] !== undefined){
                        pItem[key] = element.dataset[key];
                        if(! isNaN(element.dataset[key])){
                            pItem[key] = Number(pItem[key]);
                        }
                    }
                }
            });
            pItem.canvas = document.createElement("canvas");
            pItem.ctx = pItem.canvas.getContext("2d");
            pItem.canvas.style.position = "absolute";
            pItem.resize();
            items.push(pItem);
            element.appendChild(pItem.canvas);
        });
        elements.length = 0; // let go of elements

        // change size on resize
        window.addEventListener("resize", () =>{
            items.forEach(pItem => pItem.resize());
        });

        // start the animation
        requestAnimationFrame(update);    

        // main update loop
        function update (time) {
            items.forEach(pItem => {
                pItem.update(time);
            });
            requestAnimationFrame(update);                
        }
    }());
}());