Overlaying virtual element on the controller resulting in wrong scale - graphics

We are currently trying to create a virtual object ( A plane ) and overlay it on the controller of a Magic Leap Device. However, we are having some difficulties doing this.
When I set the width or any dimension of an entity to say 1 meter. The resulting virtual image is not 1 meter and actually smaller.
Also, It seems like the image does on stay at the same position relative to the controller when we move it around. There seems to be a offset that magic leap adds.
<a-entity id="controller" magicleap-controls="hand: right">
<a-plane id="board" width="0.45" height="0.1" position="0 0 0.0" rotation="-45 0 0" color="#b3b3b3" material="side: double; transparent: true; opacity: 0.5">
</a-plane>
</a-entity>
This is the code I am using. I am essentially trying to create a virtual board (which will map to the physical board -- but the sizes are not lining up)
What could be the issue?? Any leads would be appreciated

I think it may be caused by the parent node's attributes. In A-Frame every entity inherits position, scale, and rotation from its parent element. The child element inherits that and marks it in its local space as [0 0 0] (or [1 1 1] for scale) and that can be whatever else in world space. Any child transformation will be applied on top of that.
quick edit - not only the direct parent will have an effect but every single entity that is wrapping the final element.
source - relative-positioning
Look at the example below
there are 2 spheres that are identical but one is wrapped in another entity with changed attributes. Look what happens - it gets distorted and displaced as the transformation is applied to its local space.
<!DOCTYPE html>
<html>
<head>
<script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script>
<style>
</style>
</head>
<body>
<a-scene>
<a-entity position="-6 0 -5" scale="2 2 1">
<a-sphere scale="1 2 3" position="3 1 -5" color="blue"> </a-sphere>
</a-entity>
<a-sphere scale="1 2 3" position="3 1 -5" color="red"> </a-sphere>
</a-scene>
</body>
</html>

Related

Fill SVG path element with a background-image and full width

Can someone help me with this:
I was able to add SVG with filled image but the aspect ratio/scaling doesn't work as expected. I tried a few solutions but neither of them worked. Please help. The link is below:
https://park-maksimir.hr/testnasve/
enter code here<style>
.aspectRatioSizer {
display: grid;
}
.aspectRatioSizer > * {
grid-area: 1 / 1 / 2 / 2;
}
</style>
<div class="aspectRatioSizer">
<svg viewBox="0 0 7 2"></svg>
<div>
Content goes here
</div>
</div>
Two things going on there:
As soon as you give a a viewBox, it goes full-width, but only as tall as the implied aspect ratio in the viewBox value. The viewBox value is essentially “top, left, width, height” for the coordinate system interally to the SVG, but it has the side-effect of sizing the element itself when it has no height of its own. That’s what is used to “push” the parent element into an apsect ratio as well. The parent will still stretch if it has to (e.g. more content than fits), which is good.
CSS Grid is used to place both elements on top of each other, and the source order keeps the content on top.

D3 and SVG namespaces for custom svg elements or attributes to be valid?

I created some custom svg attributes yet want to pass the svg validator test.
I saw the D3 > Namespace page, the previous How can I specify a custom XML/SVG namespace with D3.js? and thus processed as follow:
// d3.ns.prefix.geo = "http://www.example.com/boundingbox/";
// d3.ns.prefix.inkscape = "http://www.inkscape.org/namespaces/inkscape";
// SVG injection:
var width = 600;
var svg = d3.select("#hook").append("svg")
.attr("name", "Country's_name_administrative_map_\(2015\)")
.attr("id", "Country_s_name")
.attr("width", width)
.attr(':xmlns:geo','http://www.example.com/boundingbox/')
.attr(':xmlns:inkscape','http://www.inkscape.org/namespaces/inkscape')
.attr(":xmlns:cc","http://creativecommons.org/ns#");
// Tags:
svg.append(":geo:g")
.attr(':xmlns:geo','http://www.example.com/boundingbox/')
.attr(":geo:id","geo")
.attr(':geo:syntax', "WSEN bounding box in decimal degrees")
.attr(':geo:west', WEST)
.attr('geo:south', SOUTH)
.attr(':geo:east', EAST)
.attr(':geo:north', NORTH)
.attr(':geo:title', title);
Produce :
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
name="Country's_name_administrative_map_(2015)"
id="Country_s_name"
xmlns:geo="http://www.example.com/boundingbox/"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:cc="http://creativecommons.org/ns#"
width="600"
height="579.2009758421691"
version="1.1">
<defs xmlns="http://www.w3.org/1999/xhtml">
<style type="text/css"><![CDATA[
svg { border: 1px solid rgb(100, 100, 100); }]]>
</style>
</defs>
<geo:g xmlns:geo="http://www.example.com/boundingbox/"
geo:id="geo"
geo:syntax="WSEN bounding box in decimal degrees"
geo:west="-5.8"
south="41"
geo:east="10"
geo:north="51.5"
geo:title="Country's name" />
<defs><pattern id="hash2_4" width="6" h…
…
</svg>
I still get all the errors (larger image) :
The first type of error is related to the custom <geo:g … > element itself, visible above. The 2nd type of errors is related to custom attributes such geo:west="…" or inkscape:group="…", which I expected to be valid due to the earlier xmlns declarations.
Am I walking the wrong road ? How to make custom attribute valid via d3js ?
EDIT: a minimal jsfiddle provide a demo of the buggy output.
About d3js and namespaces. According to Selvin on D3 doesn't append xmlns:something namespace properly to svg element, it's a D3js know bug with known but not yet implemented solution. Also, current way to overcome it is via JQuery
I made some mildly successful tries.
1) Reading: To produce valid svg document which could be saved, #Selim pointed out that d3.ns.prefix is NOT suitable (see d3 doesn't append namespace attributes to svg element ).
2) Reading more: So I read Namespaces Crash Course. The key point is that
[...] namespace prefixes are used to prefix attribute names and tag [element] names [...]
From the official doc with declaration and usages, for the attributes (<script> changed into <a>) :
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<a xlink:href="space-rocket.html">...</a>
</svg>
and for elements:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg">
<body>
<h1>SVG embedded inline in XHTML</h1>
<svg:svg width="300px" height="200px">
<svg:circle cx="150" cy="100" r="50" fill="#ff0000"/>
</svg:svg>
</body>
</html>
2) Porting: So I went ahead, NOT d3.ns.prefix, but with the handmade custom namespace ("geo") declaration as an attribute to the svg element via :
d3.select("svg").attr(":xmlns:geo","http://www.example.com/something/")
together with usages such
svg.append("geo").attr("id","geo")
.attr('manual', "WSEN bounding box in decimal degrees")
.attr('WEST', "-4.05")
.attr('SOUTH', "40.5")
.attr('EAST', "10.0")
.attr('NORTH', "54.5")
.attr('Title', "Imaginary map of Kinglons ruling Europe");
or
svg.append("geo").attr("id","geo")
.attr(':geo:manual', "WSEN bounding box in decimal degrees")
.attr(':geo:WEST', "-4.05")
.attr(':geo:SOUTH', "40.5")
.attr(':geo:EAST', "10.0")
.attr(':geo:NORTH', "54.5")
.attr(':geo:Title', "Imaginary map of Kinglons ruling Europe");
or
svg.append(":geo:geo").attr("id","geo")
.attr(':geo:manual', "WSEN bounding box in decimal degrees")
.attr(':geo:WEST', "-4.05")
.attr(':geo:SOUTH', "40.5")
.attr(':geo:EAST', "10.0")
.attr(':geo:NORTH', "54.5")
.attr(':geo:Title', "Imaginary map of Kinglons ruling Europe");
and about 3 other variants, but none is valid, all fails the svg validator.
I have no more ideas how to get a valid svg.
Fiddle (downloadable) , svg validator

SVG Won't show until I edit the element in Chrome developer tools

I'm creating a dom structure which includes an SVG element:
<div data-bind="with: searchable_select.f0000001" style="verticalAlign: top">
<input data-bind="value: select_filter_value, valueUpdate: 'afterkeydown', event: { change: change_filter_, blur: blur_filter_ }" style="display: none">
<div>
<select data-bind="options: select_list, value: working_value, event: { change: change_selector_ }, optionsText: 'label', optionsValue: 'value'" style="display: inline-block; maxWidth: 150px">
<option value="person_full_name_asc">Member Full Name (A-Z)</option>
<option value="person_full_name_desc">Member Full Name (Z-A)</option>
</select>
<svg style="display: inline-block; verticalAlign: middle" width="18" height="18" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle cx="6" cy="6" r="5" fill="#AAAAAA" stroke="#000000" stroke-width="2"></circle>
<path fill="#AAAAAA" stroke="#000000" stroke-width="2" d="M10,10 L17,17"></path>
</g>
</svg>
</div>
</div>
The svg element does not actually display. When I find the svg element in Chrome developer tools, both width and height show as zero.
I've tried removing the style attribute. I've tried setting the width and height in the style attribute.
I've copied the svg to a separate HTML file:
<html>
<head><title>maggen</title></head>
<body>
<svg style="display: inline-block; verticalAlign: middle" width="18" height="18" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle cx="6" cy="6" r="5" fill="#AAAAAA" stroke="#000000" stroke-width="2"></circle>
<path fill="#AAAAAA" stroke="#000000" stroke-width="2" d="M10,10 L17,17"></path>
</g>
</svg>
</body>
</html>
Where it displays fine.
If I wrap the svg element in a div, the svg element shows up. In fact, if I edit the HTML in Chrome developer tools it will show up.
So, yeah, why? I've done a search on Google for this, but either it isn't there or (more likely) my Google Fu is not up to the task. I mean, sure, I can wrap it in a div - and maybe that's the right thing to do - but I'd rather not because then I'd need to wrap other stuff in divs and the dom will start to get cluttered.
EDIT: On a hunch I tried editing viewport attribute into the SVG element in Chrome tools. Voila! The element is visible! Expect when I included the viewport attribute when creating the document, it's not visible. So I tried just adding a random attribute in Chrome tools to the SVG element. Voila! The Element is visible! So, I thought, the problem is specific to Chrome and tried running it in Firefox...
...where the element doesn't show up.
EDIT: Great, so wrapping it in a div is not guaranteed to make it show up. But doing an "edit as HTML" in Chrome developer tools does make it show up.
EDIT: Well, I've gotten it to work correctly and, yes, it turns out to be a function of the Javascript creating the DOM elements. There's a lot of stuff in the code, but I can boil it down to this:
This code works (createElement creates a tag and sets attributes based on passed in parameters):
var div = this.createElement(
'div',
element_name + '_div',
null, style_options, null, null
);
div.innerHTML = [
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width=' + width + ' height=' + height + '>',
svg_xml.join(''),
'</svg>'
].join('');
if (parent) parent.appendChild(div);
return div;
This code doesn't:
var svg = this.createElement('svg', element_name, null, style_options, classlist, {
viewport: '0 0 ' + width + ' ' + height,
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
width: width,
height: height
});
svg.innerHTML = svg_xml.join('');
if (parent) parent.appendChild(svg);
return svg;
So, sure, I've got something working now, but I don't understand why. Or more to the point, I don't understand why one way works and the other doesn't. I have a couple of guesses, but they are just wild guesses, really.
"I've got something working now, but I don't understand why."
The issue is that the methods you were using do not create an SVG element in the SVG namespace. The xmlns attribute only affects the behaviour of an XML parser, not of DOM methods.
I'm not sure which library you're using for the this.createElement() method with multiple parameters. However, I suspect it probably starts by calling the basic document.createElement(tagName) method. This is what MDN says about the standard DOM createElement method:
In an HTML document creates the specified HTML element or HTMLUnknownElement if the element is not known. ... In other documents creates an element with a null namespaceURI.
In other words, because you're (presumably, indirectly) calling createElement on an HTML document, it always creates an HTML element. An HTML element with tag name "svg" is just treated as an unknown span-type element.
In contrast, using div.innerHTML to pass a markup string creates the SVG element correctly because it invokes the HTML5 parser to figure out what type of element to create. The namespace is determined using the same rules as when parsing markup from a file. Editing the HTML in the Chrome developer tools has the same effect.
Sidenote: Avoid calling .innerHTML on an SVG element. Some browsers support it, but it's not part of the specs. You're not getting an error because your svg variable is actually an instance of HTMLUnknownElement. Passing SVG code to the innerHTML method of a parent <div> usually works, although there are some bugs with SMIL animation. As #Robert Longson says in the comments, you can use the DOMParser object to parse either HTML or XML code into a document.
The other way to dynamically create an SVG element is to use document.createElementNS(namespaceURI, tagName). You'll also have to use this method to create all the child elements of the SVG. Once they are created, you may be able to set attributes, styles, and classes using your library methods. (But you haven't specified what library you're using, so I'm not sure.)

SVG (1.1) : how to 'link-to' or 'centre' on a shape in a browser?

Is there is browser-independant way getting the browser to centre on a particular shape (by 'id' attribute) ?
I have tried using xlinks wrapped around shapes like this:
<a xlink:href="#node24"> .... </a>
I have reasonably busy (100+ shapes) directed graph diagrams (generated from dot): and when I load them up in Chrome , more often than not, the intial screen is just blank - forcing the user to use scrollbars to find the diagram at all.
I'm afraid I don't have any good news for you.
For stand-alone SVG documents, you can manipulate the part of an SVG displayed when following a link by linking to a <view> element (distinct from, but making use of, the SVG "viewBox" attribute). The view element specifies the viewBox to use and possibly some other parameters, and the graphic will be displayed with those parameters instead of the default ones.
Example code:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 100 100"
preserveAspectRatio="xMidYMin meet" >
<circle cx ="50" r="40"/>
<view id="panUp" viewBox="0 -50 100 100" />
<view id="zoomIn" viewBox="25 25 50 50" />
</svg>
If you linked to the file as a whole it would show you an image with half a circle centered at the top of the screen.
If, however, you linked to it like http://example.com/sample.svg#panUp, the circle would be the same size but centered on screen. If you linked to http://example.com/sample.svg#zoomIn, you'd only see the bottom edge of a circle that is twice as big.
(I don't have anywhere to host the file that can serve up raw SVG files, but this CodePen uses data URI to show the effects, although the data URI fragment identifiers doesn't seem to work in Firefox.)
You are supposed to be able to even specify the desired viewBox, transforms, or other attributes as part of the URL fragment (like http://example.com/sample.svg#myView(viewBox(0,0,200,200))), but I don't think that's widely implemented -- it had no effect on either Firefox or Chrome.
And even <view> fragments don't seem to work when the SVG is embedded within an HTML document. So unless your SVG is stand-alone, creating a view for each element (or one view that your dynamically change to match the clicked element), isn't going to be worth the trouble.
So what does work?
The default behaviour, when linking to a fragment (element id) that is not a <view> is to display the nearest ancestor <svg> element that contains that element ("nearest ancestor" because an SVG can contain nested <svg> tags). So if your document has a natural structure to it, you could replace some <g> elements with <svg> with a specified x,y,height and width parameter, and then linking to an element within that sub-graphic would show that view. That should work even when the SVG is embedded within a larger HTML document. But if you've got hundreds of elements moving around, it's probably not a practical solution.
Which leaves #Ian's solution of programmatically manipulating the main SVG viewBox. If you don't want to zoom in, just pan, leave the width and height as the full size of your visualization, and just change the x and y offsets. Something like:
function centerViewOnElement( el ) {
var bbox = el.getBBox()
var elCenterX = bbox.x + bbox.width/2,
elCenterY = bbox.y + bbox.height/2;
svg.setAttribute("viewBox", [(elCenterX - width/2),
(elCenterY - height/2),
width,
height
].join(" ") );
//assuming you've got the svg, width and height already saved in variables...
}
Thought I would do a simpler example, as this feels quite useful in general...with a jsfiddle here
<svg id="mySvg">
<circle id="myCirc" cx="20" cy="20" r="20"/>
<rect id="myRect" x="50" y="50" width="50" height="50"/>
</svg>
var mySvg = document.getElementById("mySvg");
function getNewViewbox( el ) {
var bbox = el.getBBox();
return newViewbox = bbox.x + " " + bbox.y + " " + bbox.width + " " + bbox.height;
}
function focusElement( ev ) {
ev.stopPropagation();
mySvg.setAttribute("viewBox", getNewViewbox( ev.target ) );
}
//click on any element, or even the svg paper
document.getElementById("mySvg").addEventListener("click", focusElement);

Unable to render vertically lay out addition of two numbers with MathJax and MathML

I would like to render two numbers on a web page like this:
123
+ 456
______
I've found this example:
<mstack>
<mn>496</mn>
<msrow> <mo>+</mo> <none/> <mn>28</mn> </msrow>
<msline/>
</mstack>
but MathJax doesn't support mstack, msrow and msline elements.I've attempted to use a mtable
<body>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mtable id="test" columnalign="right">
<mtr><mtd></mtd><mtd><mn>12321</mn></mtd></mtr>
<mtr><mtd><mo>+</mo></mtd><mtd><mn>45665445</mn></mtd></mtr>
</mtable>
</math>
</body>
with this CSS:
<style type="text/css">
#test
{
border-bottom:1px solid black;
}
</style>
but the bottom border is overlapping the lower number. Is there a way to achieve this layout with MathJax/MathML?
You can see examples of this kind of layout in the MathML spec at
http://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.elemmath.examples
If, once the document has loaded, you select the button "convert and display with MathJax" then the MathML3 mstack markup will be transformed to some MathML2 that MathJax understands. The relevant javascript is all available linked from that page.
Also relevant is the discussion between myself and the MathJax developer at
https://groups.google.com/forum/#!msg/mathjax-users/wa85p5TAIe4/hgUoLEXrweoJ

Resources