简体   繁体   中英

React on hover over box-shadow and change color of that specific box-shadow

Basically I have a div with a comma-separated list of box-shadows like in the appended code snippet and I need to change the color of an individual "shadow block" when hovering it.

期望的结果

I searched for ways on how to find out if a specific rendered CSS property is hovered but the only useful thing I found was a similar question on how to detect if the border of a cell is hovered . Here the answer seems clear: you have the position of the hovered cell and it's border-width, so check the offset in four different directions. I wasn't able to transfer this principle to the (comma-separated) box-shadow property.

Note that I don't want to replicate the positions of the box-shadows in Javascript. The solution should still work if I change the positions of individual shadows in the CSS. If required you can assume that the width and height of the div does not change. Any clever ideas on this? Bonus task would be to color the hovered shadow block as shown in the above image, but a solution that logs a message to the console if any of the box-shadows is hovered would already be a useful step.

 .box-with-shadow { display: block; width: 10px; height: 10px; box-shadow: 100px 130px #000, 90px 140px #000, 100px 140px #000, 110px 140px #000, 80px 150px #000, 90px 150px #000, 110px 150px #000, 120px 150px #000, 90px 160px #000, 100px 160px #000, 110px 160px #000, 100px 170px #000; } 
 <div class="box-with-shadow"> </div> 

As correctly pointed out by marekful the easiest way to achieve the desired effect would be to use multiple HTML elements instead of multiple shadows. However, I will answer the question with a trivial solution that works for the described setup and with variable box-shadows. It is not robust enough to solve some special cases like eg a rotation of the div.

The idea is to calculate the positions of the shadows once in the beginning (assuming that nothing moves or changes, otherwise we have to recalculate the positions multiple times). On mouse movement I check if the position of the mouse is in any of the intervals, which are defined by the position of a shadow plus its dimension.

It's been a while since I used Javascript, so there might be the chance that some parts can be simplified, but at least it works. Feel free to play around with the JSFiddle .

 var boxWidth = parseInt($("#box-with-shadow").css('width'), 10); var boxHeight = parseInt($("#box-with-shadow").css('height'), 10); var boxOffsetX = parseInt($("#box-with-shadow").css('margin-left'), 10); var boxOffsetY = parseInt($("#box-with-shadow").css('margin-top'), 10); var boxShadowString = $('#box-with-shadow').css('box-shadow'); var boxShadows = boxShadowString.split(/,(?![^\\(]*\\))/); // key: x-pos of the shadow, value: concatenated y-positions, separated by commas var keyValuePairs = fillKeyValuePairs(); var cursorX; var cursorY; document.onmousemove = function(e) { cursorX = e.pageX; cursorY = e.pageY; checkCursor(); } function checkCursor() { var shadowHovered = false; for (i = cursorX - boxWidth; i <= cursorX && !shadowHovered; i++) { if (keyValuePairs[i] != null) { // At this point we know that somewhere on this x-position there is a shadow. // Now check if there is an associated y-interval for the found x-position for (j = cursorY - boxHeight; j <= cursorY; j++) { if ((keyValuePairs[i] + "").split(",").indexOf(j + "") != -1) { shadowHovered = true; break; } } } } if (shadowHovered) { $("#status").css("background", "green"); $("#status").text("Found shadow: xOffset = " + (i - 1) + "px, yOffset = " + j + "px"); } else { $("#status").css("background", "red"); $("#status").text(""); } } function fillKeyValuePairs() { var keyValuePairs = []; for (index = 0; index < boxShadows.length; index++) { var xPos = parseInt(boxShadows[index].trim().match(/[0-9]+px/g)[0], 10) + boxOffsetX; var yPos = parseInt(boxShadows[index].trim().match(/[0-9]+px/g)[1], 10) + boxOffsetY; keyValuePairs[xPos] = keyValuePairs[xPos] != null ? keyValuePairs[xPos] + "," + yPos : yPos; } return keyValuePairs; } 
 body { margin: 0; padding: 0; } #box-with-shadow { display: block; width: 10px; height: 10px; box-shadow: 100px 130px #000, 90px 140px #000, 100px 140px #000, 110px 140px #000, 80px 150px #000, 90px 150px #000, 110px 150px #000, 120px 150px #000, 90px 160px #000, 100px 160px #000, 110px 160px #000, 100px 170px #000; } #status { width: 100%; height: 2em; background: red; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="box-with-shadow"> </div> <div id="status"> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM