Render WASM Graphics to Custom HTML Canvas - html

I have setup a WASM project using Rust and a game engine called Bevy to create graphics within a Svelte app. However, when I run the init() function generated by wasm-pack, it creates a canvas element for the graphics to be rendered into. Is there any way to make it render to a canvas I have created or to style the canvas it generates?

You should be able to specify the canvas bevy should render to by setting the WindowDescriptor's canvas field
The docs say "If set, this selector will be used to find a matching html canvas element, rather than creating a new one. Uses the CSS selector format."
When you create the WindowDescriptor add the canvas selector as a field.
let window_descriptor = WindowDescriptor {
canvas: "#mycanvas",
..default()
};

Related

How to merge three.js renders with other HTML elements?

I am very much new to programming, stackoverflow and everything here in general. So please bear with me.
I have made simple scenes using Three.js and some effects using HTML Canvas separately.
I'd like to know if there is anyway to combine the two, or in general, how to combine the Three.js renderer canvas with other HTML elements.
My current code includes something like :
var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.domElement.id = 'WebGLCanvas';
document.body.appendChild(renderer.domElement);
A seamless integration of WebGL content and HTML elements is not possible. You can position HTML elements on top of the renderer's canvas element or you can do it the other way around. By setting the alpha flag of THREE.WebGLRenderer to true, you can place the renderer's canvas on top of other HTML content.
However, you should keep in mind that WebGL content is always rendered separately. It's not possible to merge 3D objects like meshes, lines or point clouds with HTML elements so they are sorted and rendered together.
The usage of THREE.CSS3DRenderer in combination with THREE.WebGLRenderer is a good example for a proper usage. Check out the following demo that shows both renderers integrated in simple application.
https://threejs.org/examples/css3d_orthographic.html

Context menu on canvas

I'm trying to use jQuery context menu to add a context menu on a specific element drawin in a html5 canvas, but I have no idea how i could bind it to that. Any tips?
Shapes drawn on html5 Canvas cannot be referenced
Any specific shape/path you've drawn on canvas is not remembered -- the shapes are just pixels on the canvas. So you can't bind your context menu to the un-referenceable shape.
So...You must manually find your shapes
As a starting point, you need to find your shape in the "sea of pixels".
Finding circular & rectangular shapes with Math
If the shape is rectangular or circular, you can mathematically find if the mouse-click is inside the shape using basic math.
// test if the mouse is inside a circle
// Given the circle's centerpoint and its radius
var dx = mouseX-circleCenterX;
var dy = mouseY-circleCenterY;
var mouseIsInCircle = (dx*dx+dy*dy)<(circleRadius*circleRadius);
// test if the mouse is inside a rectangle
// Given the rectangle's x,y,width & height
var mouseIsInRect=(
mouseX>=rect1.x &&
mouseX<=rect1.x+rect1.width &&
mouseY>=rect1.y &&
mouseY<=rect1.y+rect1.height);
Finding more complex paths with context.isPointInPath
One way to reference paths on the canvas is to put the commands that created the path in an object. When you need to hit-test that path to see if the context menu should deploy, you can redefine the path and use context.isPointInPath. This previous Stackoverflow Q&A shows how to use isPointInPath to test if the mouse is inside your complex path.
A better way with Path2D
Path2D is built into most modern browsers (but not IE) and it allows you to save a reference to your complex path. Then you can have context.isPointInPath use that Path2D definition to hit-test your Path2D.
The context menu itself
Here is a previous Stackoverflow Q&A that shows how to create a custom context menu.
If you want to use the jQuery context menu you will need to dynamically create on-demand menus and configure the menu to show at the desired [x,y] on the canvas. Some assembly is required

How to view source code of canvas element

I am trying to access the source code inside the canvas tag. Is it possible to get source code inside canvas tag?
You cannot get the source code from canvas element . You need to check the javascript to see what's going on in the canvas . Canvas is similar to board where you can draw anything with javascript .
The canvas element is part of HTML5 and allows for dynamic, scriptable
rendering of 2D shapes and bitmap images. It is a low level,
procedural model that updates a bitmap and does not have a built-in
scene graph
If you use Chrome you're in luck. It has an experimental feature for inspecting Canvas elements. So you can actually profile the canvas element and see step by step each call, and see a shot of the output of that call.
In chrome type chrome://flags/ into the URL and once the page loads, find "Enable Developer Tools experiments". Close out of Chrome and once you load it back up, in the inspector you will find a new option under Profiles for "Capture Canvas Frame". Run that and it will output a list of every call performed.
I learned about this through twitter and the following link, enjoy.
http://www.html5rocks.com/en/tutorials/canvas/inspection/

Draw shapes on HTML5 Canvas...with video

I've been Googling around a bit for an answer and haven't found a definitive one either way: is it possible to play a video using an HTML5 canvas, and also allow the user to draw on this video? The use case, for some context, is to play a video on infinite loop so the user can draw multiple boxes over specific areas to indicate regions of interest.
As a bonus (:P), if I can figure out how to do this on its own, any hints as to how this could be done within Drupal? I'm already looking at the Canvas Field module, but if you have any hints on this point too (though the first one is the priority), that'd be awesome!
You can draw html5 video elements onto a canvas. The drawImage method accepts a video element in the first parameter just like an image element. This will take the current "frame" of the video element and render it onto the canvas. To get fluid playback of the video you will need to draw the video to the canvas repeatedly.
You can then draw on the canvas normally, making sure you redraw everything after each update of the video frame.
Here is a demo of video on canvas
here is a in-depth look into video and the canvas
I recently received this request from a client to provide this feature, and it must be CMS-friendly. The technique involves three big ideas
a drawing function
repeatedly calling upon the same drawing function
using requestAnimationFrame to paint the next frame
Assuming you have a video element already, you'd take the following steps
Hide the video element
Create a canvas element whose height/width match the video element, store this somewhere
Get the context of the canvas element with `canvas.getContext('2d') and also store that somewhere
Create a drawing function
In that drawing function, you would use canvas.drawImage(src, x, y) where src is the edited version of the current frame of the video;
In that drawing function, use recursion to call itself again
I can give you two examples of this being done (and usable for content management systems)
The first is here: https://jsfiddle.net/yywL381w/19/
A company called SDL makes a tool called Media Manager that hosts videos. What you see is a jQuery plugin that takes its parameters from a data-* , makes a request from the Media Manager Rest API, creates a video, and adds effects based entirely on data* attributes. That plugin could easily be tweaked to work with videos called from other sources. You can look at the repo for it for more details on usage.
Another example is here: http://codepen.io/paceaux/pen/egLOeR
That is not a jQuery plugin; it's an ES6 class instead. You can create an image/video and apply a cropping effect with this:
let imageModule = new ImageCanvasModule(module);
imageModule.createCanvas();
imageModule.drawOnCanvas();
imageModule.hideOriginal();
You'll observe, in the ImageCanvasModule class, this method:
drawFrame () {
if (this.isVideo && this.media.paused) return false;
let x = 0;
let width = this.media.offsetWidth;
let y = 0;
this.imageFrames[this.module.dataset.imageFrame](this.backContext);
this.backContext.drawImage(this.media, x, y, width, this.canvas.height);
this.context.drawImage(this.backCanvas, 0, 0);
if (this.isVideo) {
window.requestAnimationFrame(()=>{
this.drawFrame();
});
}
}
The class has created a second canvas, to use for drawing. That canvas isn't visible, it's just their to save the browser some heartache.
The "manipulation" that is content manageable is this.imageFrames[this.module.dataset.imageFrame](this.backContext);
The "frame" is an attribute stored on the image/video (Which could be output by a template in the CMS). This gets the name of the imageFrame, and runs it as a matching function. It also sends in the context (so I can toggle between drawing on the back canvas or main canvas if needed)
then this.backContext.drawImage(this.media, x, y, width, this.canvas.height); draws the image on the back context.
Finally, this appears on the main canvas with this.context.drawImage(this.backCanvas, 0, 0); where I take the backcanvas, and draw it on to the main canvas. So the canvas that's visible has the least amount of manipulations possible.
And at the end, because this is a video, we want to draw a new frame. So we have the function call itself:
if (this.isVideo) {
window.requestAnimationFrame(()=>{
this.drawFrame();
});
This whole setup allows us to use the CMS to output data-* attributes containing the type of frame the user wants to be drawn around the image. the JavaScript then produces a canvasified version of that image or video. Sample markup might look like:
<video muted loop autoplay data-image-frame="wedgeTop">

Getting a reference to image loaded inside an HTML 5 Canvas

I am loading an image into an HTML 5 Canvas using drawImage method. How do I get a reference to that image later (maybe on some mouse-clicked event) so that I can do a transformation to the image (like rotation)?
Save a reference to the Image object you used to paint to the canvas.
Then,
Delete the canvas (clearRect)
Make the transformations using the canvas context
Draw the Image again
Go to 1 when you need to refresh the canvas
You can't. Once it's drawn on the canvas it's just pixels. No reference to the original source is retained by the canvas. If you want to maintain state information you have to do that yourself. Alternatively use SVG, that retains an internal DOM.