My website's landing page (http://www.chrisamaddeo.com/) has a full screen background. I want to make it move like an example of this website's header (http://www.kaiserair.com/) I have this code, HTML, which goes in the head of my website:
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
var movementStrength = 25;
var height = movementStrength / $(window).height();
var width = movementStrength / $(window).width();
$("#top-image").mousemove(function(e){
var pageX = e.pageX - ($(window).width() / 2);
var pageY = e.pageY - ($(window).height() / 2);
var newvalueX = width * pageX * -1 - 50;
var newvalueY = height * pageY * -1 - 25;
$('#top-image').css("background-position", newvalueX+"px "+newvalueY+"px");
});
I have this code, css and it doesn't work:
#top-image {
background:url('https://d3ui957tjb5bqd.cloudfront.net/images/screenshots/products/0/8/8905/red-rocks-park-o.jpg' -50px -25px;
position:fixed ;
top:0;
width:100%;
z-index:0;
}
My website is hosted with weebly and their html is a little different
Actually, i've just tried copying your code:
http://codepen.io/chrisboon27/pen/rEDIC
It does work, in that it moves the image.
I did have to add some some closing braces to your jQuery but maybe you just missed those when you pasted the code into this question.
Also, I looked at your site and noticed you are currently using background-size:cover. This takes your bg image and makes it fit within the div - you dont want that as you want some bg extending beyond the div - so i'n the css in the example I linked to you can see I used calc to make the bg-image size to 100% width + 50px. I used 50px as your code currently moves the background image position by up to 25px left or right, therefore you need it to be 50px total wider than the div.
EDIT:
If you use calc you should include a -webkit prefixed version too (unless you are using prefix-free or prefixr to add prefixes. Here is browser support: http://caniuse.com/calc
If you need to support more browsers you will need to set background-size via javascript
I'm finding that quite hard to follow without recreating it and seeing where those numbers come from. However I recently made something very similar with jQuery for someone else except it moves an img within a div. It probably wouldn't take much to switch it to move a background image though (though finding out the bg-image dimensions would be tricky - you might be better hard coding them in that instance).
html:
<div class="container"><img src="foo.jpg" class="draggable"/>
</div>
jQuery:
//for each item
$(".container").each(function(){
//get the container width
var conWidth = $(this).width();
//and its height
var imgHeight = $(this).find("img").height();
//get the nested img width
var conHeight = $(this).height();
//and its height
var imgWidth = $(this).find("img").width();
//figure out how much of the image is not visible horizontally
var excessWidth = imgWidth - conWidth;
//and how much is not visible vertically
var excessHeight = imgHeight - conHeight;
//how far is this container from the left of the page
var containerPositionLeft = this.offsetLeft;
//and from the top
var containerPositionTop = this.offsetTop;
//when moving mouse over container
$(this).mousemove(function(e){
//figure out how many pixels the mouse is from the left edge of the page
var mouseoffLeftPage = e.pageX;
//and how many from the top edge of the page
var mouseoffTopPage = e.pageY;
//figure out how many pixels the mouse is from the left edge of the page
var mouseoffLeftPx = mouseoffLeftPage - containerPositionLeft;
//and how many from the top edge of the page
var mouseoffTopPx = mouseoffTopPage - containerPositionTop;
//figure out the distance the mouse is from the left edge as a percentage (kind of - all the way to the right equals 1 not 100)
var mouseoffLeftPercent = mouseoffLeftPx/conWidth;
//do the same for height
var mouseoffTopPercent = mouseoffTopPx/conHeight;
//times the 'percentage' value by the amount of image hidden - so if your conatiner is 200px wide, your image 300px wide nd your mouse is half way across this value would be 0.5*100 which would give you 50 - which is exactly half the amount of image that is missing.
//note this gets set as a minus value as we will be using a minus number to shift the image around.
var setnewWidth = -(mouseoffLeftPercent * excessWidth);
//do the same for the height
var setnewHeight = -(mouseoffTopPercent * excessHeight);
//add the values as css (using transform(translate) as it's more performant and does subpixel rendering so looks smoother [or does it? it does in animations but seems as my js is not technically animating it it might not make a difference in that respect] - could set the top,left version as fallback for unsupporting browsers but ie9 supports transforms anyway so i dont care.)
$(this).find("img").css({"transform" : "translate("+ setnewWidth+"px ,"+setnewHeight+"px)" });
//$(this).find("img").css({"left" : setnewWidth+"px", "top" : setnewHeight+"px" });
});
});
Not a direct answer to what isn't working in your code, but shows an example (with comments on what is happening) of how it can be done - note that my version doesn't rely on you knowing any of the widths or heights of objects and can run on multiple items on one page - also it doesn't have to be placed at the very top of the page. It does assume the image is larger than its container though - if it isn't larger the image just moves around within it.
You could reduce the number of variables by doing more calculations in a row, I just wanted it to be as easy to read the logic as possible.
DEMO:
http://codepen.io/chrisboon27/pen/BhkJq
Simpler than that, you can just make sure the CSS position is set to "fixed" so wherever you are on the page it's always 0px from the top.
Related
I am developing an Ionic App and it needs to have some buttons (one above another, not inline) on the bottom-left place of the device's screen
I have the following CSS:
.button {
left = "1em";
z-index = "13";
overflow = "scroll";
position = "absolute";
width = "3em";
height = "2.5em";
textAlign = "center";
}
and then I calculate its bottom like this:
let bottom: number = 0;
this.floors.forEach(floor => {
let floorButton: HTMLElement = document.createElement("button");
floorButton.setAttribute("class", "button");
floorButton.appendChild(document.createTextNode(floor.level));
floorButton.style.bottom = bottom + "em";
bottom = bottom + 5;
});
Now my problem is simple: in a device with a bigger screen than another device, it is positioning in an upper position.
I can workarround this by calculating the height of the device's screen and dividing it x times until I get to the position I want. But this looks dirty to me (I don't know if it's the right wait tho, maybe it is).
So my question is, is there a simpler way that doing this as the one I put above instead of having to calculate the screen's height size in pixels? Can it be done directly by CSS? I've checked #media but it looks like it won't help at all. Or maybe I'm just doing it right and I'm overthinking it too much?
Thanks!
You can just use CSS for this:
.button {
display: block;
margin-top: 5px;
}
In this way doesn't matter what is the width of screen, always your buttons will be in separate line.
So this one is a little hard to explain. I have a custom Text class that automatically resizes and sets the width of the text when you change its value. I then take that Text and draw it on a Bitmap to scale it up to make the text look pixelated.
I have a property called maxWidth that allows you to restrict the width of the text if you want it to maintain a certain width. By default the maxWidth is the width of the text's parent so that it doesn't get cut off or expand the parent's boundaries unexpectedly.
So unfortunately when I draw the text it sometimes gets cut off on the right side. Now I've checked all the values and the width and textWidth are showing up as within their maxWidth values, but when I take a look myself through screenshots I see the text is actually about 3 pixels wider than it should be.
Here's an image to better explain what I mean:
I turned on borders so you can easily see what I mean. The word "and" on the first line gets drawn outside its border. Here is the line of code that handles resizing text when you change its bounds.
override protected function checkResize(value:String):void {
var bufferWidth:uint = Math.floor(Number(defaultTextFormat.size) / bufferDivisor) + bufferMin;
var maxWidth:Number = this.maxWidth;
x = y = 0;
if (parent is Stage) {
var stageParent:Stage = Stage(parent);
super.width = stageParent.stageWidth;
super.height = stageParent.stageHeight;
if (maxWidth == 0) maxWidth = stageParent.stageWidth;
}
else {
super.width = parent.width;
super.height = parent.height;
if (maxWidth == 0) maxWidth = parent.width;
}
maxWidth = maxWidth / scale;
text = value;
if (textWidth + bufferWidth <= maxWidth) super.width = textWidth + bufferWidth;
else super.width = maxWidth;
super.height = textHeight + 4;
if (textSnapshot) updateSnapshot();
if (alignRelation) Align.alignTo(textSprite, alignRelation, alignDirection, alignXOffset, alignYOffest);
}
And for this text specifically the width value states it's 512, which is correct since that's the maxWidth. However if you notice the top line in the text, it goes beyond the 512 width border, it actually goes all the way to 515 even though it says its width is 512. Even more bizarre is the textWidth states it's 510.4 even though the first line goes well beyond that amount. I just want to know if I'm doing anything wrong or if there's a way to get a true textWidth value.
This seems to be related to embedding fonts, at least it was when I had the same problem. A workaround is to set the right margin of the text field, like so
var tf:TextFormat = new TextFormat();
tf.rightMargin = 10; // or whatever fixes your problem, e.g. relate it to font size
textField.setTextFormat(tf);
I like the Polymer paper elements and I want to use a paper-slider element.
However, i would like it to be vertical. I've tried to apply css to rotate it;
transform: rotate(90deg);
This rotates the slider, but not the "input"; one must still click and drag the mouse horizontally in order to get the "knob" to move up and down.
This is very annoying and any help is rely appreciated!
tk-vslider is a tweaked paper-slider with rotate functionality. Use this instead of paper-slider to solve this issue. Install using bower "tkvslider": "0.5.5"
<tk-vslider rotate="true"></tk-vslider>
Tweaks.
if rotate == true then
div#sliderContainer is css rotated by 90deg
Event on-trackx of the div#sliderKnob is replaced by on-track
In the method tracktake e.dy instead of e.dx.
This might be a pretty hacky way to do it, but we're coming up a year since you requested this as feature and it doesn't look like it's much of a priority yet. I figure this will (for the most part) allow for continued updates of paper-slider from the Polymer team without depending on third parties that might not continue support (from what I can tell, the custom element tk-vslider mentioned here hasn't been updated to support Polymer 1.0).
First, the css. I found that if I rotated 90 degrees, the smaller values were at the top of the slider, which I found to be counter-intuitive. So instead I rotate by -90. Some weird stuff happens with the margins but this is what finally did it for me:
paper-slider {
width: 20vh;
margin: 10vh -10vh;
--webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
I had my paper-slider inside my own custom element, so I put the following code in the ready callback, but I imagine you could put it anywhere you needed, as long as you can select the slider element. We're basically just going to override the method that paper-slider uses to respond to drag events. Here's how:
var slider = this.$.slider;
slider._trackX = function(e) {
if (!slider.dragging) {
slider._trackStart(e);
}
var dx = Math.min(slider._maxx, Math.max(slider._minx, (-1 * e.detail.dy)));
slider._x = slider._startx + dx;
var immediateValue = slider._calcStep(slider._calcKnobPosition(slider._x / slider._w));
slider._setImmediateValue(immediateValue);
// update knob's position
var translateY = ((slider._calcRatio(immediateValue) * slider._w) - slider._startx);
slider.translate3d(translateY + 'px', 0, 0, slider.$.sliderKnob);
};
Almost the entirety of this method is copied over from paper-slider source code, the only real change is that instead of grabbing the x coordinate in e.detail.dx we grab the y in e.detail.dy. The negative multiplier is only necessary if you want smaller values at the bottom of your slider, and you rotated your paper-slider by -90 degrees. Note that if the Polymer team ever changes the name of the method _trackX, it'll break this solution. I know this is a bit late but hopefully it'll help anyone else finding themselves in a similar situation (as I did).
UPDATE: Probably should have tested this solution a bit more, turns out there's another function that needs to be overwritten to handle click events (the other one only handles drag). I got it to work by adding this below my other method:
slider._bardown = function(event) {
slider._w = slider.$.sliderBar.offsetWidth;
var rect = slider.$.sliderBar.getBoundingClientRect();
var ratio = ((rect.bottom - event.detail.y) / slider._w);
var prevRatio = slider.ratio;
slider._setTransiting(true);
slider._positionKnob(ratio);
slider.debounce('expandKnob', slider._expandKnob, 60);
// if the ratio doesn't change, sliderKnob's animation won't start
// and `_knobTransitionEnd` won't be called
// Therefore, we need to manually update the `transiting` state
if (prevRatio === slider.ratio) {
slider._setTransiting(false);
}
slider.async(function() {
slider.fire('change');
});
// cancel selection
event.preventDefault();
}
The main change to this method is the line that calculates the ratio. Before it was var ratio = (event.detail.x - rect.left) / this._w;
<s-slider> has vertical property for vertical orientation https://github.com/StartPolymer/s-slider
zberry's answer didnt work for me anymore. However, I took his answer and updated it. The Polymer3 solution to make the paper-slider vertically responsive would look like this (given the same CSS zberry used):
let slider = this.shadowRoot.querySelector('paper-slider');
slider._trackX = function(event) {
if (!slider.dragging) {
slider._trackStart(event);
}
var dx =
Math.min(slider._maxx, Math.max(slider._minx, -1 * event.detail.dy));
slider._x = slider._startx + dx;
var immediateValue =
slider._calcStep(slider._calcKnobPosition(slider._x / slider._w * 100));
slider._setImmediateValue(immediateValue);
// update knob's position
var translateX =
((slider._calcRatio(slider.immediateValue) * slider._w) -
slider._knobstartx);
slider.translate3d(translateX + 'px', 0, 0, slider.$.sliderKnob);
};
slider._barclick = function(event) {
slider._w = slider.$.sliderBar.offsetWidth;
var rect = slider.$.sliderBar.getBoundingClientRect();
var ratio = (rect.bottom - event.detail.y) / slider._w * 100;
if (slider._isRTL) {
ratio = 100 - ratio;
}
var prevRatio = slider.ratio;
slider._setTransiting(true);
slider._positionKnob(ratio);
// if the ratio doesn't change, sliderKnob's animation won't start
// and `_knobTransitionEnd` won't be called
// Therefore, we need to manually update the `transiting` state
if (prevRatio === slider.ratio) {
slider._setTransiting(false);
}
slider.async(function() {
slider.fire('change', {composed: true});
});
// cancel selection
event.preventDefault();
// set the focus manually because we will called prevent default
slider.focus();
};
If you want to slide from top to down you have to fiddle with the directions
I'm working on a paint application and I'm trying to centre the canvas onto the middle of the screen . Any attempts I made the detection was off(still at the top left of the screen) but it was visually appearing in the centre of the screen.
Basically it wont draw onto the canvas when I moved it to the centre of the screen.
Any help would be much appreciated , Thanks....
I HAVE MY CODE BELOW ...
It's not clear from your question how you're centring it, but you need to account for any offset of elements which contain your canvas when you attempt to map the mouse position to a position on the canvas. You can do this by including the offsetLeft and offsetTop values (see docs) of the containing element when you do your calculations.
The following will work if you're offsetting the position of the div which wraps the canvas (which I've given an id to make it easier to reference):
function move(e) {
// Get the div containing the canvas. Would be more efficient to set this once on document load
var container = document.getElementById('container');
if((e.button == 0) && (mouseIsDown)) {
g.beginPath();
document.onselectstart = function(){ return false; }
//g.fillStyle = "red";
// Account for the offset of the parent when drawing to the canvas
g.arc((e.x - container.offsetLeft) - brush, (e.y - container.offsetTop) - brush, brush, 0, Math.PI * 2);
g.fill();
g.closePath();
}
}
And a simplistic demo using your fiddle here.
For reference: http://code.google.com/p/chromium/issues/detail?id=71937
Basically, the issue is that if you scale an iframe, the bounds of the contentWindow of the iframe get the scale modifier applied twice. So if, for example, you scale a 100x100 iframe by 50% (style="-webkit-transform: scale(0.5, 0.5);"), the new iframe bounds will be 50x50 but the contentWindow bounds will be 25x25. The actual content is correctly scaled.
I tried setting the innerHeight/innerWidth of the iframe contentWindow and while I was able to update the property, the contentWindow's visible bounds did not change.
Any input welcome, thanks!
For anyone that stumbles along this bug in the future. I solved it by applying the zoom transformations to the html node of the document inside the iframe rather than the iframe itself. I used the following code:
$(function() {
$("#iframe_name").load(function() {
$("#iframe_name").contents().find('html').css('-moz-transform', 'scale(<?=$scale?>)');
$("#iframe_name").contents().find('html').css('-moz-transform-origin', 'left top');
$("#iframe_name").contents().find('html').css('-webkit-transform', 'scale(<?=$scale?>)');
$("#iframe_name").contents().find('html').css('-webkit-transform-origin', 'left top');
$("#iframe_name").contents().find('html').css('transform', 'scale(<?=$scale?>)');
$("#iframe_name").contents().find('html').css('transform-origin', 'left top');
if (navigator.appVersion.match(/MSIE/)) {
$("#iframe_name").contents().find('html').css('zoom', '<?=(100*$scale)?>%');
}
});
});
This is using php and $scale is something like 0.5 for 50% of the size, or 2 for twice the size. It also uses jQuery.
Here's a solution that uses jQuery (1.4.2). The applied scale can be passed into the function, which then applies the appropriate reverse scale to the iframe. Targets versions of Chrome starting with 10.0.648
function iframeFix (scale) {
// Chrome 10 preview fix
// See: http://code.google.com/p/chromium/issues/detail?id=71937
//
// iframe is scaled twice in this version of Chrome.
// Fix is to apply a reverse scale on the iframe
var chrome_preview_bug_version = "Chrome/10.0.648";
if (navigator.userAgent.indexOf(chrome_preview_bug_version) > -1) {
var scale_fix = Math.sqrt(1/scale);
$('iframe').css({
'-webkit-transform': 'scale(' + scale_fix + ')',
'-webkit-transform-origin': '0 0'
});
}
}
We are currently working around this issue by increasing the size of the iframe such that the inner content window is the original size of the iframe, then repositioning the iframe such that the content window matches the original position of the iframe, then clipping the iframe so that only the content window is visible.
So, in our case, the code is something like:
var chromefix = 7;
var scale = .147;
frm.style.webkitTransform = 'scale(' + scale +',' + scale +')';
frm.style.width = basew/scale*chromefix + "px";
frm.style.height = baseh/scale*chromefix + "px";
frm.style.left = ( basex - ((basew/scale-basew)/2)*chromefix ) + "px";
frm.style.top = ( basey - ((baseh/scale-baseh)/2)*chromefix ) + "px";
frm.style.clip= 'rect(0px,'+basew/scale+'px,'+baseh/scale+'px, 0px)';