0

I want to make my chart float on the screen. For that I am trying to get the canvas that holds my rendered chart to have a shadow. But no matter what I search about getting shadows for a canvas element, it doesn't work.

The code that I have so far for the shadow is -

<script>
document.addEventListener('DOMContentLoaded', function() {
var canvas = document.getElementsByClassName("marks")[0];
if (canvas.getContext)
    {
      var ctx = canvas.getContext('2d');
      ctx.shadowColor = 'black';
      ctx.shadowBlur = 10;
      ctx.shadowOffsetX = 20;
      ctx.shadowOffsetY = 20;
    //  ctx.fill();
    }
}, false);
</script>

The whole HTML looks like this -

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-lite@4.8.1"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-projection-extended@2"></script>
</head>
<body>
<div id="vis"></div>
  <script type="text/javascript">
    var spec = {
      "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
      "config": {
        "view": {
          "continuousHeight": 300,
          "continuousWidth": 400
        }
      },
      "data": {
        "url": "https://vega.github.io/vega-datasets/data/cars.json"
      },
      "encoding": {
        "color": {
          "field": "Origin",
          "type": "nominal"
        },
        "x": {
          "field": "Horsepower",
          "type": "quantitative"
        },
        "y": {
          "field": "Miles_per_Gallon",
          "type": "quantitative"
        }
      },
      "mark": "point"
    };
    var opt = {"renderer": "canvas", "actions": false};
    vegaEmbed("#vis", spec, opt);
  </script>

<span class="update_time">Updated at 2020-02-24 12:10</span>

</body>
<script>
document.addEventListener('DOMContentLoaded', function() {
var canvas = document.getElementsByClassName("marks")[0];
if (canvas.getContext)
    {
      var ctx = canvas.getContext('2d');
      ctx.shadowColor = 'black';
      ctx.shadowBlur = 10;
      ctx.shadowOffsetX = 20;
      ctx.shadowOffsetY = 20;
    //  ctx.fill();
    }
}, false);
</script>
</html>

How should I modify my script to have a shadow appear below my chart on one side?

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
jar
  • 2,646
  • 1
  • 22
  • 47

1 Answers1

1

Since canvas is an HTML element, you would use CSS and the box-shadow property to alter its presentation.

Also, it is invalid to have any content after the closing body tag and before the closing html tag. So, if you were going to need that last script element (which you don't now), it should be just prior to the closing body tag.

Lastly, the following line:

var canvas = document.getElementsByClassName("marks")[0];

is really not a good approach to getting your DOM element reference and should really be (in future cases where you'll need it, but it won't be necessary at all here):

var canvas = document.querySelector(".marks");

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-lite@4.8.1"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-projection-extended@2"></script>

  <style>
    canvas { border:1px solid black; box-shadow: 4px 4px 1px grey; }
  </style>

</head>
<body>
<div id="vis"></div>
  <script>
    var spec = {
      "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
      "config": {
        "view": {
          "continuousHeight": 300,
          "continuousWidth": 400
        }
      },
      "data": {
        "url": "https://vega.github.io/vega-datasets/data/cars.json"
      },
      "encoding": {
        "color": {
          "field": "Origin",
          "type": "nominal"
        },
        "x": {
          "field": "Horsepower",
          "type": "quantitative"
        },
        "y": {
          "field": "Miles_per_Gallon",
          "type": "quantitative"
        }
      },
      "mark": "point"
    };
    var opt = {"renderer": "canvas", "actions": false};
    vegaEmbed("#vis", spec, opt);
  </script>

  <div class="update_time">Updated at 2020-02-24 12:10</div>
</body>
</html>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • I just realized one thing....the script I added for the shadow actually doesn't do anything at all. The shadow follows the specifications in the css only. Any idea how do I fix that? Do i even need js for shadow below canvas? From css is it possible to handle the offset of the shadows? – jar Feb 26 '21 at 19:58
  • 1
    @jar As you can see, I've removed that `script` as it doesn't do anything and isn't needed. It's all done with CSS. – Scott Marcus Feb 26 '21 at 22:13