Canvas not rendering inside g with transform - css

please save my sanity!
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" id="sake" stroke-opacity="0.3" style="width: 100%; height: 100%;">
<g id="1" class="squaregroup" transform="translate(300, 20)">
<g id="square_main_1" class="square_main" transform="translate(250, 50)">
<foreignObject class="" id="fo_1" style="width: 500px; height:500px;">
<div id="globe" style="width:100%; height:100%" ></div>
</foreignObject>
</g>
</g>
</svg>
A working simplified jsfiddle
https://jsfiddle.net/n6erd5dq/6/
The canvas works (albeit the globe is only a few pixels in the bottom right corner) and draws the right ThreeJS world, but it never renders inside the parent DIV.
If you inspect the body elements, you can see the DIV is translated right and down a bit.
I've tried so many options of position, absolute, max-width, div clear, changing hierarchy, etc, every trick I know. From what I see, canvas should honour a foreignObject which honours transform/translate.
Nor can I find any other question on this, so I wonder if I'm doing something SO wrong that no one else has come across this?
I know an alternative is to have one canvas for the entire screen and then multiple viewports (?) for each little image, but given the rest of the project I'm trying to stay away from this.
e.g. https://threejs.org/examples/webgl_multiple_elements.html
Many Thanks
Andy

Related

Layout for welcome modal with prev/next buttons

I'm trying to design an informational and instructional welcome modal box with 3 "pages" using custombox.js
The modal appears in the middle of the screen, I then need to display content in the middle of the modal, with a previous button to the left, next to the right and a footer showing progress.
I did this successfully using CSS grid layout, but many of the users do not have browsers that support this. I can't figure out how to make this using plain CSS...
Here's my html
<div id="modal">
<div id="leftNnav">
<i id="leftNnavImage" class="fa fa-chevron-left" aria-hidden="true"></i>
</div>
<div id="modalContent1" class="modalContent activeModalContent">
<img id="modalContentMedia" src="https://cdn.pixabay.com/photo/2013/04/06/11/50/image-editing-101040_960_720.jpg"/>
content text goes here, lots and lots and lots and lots and lots and lots more
</div>
<div id="modalContent2" class="modalContent">
Content2 = YT Video
</div>
<div id="modalContent3" class="modalContent">
Content3 = text
</div>
<div id="rightNnav">
<i id="rightNnavImage" class="fa fa-chevron-right" aria-hidden="true"></i>
</div>
<div id="modalFooter">
<svg height="40" width="40">
<circle id="circle1" class="circle activeCircle" cx="20" cy="20" r="10"></circle>
</svg>
<svg height="40" width="40">
<circle id="circle2" class="circle" cx="20" cy="20" r="10"></circle>
</svg>
<svg height="40" width="40">
<circle id="circle3" class="circle" cx="20" cy="20" r="10"></circle>
</svg>
</div>
</div>
https://jsfiddle.net/oppt6v9j/15/
But this way just ends up really messy, the text overflows and it just doesn't feel like the correct way to do things, I feel like I'm missing something really obvious. I know I can resize the image using media queries, so that's fine, but I'm not sure how to manage the text.
Any help with how I can design this modal in CSS is very much appreciated!
If your problem with aligning the components, I would suggest the following
.right { float: right; }
.left { float: left; }
.modal { display: flex; }
.modalContent { margin: auto; }
I believe using ID's as CSS selectors is bad practice.
Hope it helps.
Right, this is a tough one since I don't know the exact dimensions of the box (and you use alot of position: absolutes).
I'd imagine it varies with screen size but your image has a height/width set (300px by 150px) so I focused on that size instead.
Note This is not an "end all be all" answer, it won't solve every usecase under the sun, rather it answers the original question:
But this way just ends up really messy, the text overflows and it just
doesn't feel like the correct way to do things, I feel like I'm
missing something really obvious.
It does this by providing a way of thought rather than a clear answer.
The solution
You're using a lot of absolute positions, this means you have to work with alot of magic numbers. Try converting them to relative positions instead.
The text is really easy, you should wrap it in a <p> tag like so:
<p>
Content text goes here, lots and lots and lots and lots and lots and lots more
</p>
And style it appropriately (box padding / corners etc):
p {
color: #001818;
padding-right: 40px;
}
The same holds true for the image:
#modalContentMedia{
width: 300px;
height: 150px;
margin-left: 15px;
}
And I'm not sure where you'd want the arrows positioned (they are in the center of the box right now) but I can imagine you'd want them in the center of the image. To do so use:
#leftNnav{
position: absolute;
cursor: pointer;
z-index: 20;
padding-left: 10px;
left: 5px;
top: calc(50% - 40px);
}
#rightNnav{
position: absolute;
cursor: pointer;
z-index: 20;
padding-right: 10px;
right: 5px;
top: calc(50% - 40px);
}
This makes the entire thing look much neater:
By illustrating how I would start solving this issue I've demonstrated fixing the 3 major things (text, image position not centered, arrows) and trust you'll be able to learn and fix the rest of the issues yourself.

CSS how to warp/bend an image or div?

Hi,
Is it possible to achieve this effect with CSS only?
As you can see, the image on top is distorted along with the text inside to look like the one below. It may be a div or an image. I have been researching on transform but found nothing about curves.
This is NOT a duplicate because I am not asking how to curve the text only but the div container as well as in case of an image.
Thank you.
I don't know if you would technically qualify this as "CSS only" since it is using an SVG filter, but I think it could be made to achieve the type of warping you want.
.warped {
display: inline-block;
background-color: yellow;
padding: 4px;
filter: url(#displacement);
}
#filterSource {
display: none;
}
<span class="warped">Warped Text!</span>
<div>
<svg id="filterSource" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="displacement" filterUnits="userSpaceOnUse">
<!-- this is just a base64 encoded PNG with a simple linear gradient -->
<!-- this may not be exactly what you want, but you can adjust the R and B channels to displace the element however you like. -->
<feImage href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAdhAAAHYQGVw7i2AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAGlJREFUaIHtz6ENwEAMxVBfUWn3H7Kw8LpCdMjAT/osIF7AZuAGnsMt4D3cN3kOuIZ3eoXYFGJTiE0hNoXYFGJTiE0hNoXYFGJTiE0hNoXYFGJTiE0hNoXYFGJTiE0hNoXYFGJTiE0hNj9ceBBjuV6HJAAAAABJRU5ErkJggg==" result="dispMap" />
<feDisplacementMap
in="SourceGraphic"
in2="dispMap"
scale="10"
xChannelSelector="B"
yChannelSelector="R" />
</filter>
</defs>
</svg>
</div>
Here's a nice tutorial on some cool effects you can achieve with this technique: https://www.creativebloq.com/how-to/add-svg-filters-with-css

Align <svg><rect> on an <input>

I have a bunch of <input> sliders, with DOM that looks something like this -
<div>
<label style="width:100px">Slider A: </label>
<input type="range" style="width:600px; height:20px;"/>
<svg width="600px" height="20px">
<rect x="0" y="0" width="300" height="20"></rect>
</svg>
</div>
I want the svg rectangle to highlight portion of the input, let's say starting at left, ending exactly at middle in this example, but other ranges are also possible.
How do I do position the svg so that it exactly overlaps the input?
I got the answer to this after some research. Posting in case anyone comes across this.
Basically define height/width for the container div, and set style="position:absolute" for the divs that need to overlap.

Doesn't (desktop browser) Safari support !important - directive in css - when inline style applied to SVG? [duplicate]

The dilemma: make a full window svg image that fills WITH aspect distortion, WITHOUT using an SVG tag. Why no svg tag? Because I intend on swapping out the SVG later (if not frequently) in the life of the page, and I have not found an easy way to do that.
The failed attempts:
<!-- for the record, my style are in a css file,
for example purposes they are style attrs-->
<!-- Working in Webkit but not in firefox, in firefox blocks stretching
and places the svg in the middle of the tag-->
<img src="my.svg" style="width:100%;height:100%;
position:fixed;top:0;left:0;bottom:0;right:0;" />
<!-- Both Webkit and Firefox block distortion, so the svg
appears centered in the div rather than conforming to the div-->
<div style="width:100%;height:100%;position:fixed;top:0;
left:0;bottom:0;right:0;background-size:cover;
background-image:url(my.svg);" />
I have also tried
background-size:contain;
background-size:cover;
background-size:100% 100%;
background-postion: center center;
but no luck.
I got this to work in Firefox, Chrome, and Safari using
<img src="my.svg" style="width:100%;height:100%;position:fixed;top:0;left:0;bottom:0;right:0;" />
The trick was to make sure the SVG I was displaying had preserveAspectRatio="none" set in the root. Also, I had to either delete the viewBox in the SVG, or make sure it tightly cropped the image content.
For example:
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 5 3">
<desc>Flag of Germany</desc>
<rect id="black_stripe" width="5" height="3" y="0" x="0" fill="#000"/>
<rect id="red_stripe" width="5" height="2" y="1" x="0" fill="#D00"/>
<rect id="gold_stripe" width="5" height="1" y="2" x="0" fill="#FFCE00"/>
</svg>
Hopefully you have control over the content of the SVG files you are trying to display. :-)
Here's a jQuery solution. As you can see, I'm using it with an SVG without <svg>
The css
#bgImage{
position:absolute;
left:0;
top:0;
}
The html
<object width="10" height="10" id="bgImage" data="resources/runner.svg" type="image/svg+xml"></object>
The javascript
//resize the background image
function resizeImage($selection){
//get the ratio of the image
var imageRatio = $selection.width() / $selection.height();
//get the screen ratio
var screenRatio = $(window).width() / $(window).height();
//if the image is wider than the screen
if(imageRatio > screenRatio){
$selection.height($(window).height()); //set image height to screen height
$selection.width($(window).height()*imageRatio); //set the correct width based on image ratio
}
//if the screen is wider than the image
else{
$selection.width($(window).width()); //set the image width to the screen width
$selection.height($(window).width()/imageRatio); //set the correct image height based on the image ratio
}
}
Run this whenever you want to resize the image, typically on "onresize" and "onload"
$(window).resize(function(){
resizeImage($("#bgImage"));
}

Problem with IE overflow: auto; and Raphael canvas being loaded into a DIV

I'm trying to place a Raphael canvas in to a div which is smaller than the actual canvas. So basically I have something like this:
var paper = Raphael("test", 2000, 2000);
var a = paper.rect(0, 0, 2000, 2000).attr({fill: "#000"});
//
<div id="test" style="width: 500px; height: 500px; overflow: auto;"></div>
Seems simple enough? Most browsers have no problem with this but IE7 forces the whole 2000x2000 rectangle on screen ignoring the whole div constraints.
I tried placing the div within another div like so:
<div id="ieholder" style="width: 500px; height: 500px; overflow: auto;">
<div id="test" style="width: 2000px; height:2000px;"></div>
</div>
But no luck, same thing happened. Is there a way around this? This
whole thing is already a compromise as I use raphael-zpd to give users
zoom and pan functionality but as it doesn't work on IE I thought I'd
just give IE users the image with basic pan functionality but no! Damn
you IE!
http://jsfiddle.net/WdwGQ/
<div id="ieholder" style="width: 500px; height: 500px; overflow: auto;">
<div id="map" style="width: 2132px; height: 2872px;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="2000" height="2000">
<desc>Created with Raphaël</desc>
<defs>
<rect x="0" y="0" width="2000" height="2000" r="0" rx="0" ry="0" fill="#000000" stroke="#000">
</svg>
</div>
</div>
Prompt your users to use Google's Chrome Frame, which embeds Chrome's rendering engine in IE?
Alternatively, prompt them to use a better browser?
That's not really a solution to the underlying problem, but it would make the underlying problem irrelevant. There may or may not be a way of getting IE7 to do what you want. I have often found there isn't...
This post provides the answer:
IE7 CSS Scrolling Div Bug
Making the outer <div> (the one with the overflow:auto style) position:relative sorts it out.

Resources