Spaces:
Runtime error
Runtime error
const BlockType = require('../../extension-support/block-type'); | |
const ArgumentType = require('../../extension-support/argument-type'); | |
const Cast = require('../../util/cast'); | |
const uid = require('../../util/uid'); | |
const Textures = { | |
Snow: require('./snow.png'), | |
Light: require('./light.png'), | |
Present: require('./present.png'), | |
}; | |
/** | |
* Class for Extension blocks | |
* @constructor | |
*/ | |
class Extension { | |
constructor(runtime) { | |
/** | |
* The runtime instantiating this block package. | |
* @type {Runtime} | |
*/ | |
this.runtime = runtime; | |
/** | |
* @type {HTMLDivElement} | |
*/ | |
this.mainContainer = null; | |
/** | |
* @type {HTMLCanvasElement} | |
*/ | |
this.mainCanvas = null; | |
/** | |
* canvas context | |
* @type {CanvasRenderingContext2D} | |
*/ | |
this.ctx = null; | |
this.initialize(); | |
this.snowParticles = {}; | |
this.lights = {}; | |
this.runtime.on('RUNTIME_STEP_START', () => { | |
const viewBox = this.mainContainer.getBoundingClientRect(); | |
for (const particleId in this.snowParticles) { | |
const particle = this.snowParticles[particleId]; | |
const element = particle.element; | |
element.style.left = `calc(${particle.origin}% + ${particle.x}px)`; | |
particle.x -= 3; | |
const y = Cast.toNumber(element.style.top.replace('px', '')) + particle.speed; | |
element.style.top = `${y}px`; | |
if (element.getBoundingClientRect().right < 0 || y > viewBox.height) { | |
element.remove(); | |
delete this.snowParticles[particleId]; | |
} | |
} | |
this.drawLightBackground(); | |
}); | |
this.runtime.on('PROJECT_STOP_ALL', () => { | |
this.ctx.clearRect(0, 0, this.mainCanvas.width, this.mainCanvas.height); | |
this.clearSnow(); | |
this.removeLights(); | |
}); | |
} | |
initialize() { | |
const mainContainer = document.body.appendChild(document.createElement("div")); | |
mainContainer.style = 'position: absolute;' | |
+ 'left: 0; top: 0; width: 100%; height: 100%;' | |
+ 'pointer-events: none; overflow: hidden;' | |
+ 'z-index: 1000009;'; | |
this.mainContainer = mainContainer; | |
const mainCanvas = mainContainer.appendChild(document.createElement("canvas")); | |
mainCanvas.style = 'position: absolute;' | |
+ 'left: 0; top: 0; width: 100%; height: 100%;' | |
+ 'pointer-events: none; background: none;' | |
+ 'border: 0; margin: 0; padding: 0;' | |
+ 'z-index: 999999;'; | |
this.mainCanvas = mainCanvas; | |
mainCanvas.width = 1280; | |
mainCanvas.height = 720; | |
const canvasContext = mainCanvas.getContext('2d'); | |
this.ctx = canvasContext; | |
} | |
/** | |
* @returns {object} metadata for this extension and its blocks. | |
*/ | |
getInfo() { | |
return { | |
id: 'jgChristmas', | |
name: 'Christmas', | |
color1: '#ff0000', | |
color2: '#00ff00', | |
blockIconURI: require('./icon.png'), | |
blocks: [ | |
{ | |
opcode: 'snow', | |
text: 'snow', | |
blockType: BlockType.COMMAND | |
}, | |
{ | |
opcode: 'clearSnow', | |
text: 'clear snow', | |
blockType: BlockType.COMMAND | |
}, | |
// { | |
// opcode: 'addPresent', | |
// text: 'add present', | |
// blockType: BlockType.COMMAND | |
// }, | |
// { | |
// opcode: 'removePresents', | |
// text: 'remove all presents', | |
// blockType: BlockType.COMMAND | |
// }, | |
{ | |
opcode: 'addLight', | |
text: 'add light', | |
blockType: BlockType.COMMAND | |
}, | |
{ | |
opcode: 'removeLights', | |
text: 'remove all lights', | |
blockType: BlockType.COMMAND | |
}, | |
] | |
}; | |
} | |
snow() { | |
const snowImage = this.mainContainer.appendChild(document.createElement("img")); | |
const size = Math.round(8 + (Math.random() * 16)); | |
const opacity = 0.5 + (Math.random() / 2); | |
const originX = Math.random() * 150; | |
snowImage.style = 'position: absolute;' | |
+ `left: ${originX}%; top: -${size}px; width: ${size}px; height: ${size}px;` | |
+ `pointer-events: none; opacity: ${opacity};` | |
+ 'z-index: 1000008;'; | |
snowImage.src = Textures.Snow; | |
const id = uid(); | |
this.snowParticles[id] = { | |
element: snowImage, | |
origin: originX, | |
x: 0, | |
size: size, | |
speed: 2 + Math.random() * 6 | |
}; | |
} | |
removeLights() { | |
this.ctx.clearRect(0, 0, this.mainCanvas.width, this.mainCanvas.height); | |
for (const particleId in this.lights) { | |
const particle = this.lights[particleId]; | |
const element = particle.element; | |
element.remove(); | |
delete this.lights[particleId]; | |
} | |
} | |
addLight() { | |
const lightImage = this.mainContainer.appendChild(document.createElement("img")); | |
const viewBox = this.mainContainer.getBoundingClientRect(); | |
const originX = Math.random() * viewBox.width; | |
const originY = Math.random() * viewBox.height; | |
const direction = Math.random() * 360; | |
lightImage.style = 'position: absolute;' | |
+ `left: 0; top: 0; width: 70px; height: 70px;` | |
+ `transform: translate(${originX}px, ${originY}px) rotate(${direction}deg);` | |
+ `transform-origin: 34px 41px; pointer-events: none;` | |
+ 'z-index: 1000005;'; | |
lightImage.src = Textures.Light; | |
const id = uid(); | |
this.lights[id] = { | |
element: lightImage, | |
x: originX, | |
y: originY | |
}; | |
this.drawLightBackground(); | |
let filterGreen = false; | |
setInterval(() => { | |
lightImage.style.filter = filterGreen ? 'hue-rotate(90deg) brightness(1.5)' : ''; | |
filterGreen = !filterGreen; | |
}, 700); | |
} | |
drawLightBackground() { | |
const canvas = this.mainCanvas; | |
const viewBox = canvas.getBoundingClientRect(); | |
const ctx = this.ctx; | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
ctx.strokeStyle = '#3D5C3A'; | |
ctx.lineWidth = 1; | |
ctx.moveTo(0, 70); | |
ctx.beginPath(); | |
for (const particleId in this.lights) { | |
const particle = this.lights[particleId]; | |
ctx.lineTo(((particle.x + 34) / viewBox.width) * 1280, ((particle.y + 41) / viewBox.height) * 720); | |
ctx.moveTo(((particle.x + 34) / viewBox.width) * 1280, ((particle.y + 41) / viewBox.height) * 720); | |
ctx.stroke(); | |
} | |
} | |
clearSnow() { | |
for (const particleId in this.snowParticles) { | |
const particle = this.snowParticles[particleId]; | |
const element = particle.element; | |
element.remove(); | |
delete this.snowParticles[particleId]; | |
} | |
} | |
addPresent() { | |
} | |
} | |
module.exports = Extension; | |