SVG foreignObject not working properly on Safari - javascript

I have a problem with SVG's foreignObjects elements on Safari. I am working with SVG elements and what I am using d3.js library.
What I did is to append on canvas a foreignObject element because differently from rect or other SVG elements didn't allow to put html elements inside. Now, after some days of development I noticed that it seems that Safari doesn't allow to put html elements inside a foreignObject. Better, it allows to do and all seems to work according to the inspector, but the I put inside the foreignObject has a background set.
The result is that I can correctly drag the foreignObject and the div inside inside the canvas but differently from Chrome or Firefox, the div's background stay on the canvas top left corner not following the div.
Here below I paste the portion of the style and foreign object code I append to the canvas
SVG
<foreignObject transform="translate(304,215)rotate(-174.86597769360367)" height="180" width="40" class="dragging">
<div class="new-rect" style="background-image: url(data:image/png;base64,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); left:-45px;">
</div>
</foreignObject>
Style
foreignObject{
cursor:pointer;
position:relative;
}
foreignObject div.new-rect{
position: absolute;
top: -8px;
background-repeat: no-repeat;
background-size: auto;
height: 180px;
width: 130px;
}
That's all. I think I am doing something that Safari doesn't like. But question is .. what ?

Setting position: "fixed" on the div inside foreignObject fixed the foreignObject position for me in Safari (as well as on Chrome on iOS). It doesn't seem to scale the foreignObject according to the scaling of the SVG though

I've found that you need to insert a <body> element to get it work in Safari, like this:
<foreignObject width="170" height="28">
<body xmlns="http://www.w3.org/1999/xhtml">
<div>my content</div>
</body>
</foreignObject>

Try adding in an inline width and height for the foreignObject. This seems to work on Safari.
<foreignObject style="overflow: visible;" y="0" x="0" width="240" height="160">
<div class="info-panel" xmlns="http://www.w3.org/2000/xmlns/" >
<div class="panel-text" xmlns="http://www.w3.org/2000/xmlns/">
<h1>ForeignObject</h1>
<p>For this to work in Safari try adding in a width and height inline on the foreignObject element. The background will also expand to the more text you add.</p>
</div>
</div>
</foreignObject>
Demo
https://codepen.io/chrisgannon/pen/2107d092ec56025bba036934d680f2bc

You can use <image> element in SVG instead of <foreignObject>. This can solve the scale and position issue easily to avoid <foreignObject> bug on Safari
Remember to change the src attribute to href.

Putting display:contents on the html tag inside puts it into place as of Safari 15.4. But you won't be able to interact much with it since the wrapping div is now nuked from the DOM. Defeating the whole purpose of foreignObject. Sing with me Safari is the new IE

Try wrapping your foreignObjects in group elements. I found that trying to style foreignObjects with transforms doesn't work well in Safari. Also most SVG's don't work in canvas elements in Firefox.
<g transform="translate(304,215)rotate(-174.86597769360367)">
<foreignObject>
<div> whatever in here </div>
<foreignObject>
</g>

I found a weird bug with iOS Safari regarding foreignObject. When I set the opacity in CSS for the HTML content within the foreignObject (it was a button in my case) it would position it absolutely over the SVG. But it positioned as expected when I removed the opacity. Took me hours to debug this issue.

A bit old, but I hope this could help:
As #do-ic suggested adding position: fixed to the element inside foreignObject solves the positioning, but not the scale.
To solve the scale I added this:
d3.zoom().on('zoom', event => {
// zoom stuff...
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
if (isSafari) {
d3.selectAll(NODE_SELECTOR).style('transform', `scale(${transform.k})`);
}
});
Also the element inside foreignObject should have: transform-origin: 0px 0px

Hi i solved this behavior without viewbox and set a #svg height and width dimension

New solutions:
Do not use the following styles in Safari + foreignobjects:
position
webkit-transform-style
webkit-backface-visibility
transition
transform
calc (The calculation result may not conform to the expectation)
opacity
You can avoid style problems without using them
old:
I find #Quinn answer, Add some information, First , you need get your SVG transform information, like is <g class = "main-tree" transform="translate(875) scale(1.09)"></g> . and You can use d3.zoomTransform to get these data, let transform = d3.zoomTransform(d3.select("#treesvg").node());
The following content is the same as that of #Quinn ,You need to select the root element under the foreignObject,Do not execute the code in other browsers

Related

Make an SVG foreignObject scrollable

I have an SVG and am adding a foreign object (HTML div) in it. I would like to make the div (or the foreign object) scrollable. However, if I set exact height to the foreign object and overflow-y: auto this works in Chrome, but doesn't work in Safari. My code is as follows:
<foreignObject x="400" y="0" width="260" height="554" class="foreignObject">
<div ...></div>
</foreignObject>
and then I have
.foreignObject {
overflow-y: auto;
}
in the CSS. I couldn't find any reason why the above would not work in Safari. Any ideas?
Another thing I tried is to set height and overflow-y to the div inside the foreignObject. However when I do that the content of the div gets zoomed and displaced. My SVG has viewBox property set and preserveAspectRatio="xMidYMin meet" - is it because of this? How can I fix this?

SVG viewBox behaviour in IE

I have this SVG and by using viewBox attribute, I can move in it and see every part of it.
The yellow box you see in picture above is a constant 400x400 SVG and the width and height of it doesn't change.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="17900 -4100 1050 1050" preserveAspectRatio="none" width="400" height="400">
When I vertically scroll, Eveything moves inside the box but Internet explorer(11) behaves differently.
Like this:
Even though the SVG height and Weight are 400x400 but the IE doesn't care and move out of SVG container!
How can Internet explorer draw outside of SVG element? How can I fix it?
P.S. In both examples, Only viewBox attributes changed.
Edit: https://jsfiddle.net/omidh/unjq6h0c/
Chrome and Firefox draw all shapes inside the SVG element but Internet Explorer doesn't.
It shouldn't be needed, but you can add overflow: hidden to your SVG.
svg {
background-color: khaki; /* rgba(216, 210, 210, 0.06); */
overflow: hidden;
}

Overlay Div That Can Be Clicked Through

I was wondering if there is a way using css or javascript that allows for a semi-transparent div element to appear visually on top of all other elements, but hyperlinks and other interactive elements under it can still be clicked? Just a whimsical idea to give my website the ability to darken or lighten the look of the website.
EDIT
I know that z-index moves objects from the background to the foreground but they also block interactive objects...
Such behavior possible via poiner-events:none (non-standard and not supported by IE).
Originally being an SVG feature, it's supported for any SVG element (IE 9+):
<svg poiner-events="none">
<rect width="100%" height="100%" fill="black" fill-opacity="0.5" />
</svg>
But for the effect you mentioned I would recommend to use opacity on body and some background on html:
body {
opacity: 0.5;
}
html {
background: black;
}
create another div element on top of existing div, and have it's z-index more than the existing one. Hope this should help.

MouseEvents don't fire on body when inner div has position fixed in firefox

Look at this example
Here is the code:
CSS:
div {
position:fixed;
top:100px;
left: 320px;
border: solid 1px blue;
}
Javascript:
var i = 1;
$(document.body).mousemove(function () {
$("#text").html(i++);
});
HTML:
<body>
<div>
<span>Test Text: </span>
<span id="text"></span>
</div>
</body>
This code just updates the span while mouse is moved over the body. It works fine in Google chrome but in Firefox the span is only updated when mouse moves over the div, To debug I looked into firebug and found that the height of the body is 0, so the mouse is actually not moving over the body, but in Google chrome body covers whole document.
So My question is:
Which is the right behavior?(chrome's or firefox's)?
Is the right behavior documented somewhere?
Also surprisingly when I added this code in jsfiddle, chrome started behaving like firefox, can someone explain me this unusual behavior also?
EDIT: I know I can make the code work in both browser by adding height:100% to body, I want to know why this different behavior in browsers and the right one.
You can see what's going on if you add this css:
body { border: 1px solid red; }
I'm not entirely sure of the reasoning, but Chrome decides that the 'body' element should be the full height of the window, whereas Firefox collapses the body element to a single line. I believe the body collapsing is the correct behavior, because a 'block' element (such as <body> or <div>) should only be as tall as necessary to contain its contents (and since you made the inner div absolutely positioned, it won't take this into account in calculating its height).
The correct fix depends on your intended outcome, but you could use document or window instead of document.body because they represent the entire viewable window instead of just the actual <body> element.
You could also set your body to a specific height like 100%. Alternatively, once you add more content to the body (stuff that isn't absolutely positioned), it will "fill out" and cause the mousemove event to fire properly anyway, so you won't need any of these fixes.
Additional to Alex's answer I was still interested in the different behaviour. I found the solution: in jsfiddle you are not supposed to add the 'body' element in the html. If you remove that then you get the same behaviour as with the stand-alone page.
UPDATE:
That wasn't the case. The real reason is that the stand-alone page missed the
<!DOCTYPE html>
declaration which caused a HTML version difference.
I don't know why but this works
Replaced document.body with document in
$(document.body).mousemove(function () {
This also works on Firefox.

How can I set Html object height same as window height?

I have flash object embedded to my page and it should act as background animation. I have trouble setting height of object element, because firefox doesn't understand height="100%" value.
<object classid="my_class_id" width="100%" height="100%" id="my_id">
<blaa blaa />
</object>
Have a look at the markup source of the example.
Fullscreen Flash as BG Example
You need to set height of body and html to 100%. Otherwise your object has no parent with a height and it cant use a prozentual value to set the height.
html, body {
height: 100%;
}

Categories

Resources