Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                x<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ESP32 on the rail</title>

    <style>
    footer{font-size: 10px;background-color: #ffffff;font-family: "Comic Sans MS"; margin: 5em 0 0 13em;}


    </style>
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

      <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

  </head>

<body onload='draw(0);'>

  <div class="container" >
    <h1> ESP32 on the Rail</h1>
      <div class="row">
        <div class="col-sm-6">
          <div class="card">
            <div class="card-body">
              <h4 class="card-title">DC motor controller</h4>
                <canvas id="speedometer" width="400" height="200">Canvas not available.</canvas>

              <p class="card-text">
                プラレールを制御するコントロール画面。このメータはモータデューティを表示していて、
                下のボタンで増減を調整します。トグルSWで前進・後退が切り替えられます。
              </p>
              <br>
              <fieldset style="margin:0 0 0 2em">
                <p> 進行方向切り替えSW </p>
                <input id="item-1" class="radio-inline__input" type="radio" name="accessible-radio" value="se1" checked="checked"/>
                <label class="radio-inline__label" for="item-1">
                    Forward
                </label>
                <input id="item-2" class="radio-inline__input" type="radio" name="accessible-radio" value="se2"/>
                <label class="radio-inline__label" for="item-2">
                    Backward
                </label>
                <br>
                <button type="button" id="upbtn" class="btn btn-success" style="margin : 0 0 0 5em"><i class="glyphicon glyphicon-upload"></i> UP</button>
                <button type="button" id="stopbtn" class="btn btn-danger"><i class="glyphicon glyphicon-pause"></i>brake</button>
                <button type="button" id="dwnbtn" class="btn btn-warning"><i class="glyphicon glyphicon-download"></i>DOWN</button>
              </fieldset>
              <br>
            </div>
          </div>


          </div>
          <div class="col-sm-6"></div>
      </div>
      <footer>
        <p> ぼくのマイコン開発のメモ Copyright 2020</p>
      </footer>
  </div>
<script>
  var DutyArr = [0, 100, 150, 200, 215, 255];
  var mascon=0;
  var bBackward = 0;
  var TarDuty=DutyArr[mascon];

  $( 'input[name="accessible-radio"]:radio' ).change( function() {
//      document.getElementById("stopbtn").click();
      var val = $(this).val();
      switch (val){
        case 'se1':
          bBackward =0;
          break;
        case 'se2':
          bBackward =1;
          break;
      }
      TarDuty=0;
      DCTar(TarDuty,bBackward);
      delay(500);
  });

  $('#upbtn').on('click', function() {
      var temp=mascon+1;
      if(temp>5){mascon =5;}
      else{mascon = temp;}

      TarDuty = DutyArr[Math.abs(mascon)];
      console.log(TarDuty);
      drawWithInputValue(TarDuty);
      DCTar(TarDuty,bBackward);

      enableRadio(TarDuty);

  });
  $('#dwnbtn').on('click', function() {
    var temp = mascon -1;
    if(temp<0){mascon=0;}
    else{mascon = temp;}

    TarDuty = DutyArr[Math.abs(mascon)];
    console.log(TarDuty);
    drawWithInputValue(TarDuty);
    DCTar(TarDuty,bBackward);

    enableRadio(TarDuty);
  });

  $('#stopbtn').on('click', function() {
    mascon=0;
    TarDuty=0;
    DCTar(TarDuty,bBackward);
    drawWithInputValue(0);

    enableRadio(TarDuty);
  });

  function enableRadio(TarDuty){
    var dir_radio = $('input[name="accessible-radio"]');
    if(TarDuty==0){
      dir_radio.prop('disabled', false);
    }
    else{
      dir_radio.prop('disabled', true);
    }
  }

    function DCTar(pos,bBackward) {
      $.get("/?valduty=" + pos + "_" + "/?valdir="+ bBackward + "&");
      {Connection: close};
    }

    /*jslint plusplus: true, sloppy: true, indent: 4 */
    (function () {
        "use strict";
        // this function is strict...
    }());

    var iCurrentSpeed= 0,
        iTargetSpeed = 0,
        bDecrement = null,
        job = null;

    function degToRad(angle) {
        // Degrees to radians
        return ((angle * Math.PI) / 180);
    }

    function radToDeg(angle) {
        // Radians to degree
        return ((angle * 180) / Math.PI);
    }

    function drawLine(options, line) {
        // Draw a line using the line object passed in
        options.ctx.beginPath();
        // Set attributes of open
        options.ctx.globalAlpha = line.alpha;
        options.ctx.lineWidth = line.lineWidth;
        options.ctx.fillStyle = line.fillStyle;
        options.ctx.strokeStyle = line.fillStyle;
        options.ctx.moveTo(line.from.X,
            line.from.Y);

        // Plot the line
        options.ctx.lineTo(
            line.to.X,
            line.to.Y
        );

        options.ctx.stroke();
    }

    function createLine(fromX, fromY, toX, toY, fillStyle, lineWidth, alpha) {
        // Create a line object using Javascript object notation
        return {
            from: {
                X: fromX,
                Y: fromY
            },
            to:    {
                X: toX,
                Y: toY
            },
            fillStyle: fillStyle,
            lineWidth: lineWidth,
            alpha: alpha
        };
    }

    function drawBackground(options) {
        /* Black background with alphs transparency to
         * blend the edges of the metallic edge and
         * black background
         */
       var i = 0;

        options.ctx.globalAlpha = 0.4;
        options.ctx.fillStyle = "rgb(0,0,0)";

        // Draw semi-transparent circles
        for (i = 170; i < 190; i++) {
            options.ctx.beginPath();

            options.ctx.arc(options.center.X,
                options.center.Y,
                i,  //半径
                0,  //スタート角度
                Math.PI, //エンド角度
                true); //時計周り or 反時計周り

            options.ctx.fill();
        }

    }

    function applyDefaultContextSettings(options) {
        /* Helper function to revert to gauges
         * default settings
         */

        options.ctx.lineWidth = 2;
        options.ctx.globalAlpha = 0.5;
        options.ctx.strokeStyle = "rgb(255, 255, 255)";
        options.ctx.fillStyle = 'rgb(255,255,255)';
    }

    function drawSmallTickMarks(options) {
        /* The small tick marks against the coloured
         * arc drawn every 5 mph from 10 degrees to
         * 170 degrees.
         */

        var tickvalue = options.levelRadius - 8,
            iTick = 0,
            gaugeOptions = options.gaugeOptions,
            iTickRad = 0,
            onArchX,
            onArchY,
            innerTickX,
            innerTickY,
            fromX,
            fromY,
            line,
            toX,
            toY;

        applyDefaultContextSettings(options);

        // Tick every 20 degrees (small ticks)
        for (iTick = 10; iTick < 180; iTick += 20) {

            iTickRad = degToRad(iTick);

            /* Calculate the X and Y of both ends of the
             * line I need to draw at angle represented at Tick.
             * The aim is to draw the a line starting on the
             * coloured arc and continueing towards the outer edge
             * in the direction from the center of the gauge.
             */

            onArchX = gaugeOptions.radius - (Math.cos(iTickRad) * tickvalue);
            onArchY = gaugeOptions.radius - (Math.sin(iTickRad) * tickvalue);
            innerTickX = gaugeOptions.radius - (Math.cos(iTickRad) * gaugeOptions.radius);
            innerTickY = gaugeOptions.radius - (Math.sin(iTickRad) * gaugeOptions.radius);

            fromX = (options.center.X - gaugeOptions.radius) + onArchX;
            fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + onArchY;
            toX = (options.center.X - gaugeOptions.radius) + innerTickX;
            toY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY;

            // Create a line expressed in JSON
            line = createLine(fromX, fromY, toX, toY, "rgb(255,255,255)", 3, 0.6);

            // Draw the line
            drawLine(options, line);

        }
    }

    function drawLargeTickMarks(options) {
        /* The large tick marks against the coloured
         * arc drawn every 10 mph from 10 degrees to
         * 170 degrees.
         */

        var tickvalue = options.levelRadius - 8,
            iTick = 0,
            gaugeOptions = options.gaugeOptions,
            iTickRad = 0,
            innerTickY,
            innerTickX,
            onArchX,
            onArchY,
            fromX,
            fromY,
            toX,
            toY,
            line;

        applyDefaultContextSettings(options);

        tickvalue = options.levelRadius - 2;

        // 10 units (major ticks)
        for (iTick = 20; iTick < 180; iTick += 20) {

            iTickRad = degToRad(iTick);

            /* Calculate the X and Y of both ends of the
             * line I need to draw at angle represented at Tick.
             * The aim is to draw the a line starting on the
             * coloured arc and continueing towards the outer edge
             * in the direction from the center of the gauge.
             */

            onArchX = gaugeOptions.radius - (Math.cos(iTickRad) * tickvalue);
            onArchY = gaugeOptions.radius - (Math.sin(iTickRad) * tickvalue);
            innerTickX = gaugeOptions.radius - (Math.cos(iTickRad) * gaugeOptions.radius);
            innerTickY = gaugeOptions.radius - (Math.sin(iTickRad) * gaugeOptions.radius);

            fromX = (options.center.X - gaugeOptions.radius) + onArchX;
            fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + onArchY;
            toX = (options.center.X - gaugeOptions.radius) + innerTickX;
            toY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY;

            // Create a line expressed in JSON
            line = createLine(fromX, fromY, toX, toY, "rgb(255,255,255)", 3, 0.6);

            // Draw the line
            drawLine(options, line);
        }
    }

    function drawTicks(options) {
        /* Two tick in the coloured arc!
         * Small ticks every 5
         * Large ticks every 10
         */
        drawSmallTickMarks(options);
        drawLargeTickMarks(options);
    }

    function drawTextMarkers(options) {
        /* The text labels marks above the coloured
         * arc drawn every 10 mph from 10 degrees to
         * 170 degrees.
         */
        var innerTickX = 0,
            innerTickY = 0,
            iTick = 0,
            gaugeOptions = options.gaugeOptions,
            iTickToPrint = 00;

        applyDefaultContextSettings(options);

        // Font styling
        options.ctx.font = 'italic 15px sans-serif';
        options.ctx.textBaseline = 'top';

        options.ctx.beginPath();

        // Tick every 20 (small ticks)
        for (iTick = 10; iTick < 180; iTick += 20) {

            innerTickX = gaugeOptions.radius - (Math.cos(degToRad(iTick)) * gaugeOptions.radius);
            innerTickY = gaugeOptions.radius - (Math.sin(degToRad(iTick)) * gaugeOptions.radius);

            // Some cludging to center the values (TODO: Improve)
            if (iTick <= 10) {
                options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX,
                        (gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
            } else if (iTick < 50) {
                options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX - 5,
                        (gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
            } else if (iTick < 90) {
                options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX,
                        (gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
            } else if (iTick === 90) {
                options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 4,
                        (gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
            } else if (iTick < 145) {
                options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 10,
                        (gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
            } else {
                options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 15,
                        (gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
            }

            // MPH increase by 10 every 20 degrees
            //iTickToPrint += Math.round(2160 / 9);
             iTickToPrint += 30;
        }

        options.ctx.stroke();
    }

    function drawSpeedometerPart(options, alphaValue, strokeStyle, startPos) {
        /* Draw part of the arc that represents
        * the colour speedometer arc
        */

        options.ctx.beginPath();

        options.ctx.globalAlpha = alphaValue;
        options.ctx.lineWidth = 5;
        options.ctx.strokeStyle = strokeStyle;

        options.ctx.arc(options.center.X,
            options.center.Y,
            options.levelRadius,
            Math.PI + (Math.PI / 360 * startPos),
            0 - (Math.PI / 360 * 10),
            false);

        options.ctx.stroke();
    }

    function drawSpeedometerColourArc(options) {
        /* Draws the colour arc.  Three different colours
         * used here; thus, same arc drawn 3 times with
         * different colours.
         * TODO: Gradient possible?
         */

        var startOfGreen = 10,
            endOfGreen = 200,
            endOfOrange = 280;

        drawSpeedometerPart(options, 1.0, "rgb(50,205,50)", startOfGreen);
        drawSpeedometerPart(options, 0.9, "rgb(255,165,0)", endOfGreen);
        drawSpeedometerPart(options, 0.9, "rgb(255,69,0) ", endOfOrange);

    }

    function drawNeedleDial(options, alphaValue, strokeStyle, fillStyle,bBackward) {
        /* Draws the metallic dial that covers the base of the
        * needle.
        */
        var i = 0;

        options.ctx.globalAlpha = alphaValue;
        options.ctx.lineWidth = 3;
        options.ctx.strokeStyle = strokeStyle;

        if (bBackward==1){
          options.ctx.fillStyle = "rgb(255,0,0)";
        }
        else{
          options.ctx.fillStyle = fillStyle;
        }

        // Draw several transparent circles with alpha
        for (i = 0; i < 30; i++) {

            options.ctx.beginPath();
            options.ctx.arc(options.center.X,
                options.center.Y,
                i,
                0,
                Math.PI,
                true);

            options.ctx.fill();
            options.ctx.stroke();
        }
    }

    function convertSpeedToAngle(options) {
        /* Helper function to convert a speed to the
        * equivelant angle.
        */
        var iSpeed = options.speed,
            iSpeedAsAngle = (iSpeed)/255 * 180+10;

        // Ensure the angle is within range
        if (iSpeedAsAngle > 180) {
            iSpeedAsAngle = 180;
        } else if (iSpeedAsAngle < 10) {
            iSpeedAsAngle = 10;
        }

        return iSpeedAsAngle;
    }

    function drawNeedle(options,bBackward) {
        /* Draw the needle in a nice read colour at the
        * angle that represents the options.speed value.
        */

        var iSpeedAsAngle = convertSpeedToAngle(options),
            iSpeedAsAngleRad = degToRad(iSpeedAsAngle),
            gaugeOptions = options.gaugeOptions,
            innerTickX = gaugeOptions.radius - (Math.cos(iSpeedAsAngleRad) * 20),
            innerTickY = gaugeOptions.radius - (Math.sin(iSpeedAsAngleRad) * 20),
            fromX = (options.center.X - gaugeOptions.radius) + innerTickX,
            fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY,
            endNeedleX = gaugeOptions.radius - (Math.cos(iSpeedAsAngleRad) * gaugeOptions.radius),
            endNeedleY = gaugeOptions.radius - (Math.sin(iSpeedAsAngleRad) * gaugeOptions.radius),
            toX = (options.center.X - gaugeOptions.radius) + endNeedleX,
            toY = (gaugeOptions.center.Y - gaugeOptions.radius) + endNeedleY,
            line = createLine(fromX, fromY, toX, toY, "rgb(255, 0, 0)", 3, 1);

        drawLine(options, line);

        // Two circle to draw the dial at the base (give its a nice effect?)
        drawNeedleDial(options, 0.6, "rgb(255, 255, 255)", "rgb(255,255,255)",bBackward);
        drawNeedleDial(options, 0.2, "rgb(255, 255, 255)", "rgb(127,127,127)",bBackward);

    }

    function buildOptionsAsJSON(canvas, iSpeed) {
        /* Setting for the speedometer
        * Alter these to modify its look and feel
        */

        var centerX = 210,
            centerY = 210,
            radius = 150,
            outerRadius = 200;

        // Create a speedometer object using Javascript object notation
        return {
            ctx: canvas.getContext('2d'),
            speed: iSpeed,
            center:    {
                X: centerX,
                Y: centerY
            },
            levelRadius: radius - 10,
            gaugeOptions: {
                center:    {
                    X: centerX,
                    Y: centerY
                },
                radius: radius
            },
            radius: outerRadius
        };
    }

    function clearCanvas(options) {
        options.ctx.clearRect(0, 0, 800, 600);
        applyDefaultContextSettings(options);
    }
    function drawLabel(options,bBackward)
    {

        var offsetX=0;
        var offsetY=60;

        options.ctx.font = '20pt sans-serif';
        if(bBackward==0){
              options.ctx.strokeStyle='#ffffff';
        }else{
              options.ctx.strokeStyle='#ff0000';
        }
        var X=options.center.X;
        var Y=options.center.Y;
        options.ctx.textAlign = 'center';
        //options.ctx.globalCompositeOperation = 'destination-over';
        options.ctx.strokeText(options.speed,X-offsetX, Y-offsetY);
        options.ctx.textAlign = 'start';

    }
    function draw() {
        /* Main entry point for drawing the speedometer
        * If canvas is not support alert the user.
        */

//        console.log('Target: ' + iTargetSpeed);
//        console.log('Current: ' + iCurrentSpeed);

        var canvas = document.getElementById('speedometer'),
            options = null;

        // Canvas good?
        if (canvas !== null && canvas.getContext) {
            options = buildOptionsAsJSON(canvas, iCurrentSpeed);

            // Clear canvas
            clearCanvas(options);

            // Draw thw background
            drawBackground(options);
            // Draw tick marks
            drawTicks(options);
            // Draw labels on markers
            drawTextMarkers(options);
            // Draw speeometer colour arc
            drawSpeedometerColourArc(options);
            // Draw text of dashboard
            drawLabel(options,bBackward);
            // Draw the needle and base
            drawNeedle(options,bBackward);



        } else {
            alert("Canvas not supported by your browser!");
        }

        if(iTargetSpeed == iCurrentSpeed) {
            clearTimeout(job);
            return;
        } else if(iTargetSpeed < iCurrentSpeed) {
            bDecrement = true;
        } else if(iTargetSpeed > iCurrentSpeed) {
            bDecrement = false;
        }

        if(bDecrement) {
            if(iCurrentSpeed - 10 < iTargetSpeed)
                iCurrentSpeed = iCurrentSpeed - 1;
            else
                iCurrentSpeed = iCurrentSpeed - 1;
        } else {

            if(iCurrentSpeed + 10 > iTargetSpeed)
                iCurrentSpeed = iCurrentSpeed + 1;
            else
                iCurrentSpeed = iCurrentSpeed + 1;
        }


        job = setTimeout("draw()", 5);
    }

    function drawWithInputValue(mascon) {

        iTargetSpeed = mascon;



            // Sanity checks
            if (isNaN(iTargetSpeed)) {
                iTargetSpeed = 0;
            } else if (iTargetSpeed < 0) {
                iTargetSpeed = 0;
            } else if (iTargetSpeed > 255) {
                iTargetSpeed = 255;
            }

            job = setTimeout("draw()", 5);

        }


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

              
            
!

CSS

              
                
              
            
!

JS

              
                
              
            
!
999px

Console