Home > other >  Framer motion and transform matrix
Framer motion and transform matrix

Time:12-01

I am making app with framer motion and I need to drag svg inside another svg but my problem is that viwebox size is not equal to window size so when I drag element my 1px movement of mouse on the screen is like 100 px. I know in JavaScript we can calculate x and y with screenX, sceenY and CTM (current transform matrix). Is possible to make somehow framer motion drag function to calculate that?

<svg viewBox="0 0 40 20">
  <motion.circle drag cx="5" cy="5" r="0.5"strokeWidth="0.1"/>
</svg>

P.S. I cannot change viewbox size and its 100% of width and height of screen

this is current state of the app where you can see the problem when you try to drag player object. https://waterpolo.klaktech.com

CodePudding user response:

In Framer Motion, you can use the transformMatrix property of the drag gesture to get the current transform matrix of the element being dragged. You can then use this matrix to calculate the new position of the element based on the movement of the mouse cursor.

Here is an example of how you can use the transformMatrix property to drag an element inside an SVG element with a viewBox:

import { motion, useTransform } from "framer-motion";

// Define the dimensions of the viewBox
const viewBoxWidth = 40;
const viewBoxHeight = 20;

// Create a ref to store the transform matrix of the element being dragged
const transformMatrix = useTransform(dragState.xy, (xy) => {
  // Get the current transform matrix of the element
  const matrix = drag.transformMatrix.current;

  // Calculate the new x and y position of the element
  const x = xy.x * matrix.a   xy.y * matrix.c   matrix.e;
  const y = xy.x * matrix.b   xy.y * matrix.d   matrix.f;

  // Return the new transform matrix
  return `matrix(${matrix.a}, ${matrix.b}, ${matrix.c}, ${matrix.d}, ${x}, ${y})`;
});

return (
  <svg viewBox={`0 0 ${viewBoxWidth} ${viewBoxHeight}`}>
    <motion.circle
      drag
      cx="5"
      cy="5"
      r="0.5"
      strokeWidth="0.1"
      style={{ transform: transformMatrix }}
    />
  </svg>
);

In this example, the useTransform hook is used to create a motion value that tracks the current position of the element being dragged. This motion value is then used to calculate the new position of the element based on the movement of the mouse cursor. The updated transform matrix is then applied to the element using the style property of the motion.circle component.

CodePudding user response:

It is possible to use the property in Framer Motion to calculate the movement of the SVG element relative to the viewbox。 To do this, you will need to use the property to define the bounds within which the element can be dragged。 You can then use the property to adjust the elasticity of the element's movement.dragdragConstraints movement.dragElastic

Here is an example of how this could be implemented in your code:

<svg viewBox="0 0 40 20">
  <motion.circle
    drag
    dragConstraints={{ left: 0, right: 40, top: 0, bottom: 20 }}
    dragElastic={0.1}
    cx="5"
    cy="5"
    r="0.5"
    strokeWidth="0.1"
  />
</svg>

This will constrain the movement of the element to the bounds of the viewbox and give it some elasticity so that it bounces back when released。 <motion.circle>

Hope this helps!

  • Related