diff --git a/apps/docs/docs/image-svg.md b/apps/docs/docs/image-svg.md
index e936634779..b94afabf68 100644
--- a/apps/docs/docs/image-svg.md
+++ b/apps/docs/docs/image-svg.md
@@ -22,6 +22,8 @@ If the root dimensions are in absolute units, the width/height properties have n
The `ImageSVG` component doesn't follow the same painting rules as other components.
[see applying effects](#applying-effects).
+On Web, the Current Transformation Matrix (CTM) won't be applied to `ImageSVG` because the component relies on browser SVG rendering instead of CanvasKit. The SVG is rendered as a hidden image element and then imported as image data. This means transformations need to be prepared beforehand or applied through the `Group` component with explicit transform matrices.
+
:::
### Example
diff --git a/apps/remotion/src/Playground/Playground.tsx b/apps/remotion/src/Playground/Playground.tsx
index f2c1a78586..4468546694 100644
--- a/apps/remotion/src/Playground/Playground.tsx
+++ b/apps/remotion/src/Playground/Playground.tsx
@@ -1,4 +1,12 @@
import React from "react";
+import {
+ fitbox,
+ Group,
+ ImageSVG,
+ rect,
+ Skia,
+ useSVG,
+} from "@shopify/react-native-skia";
import { Background, Canvas } from "../components";
import { makeAnimation, wait } from "../components/animations/Animations";
@@ -11,7 +19,21 @@ const state = makeAnimation(function* ({}) {
export const durationInFrames = state.duration;
+const SVG_URL =
+ "https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg";
+
export const Playground = () => {
+ const svg = useSVG(SVG_URL);
+ const svg2 = Skia.SVG.MakeFromString(
+ `
+
+ `
+ )!;
+
+ const src = rect(0, 0, svg2.width(), svg2.height());
+ const dst = rect(0, 0, 400, 400);
return (
<>
>
);
diff --git a/packages/skia/src/skia/core/SVG.web.ts b/packages/skia/src/skia/core/SVG.web.ts
index c0de0a8bdc..cbb72ea002 100644
--- a/packages/skia/src/skia/core/SVG.web.ts
+++ b/packages/skia/src/skia/core/SVG.web.ts
@@ -1,36 +1,46 @@
+import { useEffect, useState } from "react";
+
import { Skia } from "../Skia";
-import type { DataSourceParam } from "../types";
+import type { DataSourceParam, SkSVG } from "../types";
export const useSVG = (
source: DataSourceParam,
onError?: (err: Error) => void
) => {
+ const [svg, setSVG] = useState(null);
if (source === null || source === undefined) {
throw new Error(`Invalid svg data source. Got: ${source}`);
}
- let src: string;
- if (typeof source === "string") {
- src = source;
- } else if (
- typeof source === "object" &&
- "default" in source &&
- typeof source.default === "string"
- ) {
- src = source.default;
- } else if (typeof source === "object" && "uri" in source) {
- src = source.uri;
- } else {
- throw new Error(
- `Invalid svg data source. Make sure that the source resolves to a string. Got: ${JSON.stringify(
- source,
- null,
- 2
- )}`
- );
- }
- const svg = Skia.SVG.MakeFromString(src);
- if (svg === null && onError !== undefined) {
- onError(new Error("Failed to create SVG from source."));
- }
+ useEffect(() => {
+ (async () => {
+ let src: string;
+ if (typeof source === "string") {
+ src = source;
+ } else if (
+ typeof source === "object" &&
+ "default" in source &&
+ typeof source.default === "string"
+ ) {
+ src = source.default;
+ } else if (typeof source === "object" && "uri" in source) {
+ src = source.uri;
+ } else {
+ throw new Error(
+ `Invalid svg data source. Make sure that the source resolves to a string. Got: ${JSON.stringify(
+ source,
+ null,
+ 2
+ )}`
+ );
+ }
+ const result = await fetch(src);
+ const svgStr = await result.text();
+ const newSvg = Skia.SVG.MakeFromString(svgStr);
+ setSVG(newSvg);
+ if (newSvg === null && onError !== undefined) {
+ onError(new Error("Failed to create SVG from source."));
+ }
+ })();
+ }, [onError, source]);
return svg;
};
diff --git a/packages/skia/src/skia/web/JsiSkCanvas.ts b/packages/skia/src/skia/web/JsiSkCanvas.ts
index 988bbc353b..63d147ba57 100644
--- a/packages/skia/src/skia/web/JsiSkCanvas.ts
+++ b/packages/skia/src/skia/web/JsiSkCanvas.ts
@@ -305,7 +305,9 @@ export class JsiSkCanvas
);
}
- drawSvg(svg: SkSVG, _width?: number, _height?: number) {
+ drawSvg(svg: SkSVG, width?: number, height?: number) {
+ const ctm = this.ref.getLocalToDevice();
+ console.log({ ctm, width, height });
const image = this.CanvasKit.MakeImageFromCanvasImageSource(
(svg as JsiSkSVG).ref
);