Creating CSS3D matrices

My goal is to achieve a specific effect using CSS3 and JavaScript, creating a MouseOver effect when the mouse moves over the center div.

I've developed a small library that takes in three arguments (element, sourcePoints, destination points) and returns a CSS3D matrix while updating the element. Here is my JavaScript code:

var BLEND = BLEND || {};

BLEND.Util = BLEND.Util || {};

function print(msg) {
    console.log(msg);
}
BLEND.Util.VendorPrefix = "";
BLEND.Util.DetectVendorPrefix = function() {
var styles = window.getComputedStyle(document.documentElement, ''),
        pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o']))[1];
BLEND.Util.VendorPrefix = pre[0].toUpperCase() + pre.substr(1) + "Transform";
}
BLEND.Util.DetectVendorPrefix();
BLEND.TransformElement = function(elm, src, dest) {
var L = [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]];
var R = [0, 0, 0, 0, 0, 0, 0, 0];

for (var i = 0; i < 4; i++) {
    L[i] = [];
    L[i][0] = L[i + 4][3] = src[i].x;
    L[i][2] = L[i + 4][4] = src[i].y;
    L[i][2] = L[i + 4][5] = 1;
    L[i][3] = L[i][4] = L[i][5] = L[i + 4][0] = L[i + 4][3] = L[i + 4][2] = 0;
    L[i][6] = -src[i].x * dest[i].x;
    L[i][7] = -src[i].y * dest[i].x;
    L[i + 4][6] = -src[i].x * dest[i].y;
    L[i + 4][7] = -src[i].y * dest[i].y;

    R[i] = dest[i].x;
    R[i + 4] = dest[i].y;
}


var RM = [];
for (i = 0; i < R.length; i++) {
    RM[i] = [R[i]];
}

var Left = Matrix.create(L);
var Right = Matrix.create(R);

var res = Matrix.calculate(Left, Right);

print (res);

 if (BLEND.Util.VendorPrefix == 'WebkitTransform') {

 var matrix3D = new CSSMatrix();
 matrix3D.m11 = res.get(0,0);
 matrix3D.m12 = res.get(3,0);
 matrix3D.m13 = 0;
 matrix3D.m14 = res.get(6,0);

 matrix3D.m21 = res.get(1,0);
 matrix3D.m22 = res.get(4,0);
 matrix3D.m23 = 0;
 matrix3D.m24 = res.get(7,0);

 matrix3D.m31 = 0;
 matrix3D.m32 = 0;
 matrix3D.m33 = 1;
 matrix3D.m34 = 0;

 matrix3D.m41 = res.get(2,0);
 matrix3D.m42 = res.get(5,0);
 matrix3D.m43 = 0;
 matrix3D.m44 = 1;

 elm.style.webkitTransform = matrix3D;
 } else {
 if (BLEND.Util.VendorPrefix === "")
 BLEND.Util.DetectVendorPrefix();
 elm.style[BLEND.Util.VendorPrefix] = "matrix3d(" + res.get(0,0) + "," + res.get(3,0) + ", 0," + res.get(6,0) + "," + res.get(1,0) + "," + res.get(4,0) + ", 0," + res.get(7,0) + ",0, 0, 1, 0," + res.get(2,0) + "," + res.get(5,0) + ", 0, 1)";
 } 
}

UPDATE: Here is JSFiddle

I am invoking the TransformElement method for nine different divs with proper coordinates but it's not functioning as expected. Any suggestions on how to resolve this issue? Could it be achieved using Three.js in any way?

UPDATE: Can we accomplish this with CSS3D renderer and Three.js?

The concept is to create a plane and divide it into a 3x3 grid. When hovering over each face of the plane, that particular div should scale up while others adjust accordingly. Is this feasible?

Answer №1

While I haven't had the chance to experiment with your library, I did come up with a solution for the issue you're facing: http://codepen.io/bali_balo/pen/87b980a2acf722b1c9feb35f3fcb1c65/. This implementation utilized Haml and SCSS, and the compiled code can be viewed by clicking on the small eye icon in each panel's top right corner.

To craft this code, I referenced this informative article.

The process involved computing 9 matrices initially (for the hovered tile as well as its neighboring tiles), leveraging numericjs and formulas highlighted in the aforementioned article. Subsequently, upon mouseover, these matrices were applied to the respective tiles. The following snippet showcases how the transform matrix is obtained based on the locations of 4 points before and after transformation:

//from and to are arrays of 4 objects containing a property x and a property y
//representing the quadrilateral's 4 points pre-transformation
function getTransform(from, to)
{
  var A = [], i;
  for(i = 0; i < 4; i++)
  {
      A.push([from[i].x, from[i].y, 1, 0, 0, 0, -from[i].x * to[i].x, -from[i].y * to[i].x]);
      A.push([0, 0, 0, from[i].x, from[i].y, 1, -from[i].x * to[i].y, -from[i].y * to[i].y]);
  }
  var b = [];
  for(i = 0; i < 4; i++)
  {
      b.push(to[i].x);
      b.push(to[i].y);
  }
  //Utilizes numericjs to solve matrix equations
  //returns h given A and b where A.h = b
  var h = numeric.solve(A, b);
  //Column major representation
  return [[h[0], h[3], 0, h[6]],
          [h[1], h[4], 0, h[7]],
          [ 0  ,  0  , 1,  0  ],
          [h[2], h[5], 0,  1  ]];
}

It should be noted that, per my code comments, if animated transitions are desired, utilizing CSS alone may not suffice (as it could result in transitioning individual values of the matrix, which isn't always ideal). An alternative involving javascript might be considered, albeit potentially slower due to the necessity of recalculating matrices at each frame without caching.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

switch from material ui lists on/off

Trying to learn React through coding, I've encountered an issue with displaying the 'StarBorder' icon next to folders when clicked. Currently, clicking on any folder displays the 'StarBorder' icon for all folders. Any tips on how t ...

Finding the mouseover event for an element that is beneath an overlaid div

There are four div elements, and on mouseover, the selected div will get zoomed. However, I also need to capture the mouseover event for the remaining three underlying divs, even when one is overlayed. This way, I can zoom out the previously selected div a ...

Troubleshooting Problem with Centering Rows in Bootstrap

I am utilizing the most recent version of Bootstrap 3 to design a website for a friend, but I am encountering a challenge with centering elements on the page. Typically, I would use the following code: .center{ width: 90%; margin: 0 auto; } Howev ...

Determine the prior location of an element using jQuery

Is there a way to track the previous location of an element before it is appended? I have 50 elements that need to be appended to different targets based on a certain condition. How can I determine where each element was located before being moved? $(&a ...

What is the best way to transfer the JWT token from the server to the client using an HTTP header?

I have been searching for an answer on how to pass the JWT Token from the client to the server securely, but I am not satisfied with the explanations I found. Everyone talks about the most secure way to transfer the JWT token using HTTP headers instead of ...

Construct a Product Showcase Page" (FreeCodeCamp) - Issue "Incurred upon clicking a .nav-link button in the navigation panel

Hi there! I've been working on a page programming task, but I'm having trouble with the "№5 “When I click a .nav-link button in the nav element, I am taken to the corresponding section of the landing page.” error. Can anyone help me figure ...

Using http-proxy to forward request to a different port

In my code, I am creating a proxy that routes all application calls from port 3000 to port 3002 seamlessly. var http = require('http'), httpProxy = require('http-proxy'); var proxy = httpProxy.createProxyServer(); http.create ...

Positioning items in a CSS grid layout involves ensuring that item 1 remains at the bottom of its column, while item 2 is centered within its column

I am trying to create a grid layout using CSS grid: The main section should have two columns. The first column will contain an image that sticks to the bottom of the grid, while the second column will display a centered card. Below are my HTML/CSS codes: ...

How can I create subarrays from an array in JavaScript/jQuery based on their individual counts?

Is there a way to transform an array into subarrays based on the count of their element values using either JavaScript or jQuery? For instance: var myArray=["a","b","c","a","a","c","b"]; The desired output after tallying the elements a, b, and c output ...

What is the best approach to decrease the size of a button in HTML and CSS when the text size is also reduced?

Check out this code snippet! I'm new to coding, so let me know if you see any errors or ways it could be improved. button { font-size: 10px; font-family: roboto, Arial; color: white; background-color: rgb(59, 102, 241); border-radius: 100p ...

Alignment of UI Divs with CSS Bootstrap and HTML

I am facing an issue with two divs in my UI. One div has a label, and the other contains a file selector. Currently, they are stacked vertically instead of being side by side. https://i.stack.imgur.com/fIz03.png How can I align these divs horizontally wit ...

event triggered when the values of dynamically added rows change

I am trying to calculate the product of two input fields and display it without submitting the form. I have incorporated an array and included functionality to add/delete rows, with an onchange function to calculate the product. This solution works well ...

Shadows in THREE.JS are not being affected by the displacement map

Lately, I've been facing some challenges with getting the shadows to work properly when using a displacement map. Despite researching the issue on Google, I still can't seem to figure it out. From what I gather, the displacement map is supposed t ...

Even after setting a value to an HTML input field from the C# code behind, any modifications to the text are not being displayed

My form consists of input fields with the attributes type="text" and runat="server" to enable the code behind to access it. Users can input data and later edit the same data if selected from a list. However, after populating the form for editing and making ...

Is it possible to utilize Angular validation directives programmatically within a personalized directive?

In my exploration of HTML inputs, I have noticed a recurring pattern specifically for phone numbers: <input type="text" ng-model="CellPhoneNumber" required ng-pattern="/^[0-9]+$/" ng-minlength="10" /> I am interested in developing a unique directiv ...

Using jQuery to show an Ajax loader while the page is loading

Is it possible to display a loader (gif) before the HTML is loaded and during a page transition? I have seen this type of effect on many websites and am curious if it can be implemented. If so, is it achievable using jQuery, AJAX, and PHP? I know how to ...

In Firefox, the CSS height and width values are displayed as X pixels, whereas in Internet Explorer, they are automatically set to 'auto'

When it comes to measuring div box dimensions, jQuery can be a handy tool. Here is an example code snippet: $(document).ready(function(){ var h = $("#testbox").css("height"); }); Interestingly, the same code can give different results in different brow ...

Accessing Data from the Wikipedia API

After receiving a JSON response with the following structure: { "batchcomplete": "", "query": { "pages": { "97646": { "pageid": 97646, "ns": 0, "title": "Die Hard", "extract": "Die Hard is a 1988 ...

Finding the Client's Private IP Address in React or Node.js: A Comprehensive Guide

Issue I am currently facing the challenge of comparing the user's private IP with the certificate's IP. Is there a method available to retrieve the user's private IP in react or node? Attempted Solution After attempting to find the user&a ...

How can I use AJAX to update a DIV when an image is swapped out?

I run an online radio station and I've been looking for a way to display album artwork for each song that plays. After setting up the ability to automatically upload the image of the currently playing song as "artwork.png" to a web server via FTP, I c ...