Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating realistic box-shadow with JavaScript

Tags:

javascript

css

I'm building a book library webapp with books draggable between the shelves. 

Applying box-shadow to books made them look slightly more realistic but I wondered if I can go further and dynamically calculate box-shadow values for every book by its position relative to a single chosen “light source” point, like a game engine would do. 

Thus, if we choose top center point to be the light source, a book on the left will have a left bottom shadow, and a book on the right will have a right bottom shadow. Books at the bottom would get shadows of larger height, et cetera. We might need to specify depth (z-coordinate) for the light source as well as its position.

While box-shadow doesn't allow for complex realistic shadows, I suspect it would be more than enough to adjust shadow size and angle with regards to their position for rectangular objects such as books to make them a lot more realistic. 

Has anyone already looked into implementing this in JavaScript? Are you aware of any open source libraries that calculate box-shadow values with regards to a specific light source point? If not, is the idea inherently wrong in some way I haven't thought of, or is it that nobody has tried just this yet?

like image 776
Dan Abramov Avatar asked Sep 02 '26 10:09

Dan Abramov


1 Answers

A bloke called Jeff Pamer made an experiment about this

requires jQuery and jQuery UI Draggable (see demo)

your html:

<div id="light_source">Light Source<br />(drag me)</div>
<div id="div1" class="needs_shadow">(drag me)</div>
<div id="div2" class="needs_shadow">(drag me)</div>

your JavaScript

$(document).ready(function() {
  $("div").draggable({
    drag: function() { make_shade() }
  });
  make_shade();  
});

function make_shade() {
  var light = $("div#light_source");
  var light_pos = light.position();
  var light_x = light_pos.left + (light.width() / 2);
  var light_y = light_pos.top + (light.height() / 2);

  $(".needs_shadow").each(function() {
    var div1 = $(this);
    var div1_pos = div1.position();

    var div_x = div1_pos.left + (div1.width() / 2);
    var div_y = div1_pos.top + (div1.height() / 2);

    var left_diff = light_x - div_x;
    var top_diff = light_y - div_y;

    var left = (left_diff / 10) * -1;
    var top = (top_diff / 10) * -1;

    var distance = Math.sqrt(Math.pow(left_diff, 2) + Math.pow(top_diff, 2));
    distance = distance / 10;

    shadow_style = left + "px " + top + "px " + distance + "px #3f3f3f";
    div1.css("-moz-box-shadow", shadow_style);
    div1.css("-webkit-box-shadow", shadow_style);
    div1.css("box-shadow", shadow_style);
  });
}
like image 173
Vincent Briglia Avatar answered Sep 04 '26 00:09

Vincent Briglia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!