RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 969213
Accepted
corocoto
corocoto
Asked:2020-04-13 21:32:59 +0000 UTC2020-04-13 21:32:59 +0000 UTC 2020-04-13 21:32:59 +0000 UTC

过渡到画布

  • 772

是否可以在动画期间向画布中的元素添加过渡?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Speedometer</title>
    <link rel="stylesheet" href="../css/common.css">
    <style>
        *{
            background: #fff;
            font-family: 'SF Pro Display',sans-serif!important;
            margin: 0;
            padding: 0;
        }
        .container{
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            position: relative;
        }
        .data_about_load{
            position: relative;
            top: -60px;
            opacity: 0;
        }
        .data_about_load:before{
            content: "";
            display: inline-block;
            width: 20px;
            height: 20px;
            background: url(../img/svg/add/check_green.svg) center no-repeat;
            background-size: contain;
            position: relative;
            top: 4px;
            margin-right: 12px;
        }
        #canvas{
            opacity: 0;
        }
        .data{
            font-size: 16px;
            font-weight: 600;
            color: #0a0a0a;
        }
        .bold_time{
            font-weight: 700;
        }

        /*animations*/
        .fade-in-left {
            animation: fade-in-left 0.6s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
        }
        .slide-in-fwd-center {
            animation: slide-in-fwd-center 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
        }
        @keyframes fade-in-left {
            0% {
                transform: translateX(-50px);
                opacity: 0;
            }
            100% {
                transform: translateX(0);
                opacity: 1;
            }
        }
        @keyframes slide-in-fwd-center {
            0% {
                transform: translateZ(-1400px);
                opacity: 0;
            }
            100% {
                transform: translateZ(0);
                opacity: 1;
            }
        }
    </style>
</head>
<body>
<div class="container">
    <canvas id="canvas" width="500" height="500"></canvas>
    <div class="data_about_load"><span class="data">Время загрузки <span class="bold_time">0.1 сек</span></span></div>
</div>
<script>
    const canvas = document.getElementById("canvas"),
        ctx = canvas.getContext("2d"),

        counterClockwise = false,
        proportions={
            general: {
                // general settings
                middleX : canvas.width / 2,
                middleY : canvas.height / 2,
                radius : 240,
            },
            ticks: {
                //ticks settings
                tickOffsetFromArc : canvas.width / 40,
            },
            digits: {
                digitsOffsetFromArc : canvas.width / 15,
            },
            indicator: {
                quarterY: (canvas.height / 2)/1.7
            }
        },
        colorPalette= {
            // ticks palette
            ticks: {
                red: {
                    redTickColor: "#FF0000"
                },
                yellow: {
                    darkYellowTickColor: "#F9AF00"
                },
                green: {
                    greenTickColor: "#13B74B",
                    whiteFillColor: "#FFF",
                    greenShadowColor: "#a8bbaa"
                }
            },
            //arrow color
            arrow: {
                bgBlue: "#3970eb",
                shadowColor: "rgba(66,115,247,0.5)"
            },
            //text color
            text: "#0a0a0a",
            diagram:{
                bg :{
                    gradient:[
                    "#e0f6e8",
                    "#deede4"
                    ],
                    lines: "#ecedec"
                }
            }
        },
        fonts={
            digitsFont: "bold 20px SF Pro Display",
            indicator: "600 80px SF Pro Display",
            diagramFont: "bold 10px SF Pro Display"
        },

        // numbers setting
        digits = [0, 20, 40, 50, 60, 70, 80, 90, 100],

        //zones
        zonesCount = digits.length - 1;

    // Arrow settings
    let arrowValueIndex = -2.45,

    // beginning and ending of our arc. Sets by radius*pi
        startAngleIndex = .75,
        endAngleIndex = 2.25,
        step = (endAngleIndex - startAngleIndex) / zonesCount,
        allDataDiagram=[],
        forVisibleElem=true;

    /*draw zones*/
    let DrawZones = function () {
        const greyZonesCount = zonesCount / 1.6;
              greenZonesCount = zonesCount - greyZonesCount,
              startAngle = (startAngleIndex - 0.02) * Math.PI,
              endGreyAngle = (startAngleIndex + greyZonesCount * step) * Math.PI,
              endGreenAngle = (endAngleIndex + 0.02) * Math.PI,

              //zones' options
              sectionOptions = [
                  {
                      startAngle: startAngle,
                      endAngle: endGreyAngle,
                      color: "#e7e7e7",
                      zoneLineWidth: 2
                  },
                  {
                      startAngle: endGreyAngle,
                      endAngle: endGreenAngle,
                      color: "#13b74b",
                      zoneLineWidth: 5
                  },
              ];

        //draw zones
        this.DrawZone = function (options) {
            ctx.beginPath();
            ctx.arc(proportions.general.middleX, proportions.general.middleY, proportions.general.radius, options.startAngle, options.endAngle, counterClockwise);
            ctx.lineWidth = options.zoneLineWidth;
            ctx.strokeStyle = options.color;
            ctx.lineCap = "round";
            ctx.stroke();
        };

        sectionOptions.forEach(options => this.DrawZone(options));
    };

    /*draw dots*/
    let DrawTicks = function () {
        startAngleIndex = .73,
        endAngleIndex = 2.27,
        step = (endAngleIndex - startAngleIndex) / zonesCount;
        this.DrawTick = function (angle,count) {

            let fromX = proportions.general.middleX + (proportions.general.radius - proportions.ticks.tickOffsetFromArc) * Math.cos(angle),
                fromY = proportions.general.middleY + (proportions.general.radius - proportions.ticks.tickOffsetFromArc) * Math.sin(angle),
                toX = proportions.general.middleX + (proportions.general.radius + proportions.ticks.tickOffsetFromArc) * Math.cos(angle),
                toY = proportions.general.middleY + (proportions.general.radius + proportions.ticks.tickOffsetFromArc) * Math.sin(angle),

                centerOfDotX=(fromX+toX)/2,
                centerOfDotY=(fromY+toY)/2;
            ctx.beginPath();
            ctx.arc(centerOfDotX,centerOfDotY,6,0,Math.PI*2,true);
            if (count<6){
                switch (count) {
                    case 1:
                    case 2:
                    case 3:
                        ctx.fillStyle=colorPalette.ticks.red.redTickColor;
                        break;
                    default:
                        ctx.fillStyle=colorPalette.ticks.yellow.darkYellowTickColor;
                        break;
                }
            }else{
                ctx.fillStyle=colorPalette.ticks.green.whiteFillColor;
                ctx.strokeStyle=colorPalette.ticks.green.greenTickColor;
                ctx.shadowColor = colorPalette.ticks.green.greenShadowColor;
                ctx.shadowBlur = 15;
                ctx.shadowOffsetX = 0;
                ctx.shadowOffsetY = 0;
                ctx.stroke();
            }
            ctx.fill();
            ctx.closePath();
            ctx.shadowBlur =0;
        };
        let count=0;
        for (let i = startAngleIndex; i <= endAngleIndex; i += step) {
            let angle = i * Math.PI;
            count++;
            this.DrawTick(angle,count);
        }
    };

    //draw numbers
    let DrawDigits = function () {
        let angleIndex = startAngleIndex;

        digits.forEach(function (digit) {
            let angle = angleIndex * Math.PI,
                    x = proportions.general.middleX + (proportions.general.radius - proportions.digits.digitsOffsetFromArc) * Math.cos(angle),
                    y = proportions.general.middleY + (proportions.general.radius - proportions.digits.digitsOffsetFromArc) * Math.sin(angle);

            angleIndex += step;

            ctx.font = fonts.digitsFont;
            ctx.fillStyle = colorPalette.text;
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            ctx.fillText(digit, x, y);
        });
    };

    /*draw arrow*/
    let DrawArrow = function () {
        ctx.beginPath();
        ctx.lineCap = "round";
        ctx.moveTo(proportions.general.middleX-15, proportions.general.middleY);
        ctx.lineTo(proportions.general.middleX, proportions.general.middleY-150);
        ctx.lineTo(proportions.general.middleX+15, proportions.general.middleY);
        ctx.closePath();
        ctx.strokeStyle = colorPalette.arrow.bgBlue;
        ctx.fillStyle=colorPalette.arrow.bgBlue;
        ctx.shadowColor=colorPalette.arrow.shadowColor;
        ctx.shadowBlur = 15;
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
        ctx.stroke();
        ctx.fill();
        ctx.shadowBlur =0;
    };
    let oldText=0;
    /*draw indicator's number*/
    let DrawIndicator=function (val) {
        ctx.font = fonts.indicator;
        ctx.fillStyle = colorPalette.ticks.green.whiteFillColor; // or whatever color the background is.
        ctx.fillText(oldText, proportions.general.middleX, proportions.indicator.quarterY);
        ctx.fillStyle = colorPalette.text;
        ctx.fillText(`${val}`, proportions.general.middleX, proportions.indicator.quarterY);
        ctx.font = fonts.digitsFont;
        ctx.fillText('points',proportions.general.middleX,proportions.indicator.quarterY+proportions.general.middleY/5);
        oldText=val;
    };
    let indicatorNum=0;

    /*renderer*/
    function renderer() {
        ctx.clearRect(0,0,canvas.width,canvas.height);

        DrawZones();
        DrawTicks();
        DrawDigits();
        Diagram();
        DrawIndicator(indicatorNum);
        ctx.translate(proportions.general.middleX,proportions.general.middleY);
        ctx.rotate(arrowValueIndex);
        ctx.translate(-proportions.general.middleX,-proportions.general.middleY);

        DrawArrow();

        ctx.translate(proportions.general.middleX,proportions.general.middleY);
        ctx.rotate(-arrowValueIndex);
        ctx.translate(-proportions.general.middleX,-proportions.general.middleY);

    }

    function val(value) {
        let sector = Math.PI*0.385;
        if (value < 40)
            arrowValueIndex = value/40*sector - sector*2;
        else
            arrowValueIndex = (value-40)/60*sector*3 - sector;
        let add=(val)=>{
            indicatorNum=val;
            allDataDiagram.unshift(val);
            allDataDiagram=allDataDiagram.slice(0,186);
        };
        add(value);
        // document.querySelector('span').textContent = value;
        renderer();
    }


    //кроссбраузерный requestAnimationFrame
    let requestAnimFrame = (function(){
        return  window.requestAnimationFrame   ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            window.oRequestAnimationFrame      ||
            window.msRequestAnimationFrame     ||
            function(callback){
                window.setTimeout(callback, 1000 / 60);
            };
    })();
    let mainNum=0;
    let max=0.5, min=-0.6;

    let Engine=()=>{
        if (forVisibleElem) canvas.classList.add('slide-in-fwd-center');
        if (mainNum<70) mainNum+=.5;
        if (mainNum>=70 && mainNum<97)mainNum+=.4;
        if (mainNum>=97){
            if(forVisibleElem) mainNum+=.3;
            else mainNum+=.03;
        }
        if (mainNum>=100){
            mainNum=98.7;
            if (forVisibleElem) {
                document.querySelector(".data_about_load").classList.add("fade-in-left");
                forVisibleElem=false;
            }
        }

        val(Math.floor(mainNum));
        requestAnimFrame(Engine);
    };


let Diagram=()=>{
    this.drawLines=(x,y,width,height)=>{
        ctx.lineWidth=1.5;
        ctx.strokeStyle=colorPalette.diagram.bg.lines;
        ctx.moveTo(x,y);
        ctx.lineTo(width,height);
        ctx.stroke();
    };
    this.drawCircles = (x,y,r)=>{
        ctx.beginPath();
      ctx.arc(x,y,r,2*Math.PI,false);
      ctx.fillStyle=colorPalette.ticks.green.greenTickColor;
      ctx.fill();
        ctx.closePath();
    };
    this.writeNums = (value,x,y)=>{
        ctx.font = fonts.diagramFont;
        ctx.fillStyle = colorPalette.text;
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText(value, x, y);
    };
    this.drawD=()=>{
        // console.log(allDataDiagram);
        for (var i=0; i<=widthD; i++){
            //draw bg gradient
            ctx.fillRect(proportions.general.middleX/1.6+i, proportions.general.middleY*1.53+heightD, 1, -(allDataDiagram[i]*0.25-2));
            ctx.fillStyle=colorPalette.ticks.green.whiteFillColor;
            ctx.fillRect(proportions.general.middleX/1.6+i,proportions.general.middleY*1.53,1,4+28-allDataDiagram[i]*0.25);
            ctx.fillStyle=colorPalette.ticks.green.greenTickColor;
            ctx.fillRect(proportions.general.middleX/1.6+i,proportions.general.middleY*1.53+4+28-allDataDiagram[i]*0.25,1,2);
            ctx.fillStyle=gradientD;
        }
    };
    const widthD=186,
          heightD=32,
          gradientD=ctx.createLinearGradient(0,0,widthD/2,0);
    gradientD.addColorStop(0,colorPalette.diagram.bg.gradient[0]);
    gradientD.addColorStop(1,colorPalette.diagram.bg.gradient[0]);


    //draw grey lines
    this.drawLines(proportions.general.middleX/1.6,proportions.general.middleY*1.53,proportions.general.middleX/1.6,proportions.general.middleY*1.53+heightD);
    this.drawLines(proportions.general.middleX/1.6+widthD,proportions.general.middleY*1.53,proportions.general.middleX/1.6+widthD,proportions.general.middleY*1.53+heightD);

    //write numbers
    this.writeNums(94,proportions.general.middleX/1.6, proportions.general.middleY*1.48);
    this.writeNums(97,proportions.general.middleX/1.6+widthD, proportions.general.middleY*1.48);

    //draw diagram
    this.drawD();
    //draw circles
    this.drawCircles(proportions.general.middleX/1.6,(proportions.general.middleY*1.53)+(32-94*0.25),3);
    this.drawCircles(proportions.general.middleX/1.6+widthD,(proportions.general.middleY*1.53)+(32-97*0.25),3);
};


    window.onload=Engine;

</script>
</body>
</html>

javascript
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Stranger in the Q
    2020-04-14T18:18:57Z2020-04-14T18:18:57Z

    CSS transition不能应用于画布上的元素。


    想要得到流畅的动画,一般情况下需要根据时间获取值,而不是每帧都加固定值:

    我在您的示例中更改了一个功能:

    let delay = 2; // задержка перед анимацией
    let duration = 3; // кол во секунд анимации роста значения
    let time = new Date().getTime(); // Время начала анимации
    
    let Engine = () => {
        // кол-во секунд с начала анимации
        let t = (new Date().getTime() - time) / 1000;
        val(+getValueFromTime(t).toFixed(1));
        requestAnimFrame(Engine);
    };
    
    // получить значение спидометра в зависимости от текущего времени
    function getValueFromTime(t) {
    
        if (t < delay) // если еще не прошло время задержки
           return 0 // вернем 0
    
        t -= delay; // иначе вычитаем время задержки
    
        if (t < 0.95*duration) { // если прошло меньше 95 % времени анимации
            // переводим значение времени в значение при помощи функции сглаживания 
            // EasingFunctions.easeOutCubic (значение на входе должно быть от 0 до 1)
            return 98 * EasingFunctions.easeOutCubic(t/duration);
         }
    
         // иначе это функция от синуса от этого значения
         return 98 + Math.sin(t * 55);
    }
    

    平滑函数取自这里,更多平滑函数在这里

    <div class="container">
        <canvas id="canvas" width="500" height="500"></canvas>
        <div class="data_about_load"><span class="data">Время загрузки <span class="bold_time">0.1 сек</span></span></div>
    </div>
    <script>
    
    let EasingFunctions = {
      // no easing, no acceleration
      linear: function (t) { return t },
      // accelerating from zero velocity
      easeInQuad: function (t) { return t*t },
      // decelerating to zero velocity
      easeOutQuad: function (t) { return t*(2-t) },
      // acceleration until halfway, then deceleration
      easeInOutQuad: function (t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t },
      // accelerating from zero velocity 
      easeInCubic: function (t) { return t*t*t },
      // decelerating to zero velocity 
      easeOutCubic: function (t) { return (--t)*t*t+1 },
      // acceleration until halfway, then deceleration 
      easeInOutCubic: function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 },
      // accelerating from zero velocity 
      easeInQuart: function (t) { return t*t*t*t },
      // decelerating to zero velocity 
      easeOutQuart: function (t) { return 1-(--t)*t*t*t },
      // acceleration until halfway, then deceleration
      easeInOutQuart: function (t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t },
      // accelerating from zero velocity
      easeInQuint: function (t) { return t*t*t*t*t },
      // decelerating to zero velocity
      easeOutQuint: function (t) { return 1+(--t)*t*t*t*t },
      // acceleration until halfway, then deceleration 
      easeInOutQuint: function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t }
    };
    </script>
    
    <script>
        const canvas = document.getElementById("canvas"),
            ctx = canvas.getContext("2d"),
    
            counterClockwise = false,
            proportions={
                general: {
                    // general settings
                    middleX : canvas.width / 2,
                    middleY : canvas.height / 2,
                    radius : 240,
                },
                ticks: {
                    //ticks settings
                    tickOffsetFromArc : canvas.width / 40,
                },
                digits: {
                    digitsOffsetFromArc : canvas.width / 15,
                },
                indicator: {
                    quarterY: (canvas.height / 2)/1.7
                }
            },
            colorPalette= {
                // ticks palette
                ticks: {
                    red: {
                        redTickColor: "#FF0000"
                    },
                    yellow: {
                        darkYellowTickColor: "#F9AF00"
                    },
                    green: {
                        greenTickColor: "#13B74B",
                        whiteFillColor: "#FFF",
                        greenShadowColor: "#a8bbaa"
                    }
                },
                //arrow color
                arrow: {
                    bgBlue: "#3970eb",
                    shadowColor: "rgba(66,115,247,0.5)"
                },
                //text color
                text: "#0a0a0a",
                diagram:{
                    bg :{
                        gradient:[
                        "#e0f6e8",
                        "#deede4"
                        ],
                        lines: "#ecedec"
                    }
                }
            },
            fonts={
                digitsFont: "bold 20px SF Pro Display",
                indicator: "600 80px SF Pro Display",
                diagramFont: "bold 10px SF Pro Display"
            },
    
            // numbers setting
            digits = [0, 20, 40, 50, 60, 70, 80, 90, 100],
    
            //zones
            zonesCount = digits.length - 1;
    
        // Arrow settings
        let arrowValueIndex = -2.45,
    
        // beginning and ending of our arc. Sets by radius*pi
            startAngleIndex = .75,
            endAngleIndex = 2.25,
            step = (endAngleIndex - startAngleIndex) / zonesCount,
            allDataDiagram=[],
            forVisibleElem=true;
    
        /*draw zones*/
        let DrawZones = function () {
            const greyZonesCount = zonesCount / 1.6;
                  greenZonesCount = zonesCount - greyZonesCount,
                  startAngle = (startAngleIndex - 0.02) * Math.PI,
                  endGreyAngle = (startAngleIndex + greyZonesCount * step) * Math.PI,
                  endGreenAngle = (endAngleIndex + 0.02) * Math.PI,
    
                  //zones' options
                  sectionOptions = [
                      {
                          startAngle: startAngle,
                          endAngle: endGreyAngle,
                          color: "#e7e7e7",
                          zoneLineWidth: 2
                      },
                      {
                          startAngle: endGreyAngle,
                          endAngle: endGreenAngle,
                          color: "#13b74b",
                          zoneLineWidth: 5
                      },
                  ];
    
            //draw zones
            this.DrawZone = function (options) {
                ctx.beginPath();
                ctx.arc(proportions.general.middleX, proportions.general.middleY, proportions.general.radius, options.startAngle, options.endAngle, counterClockwise);
                ctx.lineWidth = options.zoneLineWidth;
                ctx.strokeStyle = options.color;
                ctx.lineCap = "round";
                ctx.stroke();
            };
    
            sectionOptions.forEach(options => this.DrawZone(options));
        };
    
        /*draw dots*/
        let DrawTicks = function () {
            startAngleIndex = .73,
            endAngleIndex = 2.27,
            step = (endAngleIndex - startAngleIndex) / zonesCount;
            this.DrawTick = function (angle,count) {
    
                let fromX = proportions.general.middleX + (proportions.general.radius - proportions.ticks.tickOffsetFromArc) * Math.cos(angle),
                    fromY = proportions.general.middleY + (proportions.general.radius - proportions.ticks.tickOffsetFromArc) * Math.sin(angle),
                    toX = proportions.general.middleX + (proportions.general.radius + proportions.ticks.tickOffsetFromArc) * Math.cos(angle),
                    toY = proportions.general.middleY + (proportions.general.radius + proportions.ticks.tickOffsetFromArc) * Math.sin(angle),
    
                    centerOfDotX=(fromX+toX)/2,
                    centerOfDotY=(fromY+toY)/2;
                ctx.beginPath();
                ctx.arc(centerOfDotX,centerOfDotY,6,0,Math.PI*2,true);
                if (count<6){
                    switch (count) {
                        case 1:
                        case 2:
                        case 3:
                            ctx.fillStyle=colorPalette.ticks.red.redTickColor;
                            break;
                        default:
                            ctx.fillStyle=colorPalette.ticks.yellow.darkYellowTickColor;
                            break;
                    }
                }else{
                    ctx.fillStyle=colorPalette.ticks.green.whiteFillColor;
                    ctx.strokeStyle=colorPalette.ticks.green.greenTickColor;
                    ctx.shadowColor = colorPalette.ticks.green.greenShadowColor;
                    ctx.shadowBlur = 15;
                    ctx.shadowOffsetX = 0;
                    ctx.shadowOffsetY = 0;
                    ctx.stroke();
                }
                ctx.fill();
                ctx.closePath();
                ctx.shadowBlur =0;
            };
            let count=0;
            for (let i = startAngleIndex; i <= endAngleIndex; i += step) {
                let angle = i * Math.PI;
                count++;
                this.DrawTick(angle,count);
            }
        };
    
        //draw numbers
        let DrawDigits = function () {
            let angleIndex = startAngleIndex;
    
            digits.forEach(function (digit) {
                let angle = angleIndex * Math.PI,
                        x = proportions.general.middleX + (proportions.general.radius - proportions.digits.digitsOffsetFromArc) * Math.cos(angle),
                        y = proportions.general.middleY + (proportions.general.radius - proportions.digits.digitsOffsetFromArc) * Math.sin(angle);
    
                angleIndex += step;
    
                ctx.font = fonts.digitsFont;
                ctx.fillStyle = colorPalette.text;
                ctx.textAlign = "center";
                ctx.textBaseline = "middle";
                ctx.fillText(digit, x, y);
            });
        };
    
        /*draw arrow*/
        let DrawArrow = function () {
            ctx.beginPath();
            ctx.lineCap = "round";
            ctx.moveTo(proportions.general.middleX-15, proportions.general.middleY);
            ctx.lineTo(proportions.general.middleX, proportions.general.middleY-150);
            ctx.lineTo(proportions.general.middleX+15, proportions.general.middleY);
            ctx.closePath();
            ctx.strokeStyle = colorPalette.arrow.bgBlue;
            ctx.fillStyle=colorPalette.arrow.bgBlue;
            ctx.shadowColor=colorPalette.arrow.shadowColor;
            ctx.shadowBlur = 15;
            ctx.shadowOffsetX = 0;
            ctx.shadowOffsetY = 0;
            ctx.stroke();
            ctx.fill();
            ctx.shadowBlur =0;
        };
        let oldText=0;
        /*draw indicator's number*/
        let DrawIndicator=function (val) {
            ctx.font = fonts.indicator;
            ctx.fillStyle = colorPalette.ticks.green.whiteFillColor; // or whatever color the background is.
            ctx.fillText(oldText, proportions.general.middleX, proportions.indicator.quarterY);
            ctx.fillStyle = colorPalette.text;
            ctx.fillText(`${val}`, proportions.general.middleX, proportions.indicator.quarterY);
            ctx.font = fonts.digitsFont;
            ctx.fillText('points',proportions.general.middleX,proportions.indicator.quarterY+proportions.general.middleY/5);
            oldText=val;
        };
        let indicatorNum=0;
    
        /*renderer*/
        function renderer() {
            ctx.clearRect(0,0,canvas.width,canvas.height);
    
            DrawZones();
            DrawTicks();
            DrawDigits();
            Diagram();
            DrawIndicator(indicatorNum);
            ctx.translate(proportions.general.middleX,proportions.general.middleY);
            ctx.rotate(arrowValueIndex);
            ctx.translate(-proportions.general.middleX,-proportions.general.middleY);
    
            DrawArrow();
    
            ctx.translate(proportions.general.middleX,proportions.general.middleY);
            ctx.rotate(-arrowValueIndex);
            ctx.translate(-proportions.general.middleX,-proportions.general.middleY);
    
        }
    
        function val(value) {
            let sector = Math.PI*0.385;
            if (value < 40)
                arrowValueIndex = value/40*sector - sector*2;
            else
                arrowValueIndex = (value-40)/60*sector*3 - sector;
            let add=(val)=>{
                indicatorNum=val;
                allDataDiagram.unshift(val);
                allDataDiagram=allDataDiagram.slice(0,186);
            };
            add(value);
            // document.querySelector('span').textContent = value;
            renderer();
        }
    
    
        //кроссбраузерный requestAnimationFrame
        let requestAnimFrame = (function(){
            return  window.requestAnimationFrame   ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame    ||
                window.oRequestAnimationFrame      ||
                window.msRequestAnimationFrame     ||
                function(callback){
                    window.setTimeout(callback, 1000 / 60);
                };
        })();
    
       
        if (forVisibleElem) 
          canvas.classList.add('slide-in-fwd-center');
       
      let delay = 2; // задержка перед анимацией
      let duration = 3; // кол во секунд анимации роста значения
      let time = new Date().getTime(); // Время начала анимации
    
      let Engine = () => {
          // кол-во секунд с начала анимации
          let t = (new Date().getTime() - time) / 1000;
          val(+getValueFromTime(t).toFixed(1));
          requestAnimFrame(Engine);
      };
    
    // получить значение спидометра в зависимости от текущего времени
    function getValueFromTime(t) {
    
        if (t < delay) // если еще не прошло время задержки
           return 0 // вернем 0
    
        t -= delay; // иначе вычитаем время задержки
    
        if (t < 0.95*duration) { // если прошло меньше 95 % времени анимации
            // переводим значение времени в значение при помощи функции сглаживания 
            // EasingFunctions.easeOutCubic (значение на входе должно быть от 0 до 1)
            return 98 * EasingFunctions.easeOutCubic(t/duration);
         }
    
         // иначе это функция от синуса от этого значения
         return 98 + EasingFunctions.easeInOutQuint(1-(1+Math.sin(t*22))/2);
    }
    
    let Diagram=()=>{
        this.drawLines=(x,y,width,height)=>{
            ctx.lineWidth=1.5;
            ctx.strokeStyle=colorPalette.diagram.bg.lines;
            ctx.moveTo(x,y);
            ctx.lineTo(width,height);
            ctx.stroke();
        };
        this.drawCircles = (x,y,r)=>{
            ctx.beginPath();
          ctx.arc(x,y,r,2*Math.PI,false);
          ctx.fillStyle=colorPalette.ticks.green.greenTickColor;
          ctx.fill();
            ctx.closePath();
        };
        this.writeNums = (value,x,y)=>{
            ctx.font = fonts.diagramFont;
            ctx.fillStyle = colorPalette.text;
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            ctx.fillText(value, x, y);
        };
        this.drawD=()=>{
            // console.log(allDataDiagram);
            for (var i=0; i<=widthD; i++){
                //draw bg gradient
                ctx.fillRect(proportions.general.middleX/1.6+i, proportions.general.middleY*1.53+heightD, 1, -(allDataDiagram[i]*0.25-2));
                ctx.fillStyle=colorPalette.ticks.green.whiteFillColor;
                ctx.fillRect(proportions.general.middleX/1.6+i,proportions.general.middleY*1.53,1,4+28-allDataDiagram[i]*0.25);
                ctx.fillStyle=colorPalette.ticks.green.greenTickColor;
                ctx.fillRect(proportions.general.middleX/1.6+i,proportions.general.middleY*1.53+4+28-allDataDiagram[i]*0.25,1,2);
                ctx.fillStyle=gradientD;
            }
        };
        const widthD=186,
              heightD=32,
              gradientD=ctx.createLinearGradient(0,0,widthD/2,0);
        gradientD.addColorStop(0,colorPalette.diagram.bg.gradient[0]);
        gradientD.addColorStop(1,colorPalette.diagram.bg.gradient[0]);
    
    
        //draw grey lines
        this.drawLines(proportions.general.middleX/1.6,proportions.general.middleY*1.53,proportions.general.middleX/1.6,proportions.general.middleY*1.53+heightD);
        this.drawLines(proportions.general.middleX/1.6+widthD,proportions.general.middleY*1.53,proportions.general.middleX/1.6+widthD,proportions.general.middleY*1.53+heightD);
    
        //write numbers
        this.writeNums(94,proportions.general.middleX/1.6, proportions.general.middleY*1.48);
        this.writeNums(97,proportions.general.middleX/1.6+widthD, proportions.general.middleY*1.48);
    
        //draw diagram
        this.drawD();
        //draw circles
        this.drawCircles(proportions.general.middleX/1.6,(proportions.general.middleY*1.53)+(32-94*0.25),3);
        this.drawCircles(proportions.general.middleX/1.6+widthD,(proportions.general.middleY*1.53)+(32-97*0.25),3);
    };
    
    
        window.onload=Engine;
        
        
    
    
    </script>

    • 4

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5