-
• #2
Yes, I think likely what's happening is the IDE uploads the code and then doesn't get a response after a second or so, so it issues a Ctrl-C to break out of it.
You could do:
setTimeout(function() { invertCircle(g.getWidth() / 2, g.getHeight() / 2, 30); }, 1000);
to run the command after a delay so the IDE can upload the code fine and see a response, but then the code happens after.
BUT: iterating over every pixel is always going to be really slow I'm afraid - it's probably not something you want to be doing if there's any way to avoid it. What I'd suggest is actually making two images - one with what you want to draw and one with the circle, and XORing the actual binary data of the image together.
ga = Graphics.createArrayBuffer(176,176,1,{msb:true}); gb = Graphics.createArrayBuffer(176,176,1,{msb:true}); var ba = new Uint32Array(ga.buffer); var bb = new Uint32Array(gb.buffer); ga.setFont("Vector:80").drawString("Hello"); gb.fillCircle(40,40,40); // define this once so JIT only runs once function xor(a,i) { "jit" return a ^ bb[i]; } function update() { var t = getTime(); E.mapInPlace(ba, ba, xor); g.drawImage(ga); // draws with current FG and BG colors print("took",getTime()-t,"sec"); } update();
There are other ways to do it (eg compiled code) but this way a relatively straightforward.
It still takes ~0.4sec to do the entire screen, but if you only wanted part of the screen done then it'd be a bit faster.
I was considering adding different draw styles (add/xor/or/etc) to the Graphics lib which would really help with this, but I'm afraid that isn't implemented yet.
-
• #3
I was trying to implement something similar for a stop watch app except mine was a rectangle, not a circle, so I was able to use g.setClipRect.
Maybe there could also be a g.setClipCircle?
-
• #4
That feels like it's quite a rare thing to want to do - I could imagine maybe having a 'mask' image where you set the areas you want to write to though?
...but personally I'd have thought that extending
drawImages
would be better - so we could allow each image to have a 'blend mode', much like you might blend layers in photoshop/Gimp.In the case above, you could have an XOR mode, but you could also do AND/OR or even just using an image to set the transparency, which would do what you want too
-
• #5
Yeah, I was using setClipRect as a mask essentially and layering the draws to create the animation.
const SCREEN_WIDTH = g.getWidth(); const SCREEN_HEIGHT = g.getHeight(); const BOX_HEIGHT = 50; const NUMBER_SIZE = 30; const ANIMATION_DURATION = 3000; const BOX_DIMENSIONS = { left: 0, top: SCREEN_HEIGHT / 2 - BOX_HEIGHT / 2, width: SCREEN_WIDTH, height: BOX_HEIGHT }; let numberValue = 0; let startTime = 0; let animationInterval; function setRect(method) { g[method](BOX_DIMENSIONS.left, BOX_DIMENSIONS.top, BOX_DIMENSIONS.width, BOX_DIMENSIONS.top + BOX_DIMENSIONS.height); } function drawNumber(yPosition, color) { g.setColor(color); g.setFont("Vector", NUMBER_SIZE); g.drawString(numberValue.toString(), SCREEN_WIDTH / 2 - g.stringWidth(numberValue.toString()) / 2, yPosition); } function animateNumber() { const now = Date.now(); const progress = Math.min(1, (now - startTime) / ANIMATION_DURATION); g.clear(); const currentY = (SCREEN_HEIGHT - NUMBER_SIZE) * progress; drawNumber(currentY, g.theme.fg); setRect('fillRect'); setRect('setClipRect'); drawNumber(currentY, g.theme.bg); g.setClipRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); g.flip(); if (progress < 1) { animationInterval = setTimeout(animateNumber, 1000 / 60); } else { numberValue = Math.floor(Math.random() * 100); startTime = Date.now(); animationInterval = setTimeout(animateNumber, 500); } } startTime = Date.now(); animateNumber();
But it sounds like extending drawImages like you said could be way more versatile.
First, I should mention that I'm pretty new to JS, so forgive me if this is a rookie mistake. I'm trying to make a custom clock for my bangle.js 2, and it involves inverting the colors of portions of the screen. I wrote a function that iterates over the pixels in a given circle and inverts them:
When inverting larger areas, execution gets halted a few hundred milliseconds into the drawing process.
I'm guessing that this has something to do with hogging the CPU for too long, but I'm not really sure. Any advice on how to avoid halting execution and / or make this more efficient would be appreciated.