Skip to content

Commit

Permalink
fix: fix svg origin for viewbox and foreignbox #1048
Browse files Browse the repository at this point in the history
  • Loading branch information
daybrush committed Dec 2, 2023
1 parent 786fc0c commit 6c27742
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 8 deletions.
35 changes: 31 additions & 4 deletions packages/react-moveable/src/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ export function getOffsetInfo(
// offsetParent is the parentElement if the target's zoom is not 1 and not absolute.
!isParent && checkZoom && targetZoom !== 1 && targetPosition && targetPosition !== "absolute"
|| tagName === "svg"
|| tagName === "foreignobject"
|| position !== "static"
|| (transform && transform !== "none")
|| willChange === "transform"
Expand Down Expand Up @@ -240,7 +241,7 @@ export function getOffsetPosInfo(
let origin: number[];
let targetOrigin: number[];
// inner svg element
if (!hasOffset && (tagName !== "svg" || (target as SVGElement).ownerSVGElement)) {
if (!hasOffset && (tagName !== "svg" || (el as SVGElement).ownerSVGElement)) {
origin = IS_WEBKIT605
? getBeforeTransformOrigin(el as SVGElement)
: getTransformOriginArray(getStyle("transformOrigin")).map(pos => parseFloat(pos));
Expand All @@ -262,7 +263,9 @@ export function getOffsetPosInfo(
}
} else {
origin = getTransformOriginArray(getStyle("transformOrigin")).map(pos => parseFloat(pos));

targetOrigin = origin.slice();
// console.log(getStyle("transformOrigin"), targetOrigin);
}
return {
tagName,
Expand Down Expand Up @@ -409,19 +412,43 @@ export function getSVGGraphicsOffset(
origin: number[],
isGTarget?: boolean,
) {
if (!el.getBBox || !isGTarget && el.tagName.toLowerCase() === "g") {
const tagName = el.tagName.toLowerCase();

if (!el.getBBox || !isGTarget && tagName === "g") {
return [0, 0, 0, 0];
}
const getStyle = getCachedStyle(el);
const isFillBox = getStyle("transform-box") === "fill-box";

const bbox = el.getBBox();
const viewBox = getSVGViewBox(el.ownerSVGElement!);
const left = bbox.x - viewBox.x;
const top = bbox.y - viewBox.y;
let x = bbox.x;
let y = bbox.y;

// x, y가 0으로 나타나는 버그
if (tagName === "foreignobject" && (!x && !y)) {
x = parseFloat(el.getAttribute("x")!) || 0;
y = parseFloat(el.getAttribute("y")!) || 0;
}
const left = x - viewBox.x;
const top = y - viewBox.y;
const originX = isFillBox ? origin[0] : origin[0] - left;
const originY = isFillBox ? origin[1] : origin[1] - top;

// if (isFillBox) {
// const bbox = (el as SVGGraphicsElement).getBBox();
// const x = parseFloat(getStyle("x")) || bbox.x;
// const y = parseFloat(getStyle("y")) || bbox.y;

// const xScale = bbox.x / x;
// const yScale = bbox.y / y;

// console.log(x, y);

// originX *= xScale;
// originY *= yScale;
// }

return [left, top, originX, originY];
}
export function calculatePosition(matrix: number[], pos: number[], n: number) {
Expand Down
3 changes: 2 additions & 1 deletion packages/react-moveable/src/utils/getMatrixStackInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ export function getMatrixStackInfo(
offsetTop,
] = offsetPos;

if (tagName === "svg" && !(target as SVGSVGElement).ownerSVGElement && targetMatrix) {
// no target with svg
if (tagName === "svg" && !(el as SVGSVGElement).ownerSVGElement && targetMatrix) {
// scale matrix for svg's SVGElements.
matrixes.push({
type: "target",
Expand Down
14 changes: 14 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 @@ -63,3 +63,17 @@ export const SVGFillboxOrigin = add("SVGPathElement with center origin and trans
app: require("./ReactOriginFillboxApp").default,
text: require("!!raw-loader!./ReactOriginFillboxApp").default,
});




export const SVGForeignObject = add("SVGForeignObject", {
app: require("./ReactSVGForeignObjectApp").default,
text: require("!!raw-loader!./ReactSVGForeignObjectApp").default,
});


export const SVGForeignObjectInner = add("SVGForeignObject div", {
app: require("./ReactSVGForeignObjectInnerApp").default,
text: require("!!raw-loader!./ReactSVGForeignObjectInnerApp").default,
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ export default function App(props: Record<string, any>) {
style={{
fill: "red",
transformBox: "fill-box",
transform: "",
strokeWidth: "0",
transformOrigin: "50% 50%",
}}
transform="rotate(45)"
{...{ "transform-origin": "50% 50%" }}
// {...{ "transform-origin": "50% 50%" }}
/>
</svg>
<Moveable
Expand Down
5 changes: 4 additions & 1 deletion packages/react-moveable/stories/4-SVG/ReactPathApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ export default function App(props: Record<string, any>) {
transformOrigin: "0 0",
transform: `scale(${props.containerScale})`,
}}>
<svg viewBox="0 0 200 200" style={{
<svg viewBox="0 0 400 400" style={{
position: "relative",
left: "200px",
top: "200px",
border: "1px solid black",
width: "200px",
height: "200px",
Expand Down
23 changes: 23 additions & 0 deletions packages/react-moveable/stories/4-SVG/ReactSVGForeignObjectApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from "react";
import Moveable from "@/react-moveable";

export default function App() {
return (
<div className="root">
<div className="container">
<svg viewBox="0 0 86 54">
<foreignObject x="10" y="10" width="20" height="20">
<div>Hi</div>
</foreignObject>
</svg>
<Moveable
target={"foreignObject"}
draggable={true}
onRender={e => {
e.target.style.cssText += e.cssText;
}}
/>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from "react";
import Moveable from "@/react-moveable";

export default function App() {
return (
<div className="root">
<div className="container">
<svg viewBox="0 0 86 54">
<foreignObject x="10" y="10" width="20" height="20">
<div>Hi</div>
</foreignObject>
</svg>
<Moveable
target={"foreignObject div"}
draggable={true}
onRender={e => {
e.target.style.cssText += e.cssText;
}}
/>
</div>
</div>
);
}
3 changes: 3 additions & 0 deletions packages/react-moveable/stories/4-SVG/ReactSVGSVGApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export default function App(props: Record<string, any>) {
transform: `scale(${props.containerScale})`,
}}>
<svg viewBox="0 0 200 200" ref={targetRef} style={{
position: "relative",
left: "200px",
top: "200px",
border: "1px solid black",
width: "200px",
height: "200px",
Expand Down

0 comments on commit 6c27742

Please sign in to comment.