Skip to content

Commit

Permalink
iframe: various fixes (#955)
Browse files Browse the repository at this point in the history
- update default page
- add resize behavior option
- fix position after custom stage size changes
  • Loading branch information
GarboMuffin authored Aug 26, 2023
1 parent 01a6f2f commit ed74f58
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 10 deletions.
67 changes: 58 additions & 9 deletions extensions/iframe.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

/** @type {HTMLIFrameElement|null} */
let iframe = null;
let overlay = null;

const featurePolicy = {
accelerometer: "'none'",
Expand Down Expand Up @@ -39,32 +40,48 @@
let width = -1; // negative means default
let height = -1; // negative means default
let interactive = true;
let resizeBehavior = "scale";

const updateFrameAttributes = () => {
if (!iframe) {
return;
}

iframe.style.pointerEvents = interactive ? "auto" : "none";

const { stageWidth, stageHeight } = Scratch.vm.runtime;
const effectiveWidth = width >= 0 ? width : stageWidth;
const effectiveHeight = height >= 0 ? height : stageHeight;
iframe.style.width = `${effectiveWidth}px`;
iframe.style.height = `${effectiveHeight}px`;

let transform = "";
transform += `translate(${stageWidth / 2 - effectiveWidth / 2 + x}px,${
stageHeight / 2 - effectiveHeight / 2 - y
}px)`;
iframe.style.transform = transform;
if (resizeBehavior === "scale") {
iframe.style.width = `${effectiveWidth}px`;
iframe.style.height = `${effectiveHeight}px`;

iframe.style.pointerEvents = interactive ? "auto" : "none";
iframe.style.transform = `translate(${-effectiveWidth / 2 + x}px, ${
-effectiveHeight / 2 - y
}px)`;
iframe.style.top = "0";
iframe.style.left = "0";
} else {
// As the stage is resized in fullscreen mode, only % can be relied upon
iframe.style.width = `${(effectiveWidth / stageWidth) * 100}%`;
iframe.style.height = `${(effectiveHeight / stageHeight) * 100}%`;

iframe.style.transform = "";
iframe.style.top = `${(0.5 - effectiveHeight / 2 / stageHeight) * 100}%`;
iframe.style.left = `${(0.5 - effectiveWidth / 2 / stageWidth) * 100}%`;
}
};

const getOverlayMode = () =>
resizeBehavior === "scale" ? "scale-centered" : "manual";

const createFrame = (src) => {
iframe = document.createElement("iframe");
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.border = "none";
iframe.style.position = "absolute";
iframe.setAttribute("sandbox", "allow-scripts allow-same-origin");
iframe.setAttribute(
"allow",
Expand All @@ -75,11 +92,13 @@
iframe.setAttribute("allowtransparency", "true");
iframe.setAttribute("allowtransparency", "true");
iframe.setAttribute("src", src);
Scratch.renderer.addOverlay(iframe, "scale");

overlay = Scratch.renderer.addOverlay(iframe, getOverlayMode());
updateFrameAttributes();
};

Scratch.vm.on("STAGE_SIZE_CHANGED", updateFrameAttributes);

class IframeExtension {
getInfo() {
return {
Expand Down Expand Up @@ -191,6 +210,17 @@
},
},
},
{
opcode: "setResize",
blockType: Scratch.BlockType.COMMAND,
text: "set iframe resize behavior to [RESIZE]",
arguments: {
RESIZE: {
type: Scratch.ArgumentType.STRING,
menu: "resizeMenu",
},
},
},
],
menus: {
getMenu: {
Expand All @@ -203,12 +233,17 @@
"width",
"height",
"interactive",
"resize behavior",
],
},
interactiveMenu: {
acceptReporters: true,
items: ["true", "false"],
},
resizeMenu: {
acceptReporters: true,
items: ["scale", "viewport"],
},
},
};
}
Expand Down Expand Up @@ -246,6 +281,7 @@
if (iframe) {
Scratch.renderer.removeOverlay(iframe);
iframe = null;
overlay = null;
}
}

Expand All @@ -266,6 +302,8 @@
return height >= 0 ? height : Scratch.vm.runtime.stageHeight;
} else if (MENU === "interactive") {
return interactive;
} else if (MENU === "resize behavior") {
return resizeBehavior;
} else {
return "";
}
Expand Down Expand Up @@ -295,6 +333,17 @@
interactive = Scratch.Cast.toBoolean(INTERACTIVE);
updateFrameAttributes();
}

setResize({ RESIZE }) {
if (RESIZE === "scale" || RESIZE === "viewport") {
resizeBehavior = RESIZE;
if (overlay) {
overlay.mode = getOverlayMode();
Scratch.renderer._updateOverlays();
updateFrameAttributes();
}
}
}
}

Scratch.extensions.register(new IframeExtension());
Expand Down
2 changes: 1 addition & 1 deletion website/hello.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h1>It works!</h1>
<p>Transparency is supported, so you can display the project behind the frame as long as the page doesn't explicitly set a background color.</p>
<p>You can also use JavaScript and most other Web APIs, like this:</p>
<p><button class="clickme">Click me!</button></p>
<p>Due to browser security measures blocks like "mouse x" and "mouse down?" will not work while the cursor is over the frame unless you disable interactivity.</p>
<p>Due to browser security measures, blocks like "mouse x" and "mouse down?" will not work while the cursor is over the frame unless you use the disable interactivity block.</p>
<p>Many websites also block other sites from embedding them for security reasons.</p>
</main>
<script>
Expand Down

0 comments on commit ed74f58

Please sign in to comment.