隐藏编辑器中所有积木
慕然科技官网ccwmoran.github.io
(function(Scratch) {
'use strict';
const Blockly = Scratch.Blockly;
class BiyuanExtension {
constructor() {
this.workspace = null;
this.original = {
domToBlock: null,
setVisible: null,
contextMenu: null
};
this.observer = null;
this.checkInterval = null;
}
getInfo() {
return {
id: 'hide',
name: '慕然科技的积木隐藏',
color: '#00704A',
blocks: []
};
}
applyProtection() {
// 保存原始引用
const originalContextMenu = Blockly.ContextMenu;
// 劫持积木创建
this.original.domToBlock = Blockly.Xml.domToBlock;
Blockly.Xml.domToBlock = (xml, ws) => {
const block = this.original.domToBlock(xml, ws);
this.superHide(block);
return block;
};
// 重写可见性设置
this.original.setVisible = Blockly.Block.prototype.setVisible;
Blockly.Block.prototype.setVisible = function(visible) {
return this.original.setVisible.call(this, visible && false);
};
// 监控DOM变化
this.observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
const element = mutation.target;
if (element.classList?.contains('blocklyBlockCanvas') &&
element.style.display !== 'none') {
element.style.display = 'none';
}
});
});
// 修复this指向问题
const self = this;
this.original.contextMenu = originalContextMenu;
Blockly.ContextMenu = function(...args) {
const instance = new originalContextMenu(...args);
instance.show = () => {};
return instance;
};
}
superHide(block) {
// 多层隐藏技术
block.setVisible(false);
const svgRoot = block.getSvgRoot();
if (svgRoot) {
svgRoot.style.display = 'none';
svgRoot.setAttribute('visibility', 'hidden');
// 添加DOM监控
this.observer.observe(svgRoot, {
attributes: true,
attributeFilter: ['style', 'visibility']
});
}
}
onInit() {
this.workspace = Scratch.vm.runtime.work space;
this.applyProtection();
// 初始隐藏
this.workspace.getAllBlocks().forEach(block => {
this.superHide(block);
});
// 定时检查
this.checkInterval = setInterval(() => {
this.workspace.getAllBlocks().forEach(block => {
if (block.isVisible() ||
(block.getSvgRoot()?.style.display !== 'none') ||
(block.getSvgRoot()?.getAttribute('visibility') === 'visible')) {
this.superHide(block);
}
});
}, 50);
}
onUnload() {
// 恢复原始环境
Blockly.Xml.domToBlock = this.original.domToBlock;
if (Blockly.Block.prototype.setVisible) {
Blockly.Block.prototype.setVisible = this.original.setVisible;
}
Blockly.ContextMenu = this.original.contextMenu;
clearInterval(this.checkInterval);
this.observer?.disconnect();
// 恢复所有元素
this.workspace.getAllBlocks().forEach(block => {
const svgRoot = block.getSvgRoot();
if (svgRoot) {
svgRoot.style.display = '';
svgRoot.removeAttribute('visibility');
}
block.setVisible(true);
});
this.workspace.resize();
}
}
const ext = new BiyuanExtension();
Scratch.extensions.register(ext);
ext.runtime.once('PROJECT_LOADED', () => ext.onInit());
ext.runtime.once('EXTENSION_UNLOADED', () => ext.onUnload());
})(Scratch);