Add my own shapes to the canvas.

188 views
Skip to first unread message

Lynn Duke

unread,
Jul 24, 2023, 7:04:40 PM7/24/23
to Blockly
Hello Blockly Team!

I came to blockly to escape heavy wiring messes that show up in traditional node editors like shader graphs or Kismet in Unreal. After a couple of weeks, I think 99% of the wires that would have been used to connect nodes in those systems are not needed. 

The 1% need I feel for wiring is likely domain specific to my industry. I have a set of "Scene" blocks that you can jump between in a story. Even though there's a "goto" block that mentions the name of the Scene that comes next, you really end up missing a gorgeous wire that extends out of the scene block and points to the next scene block. 

When the scene blocks are moved, I'd update the wires dynamically, etc.

So, I feel I'm ready (and brave enough) to attempt adding my own shapes to the canvas no matter the difficulty. :D I

In the image below, I depict a rough example of what I want to do. The white arrows would be svg drawing I'd manage dynamically. No need to serialize. I'm assuming since this is all SVG at the end of the day, there's some way to add and update my own shapes that share the same workspace as the blocks.

How would a brave soul begin this journey? I would appreciate any guidance you could give. I haven't found any examples of someone wanting to add their own svg to the workspace that respects zoom and pan, etc.

Screenshot 2023-07-24 at 5.59.09 PM.png

Lynn Duke

unread,
Jul 25, 2023, 12:27:46 AM7/25/23
to Blockly
Oh I suppose this is fairly easy to do by just grabbing the canvas from the workspace. Zoom is handled. Hrmmm, am I making this too simple?

const svg = blocklyWorkspace.getCanvas()

const line = document.createElementNS('http://www.w3.org/2000/svg', 'line')
line.setAttribute('x1', '50')
line.setAttribute('y1', '50')
line.setAttribute('x2', '200')
line.setAttribute('y2', '200')
line.setAttribute('stroke', 'orange')
line.setAttribute('stroke-width', '5')
line.setAttribute('stroke-dasharray', '5,5')
svg.appendChild(line)

Screenshot 2023-07-24 at 11.27.10 PM.png

Lynn Duke

unread,
Jul 25, 2023, 10:01:59 AM7/25/23
to Blockly
I see there are Block events for MOVE but that even is just when the move stops. I'm looking for something that fires repeatedly as the block's XY position is updated. This way I can recreate the line along with the block as it moves. Workspace has something similar that fires when scrolling. 

How can I get positional updates on a block *while* being dragged?





On Monday, July 24, 2023 at 6:04:40 PM UTC-5 Lynn Duke wrote:
Screenshot 2023-07-25 at 9.00.41 AM.png

Lynn Duke

unread,
Jul 25, 2023, 12:09:37 PM7/25/23
to Blockly
Okay, 99% there. Please see the attached movie. If I could just get the position updates of the moving block, I'd have a perfect solution. Please advise when you can. Thanks!
Screen Recording 2023-07-25 at 11.06.53 AM.mov

Mark Friedman

unread,
Jul 25, 2023, 2:09:48 PM7/25/23
to blo...@googlegroups.com
Lynn,

  I think that you might need to register your own BLOCK_DRAGGER class for this.  Unfortunately, there doesn't appear to be any developer guide describing how to do this, but here's an example of a plugin which does it.  I don't think that you'll need to do anything as complicated as that plugin.  I think that for the new class that you register you'll probably want to do something like extend the existing BlockDragger class and just override the drag() method to call its super.drag() function and then do your wire rendering.  If you want to get a little more sophisticated, you could define a new Blockly event type which you would fire in your drag() method and then do your wire rendering in a standard Blockly event handler (guide here).

  Another, simpler, option might be to use Blockly's existing BLOCK_DRAG which is called at the beginning and end of the drag.  In that scenario you could simply remove the wire at the beginning of the drag and render it at the end.  I know that that's not necessarily the UX that you ideally want, but it would be much simpler to implement.

  All this makes me wonder if perhaps there should be a new event in standard Blockly that would fire as a block is dragged.  If there are concerns about performance, it could be an option that would be off by default.

  Hope this helps.

-Mark


--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/c76510a5-a9fe-45c6-92b7-9920f8bdb327n%40googlegroups.com.

Koen Van Wijk

unread,
Aug 27, 2023, 4:36:01 AM8/27/23
to Blockly
The video looks very nice, would you be able to share a demo or code?

Koen Van Wijk

unread,
Sep 8, 2023, 7:09:32 PM9/8/23
to Blockly
Hi, I like to replicate this demo. Are there any other examples to draw on the workspace canvas taking into account the scaling, scrolling, transforming? Just the dot on the right bottom of a blocks should get me started.

Regards,
Koen  

ZY Zhuang

unread,
Jan 17, 2024, 7:59:13 AM1/17/24
to Blockly
Hi, 
This work is very cool. There's one thing I'm curious about and would like to ask you: What kind of code do these lines and arrows correspond to after generating the code? Do they represent the execution order of the blocks? Or have you planned various types of pins like Unreal Engine?

Koen Van Wijk

unread,
Jan 18, 2024, 2:39:56 PM1/18/24
to Blockly
I implemented this meanwhile. I used it to make a connection between a function call and its implementation. With a little dot to smooth scroll to the implementation.

Regards,
Koen
blockly goto implementation.mp4

Lynn Duke

unread,
Jan 25, 2024, 9:52:58 PM1/25/24
to Blockly
Koen,

How did you do the pan animation of the workspace after the dot was clicked?!  :D 

Koen Van Wijk

unread,
Jan 26, 2024, 3:44:44 AM1/26/24
to Blockly
dot.addEventListener('click', function(event) {
            // move the workspace to the function block
            workspace.beginCanvasTransition();
            workspace.centerOnBlock(functionBlock.id);
            setTimeout(endCanvasTransition, 500);
          });

So I used the existing functionality of a workspace. 

function endCanvasTransition() {
  workspace.endCanvasTransition();
  createFunctionSplines();
}
Reply all
Reply to author
Forward
0 new messages