How can you use HTML in the viewer, with the same scaling? - autodesk-forge

So, I am trying to take a different approach of adding text into the viewer by using HTML. My current approach is that I append the elements to the viewer container, but the problem with that is that the position is absolute. It always sticks to the screen/canvas, so when I move around in the scene, it does not move with it. What I want is for the element to be stuck to the scene, so when the camera moves, it moves along with the scene because it is stuck to it.
I have tried the following:
this.viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, function(event){
console.log(event.target);
event.target.impl.createOverlayScene('test');
event.target.impl.addOverlay('test');
var node = document.createElement("LI"); // Create a <li> node
var textnode = document.createTextNode("Water"); // Create a text node
node.appendChild(textnode);
// Append the text to <li>
event.target.clientContainer.appendChild(node)
});
I have messed around with overlay scenes, but it seems they are only for WebGL. So, what is the correct way to add elements to the viewer that share the same scale, and will move around with the camera like the element is part of the scene?

I have an extensive demo of that approach that you can find at Viewing.Extension.Markup3D. For more details see the article.
Keep in mind that will be a low-perf approach when dealing with a large number of markups compared with using a PointCloud + custom shader:
High-Performance 3D markups with PointCloud in the Forge Viewer

Related

Forge viewer - How to link restored markups with their label text written on it while camera change event

In my markup, I add a label on it using (x,y) co-ordinates using "markup.markups[0].getClientPosition". This works, but if I change camera mode or rotate it will lose it place, so am wondering how I can put it back to the new position as per the new markup position?
I understand I have to add event listener for "CAMERA_CHANGE_EVENT", but how I should relate the label with its corresponding svg markup, what if there are more than one markups?
Thanks in advance.
I'd suggest to use the 3d markup extension to make things easier - it supports navigation right out of the box
Follow here to get started: https://forge.autodesk.com/blog/3d-markup-icons-and-info-card
Or SVG markups work well as well: https://forge.autodesk.com/blog/create-pushpin-markup-svg

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

Html5 drag and drop unicode chessboard

I am trying to do html5 dragndrop on my html5/css chessboard using unicode pieces but have a problem at the moment with it.
On dragging & dropping the whole 'li' element seems to move & on drop this disrupts the board.
This can be seen on the chess WordPress site at:
http://www.buryknightschess.org.uk/play-chess/
(As can be seen I asked for help with this on SitePoint Forums but haven't had a reply to help yet from there).
Possibly I somehow need just to make the unicode chess pieces draggable & not the whole chess square (<li></li>).
I shall keep trying to fix this but meanwhile I would greatly appreciate any advice to help with this html5 dragndrop issue. I look forward to helpful replies, many thanks
The reason the <li/> is being moved (thus rearranging the chess board) is because in your drop function is calling appendChild:
function drop(event) {
var element = event.dataTransfer.getData("Text");
// This changes the DOM
event.target.appendChild(document.getElementById(element));
event.stopPropagation();
return false;
}
Instead of moving that actual DOM node, the drop function should copy the innerHTML of the node that's being dragged. Here's how the new drop would look function:
function drop(event) {
var coordinate = event.dataTransfer.getData("Text");
var element = document.getElementById(coordinate);
event.target.innerHTML = element.innerHTML; // Moving piece to new cell
element.innerHTML = ""; // Clearing old cell
event.stopPropagation(); // Consider using `event.preventDefault` instead
return false;
}
Also, I'd consider using event.preventDfault instead of event.stopPropagation. This makes it possible to add new drop listeners to the board or one of its parents. For example you may want to add a drop listener to the document body to handle the case where a user tries to drag a piece off the board.
As general remark, have you considering using jQueryUI draggable and droppable libraries? You'd be able to support much richer drag/drop interactions such as snap-to-grid movement and delayed starts. Also, HTML5 drag-and-drop is typically used to allow users to drag files from their OS desktop onto the a web page. The way your using it is totally fine, it's just a little strange.

Drag objects in canvas

Im looking for an easy to use method of assigning drag behavior to multiple objects (images, shapes etc) in canvas. Does anyone have a good way or know of any libraries for dragging objects around? Thanks
Creating your own mouse events takes a little work - ideally you should either create or use some kind of mini-library. I'm thinking of creating something like this in the near future. Anyway, I created a drag and drop demo on jsFiddle showing how to drag images - you can view it here.
You can create draggable images like this:
var myImage = new DragImage(sourcePath, x, y);
Let me know if you have any questions about this. Hope it helps.
EDIT
There was a bug when dragging multiple images. Here is a new version.
Another thing you might want to check out is easeljs it sort of in the style of AS3... mouseEvents dragging etc...
The HTML Canvas—unlike SVG or HTML—uses a non-retained (or immediate) graphics API. This means that when you draw something (like an image) to the canvas no knowledge of that thing remains. The only thing left is pixels on the canvas, blended with all the previous pixels. You can't really drag a subset of pixels; for one thing, the pixels that were 'under' them are gone. What you would have to do is:
Track the mousedown event and see if it's in the 'right' location for dragging. (You'll have to keep track of what images/objects are where and perform mouse hit detection.)
As the user drags the mouse, redraw the entire canvas from scratch, drawing the image in a new location each time based on the offset between the current mouse location and the initial mousedown location.
Some alternatives that I might suggest:
SVG
Pure HTML
Multiple layered canvases, and drag one transparent canvas over another.
The HTML Canvas is good for a lot of things. User interaction with "elements" that appear to be distinct (but are not) is not one of those things.
Update: Here are some examples showing dragging on the canvas:
http://developer.yahoo.com/yui/examples/dragdrop/dd-region.html
http://www.redsquirrel.com/dave/work/interactivecanvas/
http://langexplr.blogspot.com/2008/11/using-canvas-html-element.html
None of these have created a separate library for tracking your shapes for you, however.
KineticJS is one such Javascript Library that u can use exclusively for animations
Heres the Link html5canvastutorials
Canvas and jCanvas
You're definitely gonna want to check out jCanvas. It's a super clean wrapper for Canvas, which kicks open a lot of doors without adding code complexity. It makes things like this a breeze.
For example, here's a little sandbox of something close to what you're after, with dragging and redrawing built right in:
Drawing an Arrow Between Two Elements.
I ventured down the road of doing everything with DIVs and jQuery but it always fell short on interactivity and quality.
Hope that helps others, like me.
JP
As you create new objects whether they are windows, cards, shapes or images to be draggable, you can store them in an array of "objects currently not selected". When you click on them or select them or start dragging them you can remove them from the array of "objects not selected". This way you can control what can move in the event of a particular mousedown event or mousemove event by checking if it isn't selected. If it is selected it will not be in the "not selected" array and you can move the mouse pointer over other shapes while dragging shapes without them becoming dragged.
Creating arrays of objects you would like to drag also helps with hierarchy. Canvas draws the pixels belonging to the foremost object last. So if the objects are in an array you simply switch their instance as in element in the array say from objectArray[20] to objectArray[4] as you iterate through the array and draw the objects stored in the array elements you can change whether other objects are seen on top or behind other objects.