Files
001code-html--cocos/scratch-blocks/core/intersection_observer.js
刘宇飞 6e0a1fbcbb Initial commit of 001code-html Scratch frontend project.
Includes scratch-gui, scratch-vm, scratch-blocks, scratch-render, scratch-l10n, and deployment config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 15:37:45 +08:00

103 lines
3.0 KiB
JavaScript

'use strict';
goog.provide('Blockly.IntersectionObserver');
Blockly.IntersectionObserver = function(workspace) {
this.workspace = workspace;
this.observing = [];
this.intersectionCheckQueued = false;
this.checkForIntersections = this.checkForIntersections.bind(this);
};
Blockly.IntersectionObserver.prototype.observe = function(block) {
var index = this.observing.indexOf(block);
if (index === -1) {
this.observing.push(block);
}
};
Blockly.IntersectionObserver.prototype.unobserve = function(block) {
var index = this.observing.indexOf(block);
if (index !== -1) {
this.observing = this.observing.filter(function(i) {
return i !== block;
});
}
};
Blockly.IntersectionObserver.prototype.dispose = function() {
this.observing = [];
this.workspace = null;
};
Blockly.IntersectionObserver.prototype.queueIntersectionCheck = function() {
if (this.intersectionCheckQueued) {
return;
}
this.intersectionCheckQueued = true;
// Check for intersections on the next microtick
// Prefer to use the native method when available, otherwise fallback to a Promise-based polyfill
if (window.queueMicrotask) {
window.queueMicrotask(this.checkForIntersections);
} else {
// eslint-disable-next-line no-undef
Promise.resolve().then(this.checkForIntersections);
}
};
Blockly.IntersectionObserver.prototype.checkForIntersections = function() {
this.intersectionCheckQueued = false;
if (!this.workspace) {
return;
}
var workspace = this.workspace;
var workspaceScale = workspace.scale;
var RTL = workspace.RTL;
var workspaceHeight = workspace.getParentSvg().height.baseVal.value;
var workspaceWidth = workspace.getParentSvg().width.baseVal.value;
if (workspace.isDragSurfaceActive_) {
var canvasPos = Blockly.utils.getRelativeXY(workspace.workspaceDragSurface_.SVG_);
} else {
var canvasPos = Blockly.utils.getRelativeXY(workspace.getCanvas());
}
// Allow blocks to go slightly offscreen so that effects such as glow do not get cut off.
var margin = 12 * workspaceScale;
for (var i = 0; i < this.observing.length; i++) {
var block = this.observing[i];
var blockPos = block.getRelativeToSurfaceXY();
var blockSize = null;
if (RTL) {
blockSize = block.getHeightWidth();
blockPos.x -= blockSize.width;
blockSize.width *= workspaceScale;
blockSize.height *= workspaceScale;
}
blockPos.x *= workspaceScale;
blockPos.y *= workspaceScale;
var visible = true;
if (canvasPos.y + blockPos.y - margin > workspaceHeight) {
visible = false;
} else if (canvasPos.x + blockPos.x - margin > workspaceWidth) {
visible = false;
} else {
if (!blockSize) {
blockSize = block.getHeightWidth();
blockSize.width *= workspaceScale;
blockSize.height *= workspaceScale;
}
if (canvasPos.x + blockPos.x + blockSize.width + margin < 0) {
visible = false;
} else if (canvasPos.y + blockPos.y + blockSize.height + margin < 0) {
visible = false;
}
}
block.setIntersects(visible);
}
};