I have a iframe that I create and add to the page as an overlay. I want it to be in the center of the page. However, when I am on mobile on a non mobile optimized page, and zoomed in, the iframe usually shows up off the screen.
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0],
width = w.innerWidth || e.clientWidth || g.clientWidth;
display_width = 450;
margin = (width-450) / 2;
frame.setAttribute('style','z-index: 2147483647;position:fixed;top:20px;left:'+margin+'px;width:'+display_width+'px;margin:0px;border: 1px solid; border-color:#ddd;max-width:none;overflow:visible;');
function resizeFrameWidth(){
var frame = document.getElementById('PennyPledge54DT');
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0],
width = w.innerWidth || e.clientWidth || g.clientWidth;
var margin = 20;
var display_width = width - 40;
if(!mobile){
display_width = 450;
margin = (width-450) / 2;
}
frame.style.width = display_width+"px";
frame.style.left = margin+"px";
}
if(window.attachEvent) {
window.attachEvent('onresize', resizeFrameWidth);
}
else if(window.addEventListener) {
window.addEventListener('resize', resizeFrameWidth, true);
It works when I resize the window, but not when I zoom.
edit:
here is a jsfiddle as requested. However, the problem manifests itself when you zoom in on the content. I only know how to do that via a mobile device. So I don't know how useful a fiddle will be.
https://jsfiddle.net/41y62su7/
edit
Here's a screenshot of what my iframe looks like on mobile when I zoom in on the page a little bit.
Here is a simpler method of achieving the same effect without grabbing the window.onresize event (which fires repeatedly throughout the resize event not just at the end). Using the heredoc function defined below allows for better maintainabilty and readability in your code. In this example I include the overlay which is not included in your javascript code.
This method uses margins to center the iframe within the overlay which is fixed in one position and set to the width and height of the viewport.
function heredoc(f) {
return f.toString().match(/\/\*\s*([\s\S]*?)\s*\*\//m)[1];
};
var overlay = document.createElement("div");
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "https://www.google.ca");
overlay.style.cssText = heredoc(function() {/*
z-index: 2147483647;
position: fixed;
top: 0;
width: 100vw;
height: 100vw;
background: rgba(0,0,0,0.8);
*/});
iframe.style.cssText = heredoc(function() {/*
display: block;
margin-top:20px;
width: 450px;
max-width: 100vw;
height: 150px;
border: 1px solid #ddd;
overflow:visible;
margin: 0 auto;
margin-top: 20px;
*/});
overlay.appendChild(iframe);
document.getElementById('main').appendChild(overlay);
// you can also use
// document.body.appendChild(overlay);
// if you don't want to require that the user have an element with the id main
/* for example only, not required */
body {
width: 1000px;
height: 1000px;
}
<body>
<p id="main">
This is a bunch of text. Yadda yadda.
</p>
</body>
Related
I am doing something similar to this topic :
Text on top of image map
My problem is that the titles are not exactly at the center of the circle area and they don't stick to the area mapped on my image when the window is resized, although the areas themselves are always correctly positioned when resizing the window.
here is my code:
<div id="molecule">
<img src="./images/molecule-total.svg" alt="menu" usemap="#molecule-links">
<map name="molecule-links">
<area class="contact" shape="circle" coords="70,100,90" alt="Page1" data-name="Contact">
<area shape="circle" coords="250,350,150" href="page2.html" alt="Page2" data-name="Home">
</map>
</div>
#molecule {
height: 80vh;
width: 100vh;
padding-left: 141px;
padding-top: 15px;
position: relative;
}
.map_title {
position: absolute;
z-index: 2;
}
img {
min-height: 80%;
max-height: 100%;
}
area {
cursor: pointer;
outline-color: white;
}
function displayLinksName() {
const area = document.querySelectorAll("area");
const map = document.querySelector("map")
area.forEach(function(area){
let txt = area.getAttribute('data-name')
let coor = area.getAttribute('coords');
let coorA = coor.split(',')
let left = coorA[0];
let top = coorA[1];
let links = document.createElement('div');
links.classList.add("map-title");
links.innerHTML = txt;
links.style.top = top + 'px';
links.style.left = left + 'px';
links.style.position = 'absolute';
links.style.color = 'red';
map.append(links);
})
}
It's like the coords of the area doesn't obey to the same rules than the CSS properties top and left. Is there a workaround to make it works properly?
U can try to remake the javascript to update the position of the text based on the image position with onresize event:
window.addEventListener("resize", updateTextPosition);
function updateTextPosition() {
var img = document.querySelector("img");
var imgRect = img.getBoundingClientRect();
var areas = document.querySelectorAll("area");
areas.forEach(function(area) {
var coords = area.getAttribute("coords").split(",");
var left = coords[0];
var top = coords[1];
var text = area.nextElementSibling;
text.style.left = (imgRect.left + parseInt(left)) + "px";
text.style.top = (imgRect.top + parseInt(top)) + "px";
});
}
Adittionally you can use CSS Media queries to adjust the text, for example when the window width is less than 800:
#media (max-width: 800px) {
.map_title {
top: 50px;
left: 50px;
}
}
This adjust the position of the text.
PS:
You have an error in the javascript, it is written map-title and the css class is called map_title
I finally found the easiest way to deal with maps on any image, without using map or area tag. Just using this generator: https://imagemapper.noc.io/#/
and add tags inside the SVG code provided by the generator.
This comes from this discussion, which has lots of interesting ways to achieve this:
Responsive image map
I have a div element within my webpage, with the id "glCanvas". I want to be able to match it's aspect ratio to that of a photo that a user uploads:
$("#imageInput").change(function() {
readBackgroundFile(this);
readExif(this, function(data) {
aspectRatio = data.width/data.height;
height = $("#glCanvas").height();
width = $("#glCanvas").width();
newWidth = height*aspectRatio;
console.log(data.focalLength);
halfWidth = newWidth/2;
FOV = 2 * Math.atan(halfWidth*0.5, data.focalLength);
camera.aspect(aspectRatio);
$("#glCanvas").width(newWidth);
renderer.setSize(newWidth, height);
viewerPosition = new THREE.Vector3().fromArray(llhxyz(data.latitude, data.longitude, data.altitude));
updateScenePlacement();
});
I think maybe the style.CSS may be the issue:
#glCanvas{
background-color: black;
width: 650px;
margin: 0 auto 0 auto;
height: 500px;
So i tried deleting it, but unfortunately that removed it all together. What do i do?
I'm having trouble resizing this canvas that is displaying a video. After resizing, it continually jerks all around into different sizes between the "before" and "after" window sizes.
I tried this posts' idea, and that seemed to calm down Chrome a little, but had no affect on Firefox.
This other post gave me some ideas, but still didn't fix it. It seems like I'm either calling resize multiple times in a loop (which I don't see), or the canvas's context doesn't know how to settle on the final size. Any ideas?
<!DOCTYPE html>
<html>
<head>
<title>overflow</title>
<style>
#c {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
z-index: 1;
}
#hold {
position: fixed;
}
#v {
position: absolute;
height: auto;
width: 100%;
z-index: 0;
}
#see {
position: relative;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
}
</style>
</head>
<body>
<canvas id=c></canvas>
<div id=hold>
<video id=v>
</video>
</div>
<canvas id=see></canvas>
<script>
window.onload = start;
function start() {
var v = document.getElementById('v');
var house = document.getElementById('hold');
var base = document.getElementById('c');
var canvas = base.getContext('2d');
var cover = document.getElementById('see');
var canvastwo = cover.getContext('2d');
v.src=("keyed.ogv")
v.load();
v.play();
resize();
function resize() {
var wth = (window.innerWidth * 0.65);
house.width = wth;
house.height = (wth * 9/16);
house.style.marginTop=((window.innerHeight/2) - (house.height/2) + "px");
house.style.marginLeft=((window.innerWidth/2) - (house.width/2) + "px");
cover.width = (wth/2);
cover.height = (house.height/2);
cover.style.marginTop=((window.innerHeight/2) - (cover.height/2) + "px");
cover.style.marginLeft=((window.innerWidth/2) - (cover.width/2) + "px");
var rw = cover.width;
var rh = cover.height;
canvastwo.clearRect(0, 0, rw, rh);
draw(v, canvastwo, rw, rh);
}
window.onresize = resize;
function draw(o,j,w,h) {
if(v.paused || v.ended) return false;
j.drawImage(o,0,0,w,h);
setTimeout(draw,20,o,j,w,h);
}
}
</script>
</body>
</html>
You seem to lock in the old values you use for the setTimeout function the way you are using it here, as the context changes. So when you re-size the loop still uses the old values which no longer corresponds with the new sizes and results in the video toggle between these sizes.
Try to more "globalize" the values so that the loop call is clean when it comes to arguments. This way you are sure the variables contains the correct values for each round.
Also change setTimeout with requestAnimationFrame to make the loop more low-level (efficient) and fluid as this syncs to the monitor's vblank gap. This is particular important with video as you otherwise will get skipped frames as setTimeout is not able to sync with monitor.
Here is the essential code you need to change:
/// put these into you start block to keep them "global"
/// for the functions within it.
var w, h;
Change this part in the resize function:
/// ...
w = cover.width;
h = cover.height;
canvastwo.clearRect(0, 0, w, h);
/// argument free call to draw:
draw();
And finally the loop:
function draw() {
if(v.paused || v.ended) return false;
canvastwo.drawImage(v,0,0,w,h);
requestAnimationFrame(draw);
}
This will remove the jerking video and also make the update in sync to the monitor like the video element itself does.
ONLINE DEMO
It's easy to keep a column in my layout fixed so it's always visible, even when the user scrolls down.
It's also easy to only move the column down the page when the page is scrolled down far enough for it to be out of the viewport so it's anchored before scrolling starts.
My problem is, I have left hand column that is taller than the average window so you need to be able to scroll down to see all the content (controls) in the left column but at the same time when you scroll up you want to see the top of the controls again.
Here's a visual of what I want to accomplish:
So the left column is always occupying 100% of the height of the window but as the user scrolls down they can see the bottom of the div, and when they start to scroll up the scrolls up until it reaches the top of the window again. So no matter how far they scroll the page, the top of the div is always nearby.
Is there some jQuery magic to make this happen?
Did you mean something like this? (Demo)
var sidebar = document.getElementById('sidebar');
var sidebarScroll = 0;
var lastScroll = 0;
var topMargin = sidebar.offsetTop;
sidebar.style.bottom = 'auto';
function update() {
var delta = window.scrollY - lastScroll;
sidebarScroll += delta;
lastScroll = window.scrollY;
if(sidebarScroll < 0) {
sidebarScroll = 0;
} else if(sidebarScroll > sidebar.scrollHeight - window.innerHeight + topMargin * 2) {
sidebarScroll = sidebar.scrollHeight - window.innerHeight + topMargin * 2;
}
sidebar.style.marginTop = -sidebarScroll + 'px';
}
document.addEventListener('scroll', update);
window.addEventListener('resize', update);
#sidebar {
background-color: #003;
bottom: 1em;
color: white;
left: 1%;
overflow: auto;
padding: 1em;
position: fixed;
right: 80%;
top: 1em;
}
body {
line-height: 1.6;
margin: 1em;
margin-left: 21%;
}
It almost degrades gracefully, too…
I made a fiddle for you, hope this helps you out abit.
I detect scroll up or scroll down, and set the fixed position accordion to the direction.
http://jsfiddle.net/8eruY/
CSS
aside {
position:fixed;
height:140%;
background-color:red;
width:100px;
top:20px;
left:20px;
}
Javascript
//Detect user scroll down or scroll up in jQuery
var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
$('html').bind(mousewheelevt, function(e){
var evt = window.event || e //equalize event object
evt = evt.originalEvent ? evt.originalEvent : evt; //convert to originalEvent if possible
var delta = evt.detail ? evt.detail*(-40) : evt.wheelDelta //check for detail first, because it is used by Opera and FF
if(delta > 0) {
$('aside').css('top', '20px');
$('aside').css('bottom', 'auto');
}
else{
$('aside').css('bottom', '20px');
$('aside').css('top', 'auto');
}
});
http://jsfiddle.net/KCrFe/
or this:
.top-aligned {
position: fixed;
top: 10px;
}
with
var scrollPos
$(window).scroll(function(event){
var pos = $(this).scrollTop();
if ( pos < scrollPos){
$('.sidebar').addClass('top-aligned');
} else {
$('.sidebar').removeClass('top-aligned');
}
scrollPos = pos;
});
I have implemented a parallax scrolling effect based on a tutorial I found. The effect works great. However, when I specify the background images, I am unable to control the y (vertical) axis. This is causing problems because I'm trying to set locations on multiple layered images.
Any thoughts on what's causing the problem?
Here is one external script:
$(document).ready(function(){
$('#nav').localScroll(800);
//.parallax(xPosition, speedFactor, outerHeight) options:
//xPosition - Horizontal position of the element
//inertia - speed to move relative to vertical scroll. Example: 0.1 is one tenth the speed of scrolling, 2 is twice the speed of scrolling
//outerHeight (true/false) - Whether or not jQuery should use it's outerHeight option to determine when a section is in the viewport
$('#mainimagewrapper').parallax("50%", 1.3);
$('#secondaryimagewrapper').parallax("50%", 0.5);
$('.image2').parallax("50%", -0.1);
$('#aboutwrapper').parallax("50%", 1.7);
$('.image4').parallax("50%", 1.5);
})
This is another external script:
(function( $ ){
var $window = $(window);
var windowHeight = $window.height();
$window.resize(function () {
windowHeight = $window.height();
});
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
var $this = $(this);
var getHeight;
var firstTop;
var paddingTop = 0;
//get the starting position of each element to have parallax applied to it
$this.each(function(){
firstTop = $this.offset().top;
});
if (outerHeight) {
getHeight = function(jqo) {
return jqo.outerHeight(true);
};
} else {
getHeight = function(jqo) {
return jqo.height();
};
}
// setup defaults if arguments aren't specified
if (arguments.length < 1 || xpos === null) xpos = "50%";
if (arguments.length < 2 || speedFactor === null) speedFactor = 0.1;
if (arguments.length < 3 || outerHeight === null) outerHeight = true;
// function to be called whenever the window is scrolled or resized
function update(){
var pos = $window.scrollTop();
$this.each(function(){
var $element = $(this);
var top = $element.offset().top;
var height = getHeight($element);
// Check if totally above or totally below viewport
if (top + height < pos || top > pos + windowHeight) {
return;
}
$this.css('backgroundPosition', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
});
}
$window.bind('scroll', update).resize(update);
update();
};
})(jQuery);
Here is the CSS for one section:
#aboutwrapper {
background-image: url(../images/polaroid.png);
background-position: 50% 0;
background-repeat: no-repeat;
background-attachment: fixed;
color: white;
height: 500px;
width: 100%;
margin: 0 auto;
padding: 0;
}
#aboutwrapper .image4 {
background: url(../images/polaroid2.png) 50% 0 no-repeat fixed;
height: 500px;
width: 100%;
margin: 0 auto;
padding: 0;
}
.image3{
margin: 0 auto;
min-width: 970px;
overflow: auto;
width: 970px;
}
Both of these are being called to achieve the parallax scrolling. I really just want to more specifically control the background image locations. I've tried messing with the CSS background position and I've messed with the first javascript snippet as well. No luck.
just a quick shot, have you tried actually placing the images, either in a div or just using the img src tag to actually move the element rather than manipulating the y axis of a background image?