Skip to content

Commit

Permalink
feat: add svgOrigin prop #894
Browse files Browse the repository at this point in the history
  • Loading branch information
daybrush committed Apr 26, 2023
1 parent a00ab2a commit 619d57d
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 6 deletions.
28 changes: 23 additions & 5 deletions packages/react-moveable/src/ables/Origin.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
import { prefix, getControlTransform } from "../utils";
import { prefix, getControlTransform, calculatePosition, convertTransformOriginArray } from "../utils";
import { Renderer, OriginOptions, MoveableManagerInterface } from "../types";
import { makeAble } from "./AbleManager";
import { minus } from "@scena/matrix";

export default makeAble("origin", {
props: ["origin", "svgOrigin"] as const,
render(moveable: MoveableManagerInterface<OriginOptions>, React: Renderer): any[] {
const { zoom } = moveable.props;
const { beforeOrigin, rotation } = moveable.getState();
const { zoom, svgOrigin, groupable } = moveable.props;
const {
beforeOrigin, rotation, svg, allMatrix, is3d,
left, top, offsetWidth, offsetHeight,
} = moveable.getState();

let originStyle!: Record<string, any>;

if (!groupable && svg && svgOrigin) {
const [originX, originY] = convertTransformOriginArray(svgOrigin, offsetWidth, offsetHeight);
const n = is3d ? 4 : 3;
const result = calculatePosition(
allMatrix,
[originX, originY],
n,
);
originStyle = getControlTransform(rotation, zoom!, minus(result, [left, top]));
} else {
originStyle = getControlTransform(rotation, zoom!, beforeOrigin);
}
return [
<div className={prefix("control", "origin")}
style={getControlTransform(rotation, zoom!, beforeOrigin)} key="beforeOrigin"></div>,
<div className={prefix("control", "origin")} style={originStyle} key="beforeOrigin"></div>,
];
},
});
Expand Down
3 changes: 2 additions & 1 deletion packages/react-moveable/src/ables/Rotatable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
calculatePosition, fillEndParams, getRotationRad, getRefTargets,
catchEvent, getProps, calculateMoveableClientPositions,
fillAfterTransform,
getTotalOrigin,
} from "../utils";
import {
IObject, hasClass, getRad,
Expand Down Expand Up @@ -539,7 +540,7 @@ export default {
);
}

setFixedPosition(state.transformOrigin);
setFixedPosition(getTotalOrigin(moveable));
const params = fillParams<OnRotateStart>(moveable, e, {
set: (rotatation: number) => {
datas.startValue = rotatation * Math.PI / 180;
Expand Down
5 changes: 5 additions & 0 deletions packages/react-moveable/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,11 @@ export interface OriginOptions {
* @default true
*/
origin?: boolean;
/**
* Sets the transform origin based on the svg target. If not set, it is set as the transform origin based on the owner of svg.
* @default ""
*/
svgOrigin?: string;
}
/**
* @typedef
Expand Down
22 changes: 22 additions & 0 deletions packages/react-moveable/src/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,28 @@ export function getClientRect(el: HTMLElement | SVGElement, isExtends?: boolean)
}
return rect;
}


export function getTotalOrigin(moveable: MoveableManagerInterface<any>) {
const {
groupable,
svgOrigin,
} = moveable.props;
const {
offsetWidth,
offsetHeight,
svg,
transformOrigin,
} = moveable.getState();

if (!groupable && svg && svgOrigin) {
return convertTransformOriginArray(svgOrigin, offsetWidth, offsetHeight);
}

return transformOrigin;
}


export function getTotalDirection(
parentDirection: number[],
isPinch: boolean,
Expand Down
6 changes: 6 additions & 0 deletions packages/react-moveable/stories/4-SVG/0-SVG.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ export const SVGTargetG = add("SVGElement with target G tag", {
app: require("./ReactSVGTargetGApp").default,
text: require("!!raw-loader!./ReactSVGTargetGApp").default,
});


export const SVGOrigin = add("SVGPathElement with center origin", {
app: require("./ReactOriginApp").default,
text: require("!!raw-loader!./ReactOriginApp").default,
});
41 changes: 41 additions & 0 deletions packages/react-moveable/stories/4-SVG/ReactOriginApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as React from "react";
import Moveable from "@/react-moveable";

export default function App(props: Record<string, any>) {
return (
<div className="root">
<div className="container" style={{
transformOrigin: "0 0",
transform: `scale(${props.containerScale})`,
}}>
<svg viewBox="0 0 200 200" style={{
border: "1px solid black",
width: "200px",
height: "200px",
}}>
<path d="M 0 0 L 200 0 L 200 200 z" style={{
fill: "white",
stroke: "red",
strokeWidth: 2,
}} />
</svg>
<Moveable
target={"path"}
draggable={true}
rotatable={true}
scalable={true}
svgOrigin="50% 50%"
// onRotateStart={e => {
// e.setFixedDirection([0, 0]);
// }}
// onScaleStart={e => {
// e.setFixedDirection([0, 0]);
// }}
onRender={e => {
e.target.style.cssText += e.cssText;
}}
/>
</div>
</div>
);
}

0 comments on commit 619d57d

Please sign in to comment.