On mousemove translate div position within a specified range - javascript

I have a wrapper called #mousearea and I have a div called #mouseshift what I would like to do is when I hover over #mousearea I would like to shift the translate3d(0,230%,0) value between a particular range.
I have got the mousemove working but I currently end up with something like translate3d(7881%,230%,0) it's just too sensetive I would like it to translate the X co-ordinate between something like 0-60% so it's far more subtle.
Here is what I have so far:
jQuery(document).ready(function($){
$('#mousearea').mousemove(function (e) {
var shiftAmount = 1;
$('#mouseshift').css(
'transform', 'rotate(90deg) translate3d(' + -e.pageY + shiftAmount + '%,230%,0)'
);
});
});
Update:
This is a little closer, except it logs the correct translate3d but doesn't apply it to #mouseshift.
$('#mousearea').mousemove(function(e){
var x = e.pageY - this.offsetTop;
var transfromPosition = 'translate3d(' + x + ', 230%, 0)';
console.log(transfromPosition);
if ((x <= 800)) {
//$('#mouseshift').css({'top': x});
$('#mouseshift').css('transform', transfromPosition);
}
});
Final Solution:
jQuery(document).ready(function($){
$('#mousearea').mousemove(function(e){
var min = 50;
var max = 70;
var x = e.pageY;
var windowHeight = window.innerHeight;
scrolled = (x / windowHeight);
percentageScrolled = scrolled * 100;
offsetScroll = max - min;
offsetPercentage = scrolled * 20;
translateX = min + offsetPercentage;
console.log(x + 'px');
console.log(windowHeight + 'px window height');
console.log(percentageScrolled + '% scrolled');
console.log(offsetScroll + 'offset scroll');
console.log(offsetPercentage + '% offset percentage');
var transfromPosition = 'rotate(90deg) translate3d(' + translateX + '%, 230%, 0)';
$('#mouseshift h1').css('transform', transfromPosition);
});
});
Convert to a reusable plugin I would like to extend this to work with more than one object now and each object would have a different max and min value:
This is what I have but it seems to effect all the items on only use on elements max and min.
$(function () {
$('#mouseshift-1, #mouseshift-2').mouseShift();
});
(function ($) {
$.fn.mouseShift = function () {
return this.each(function () {
var myEl = $(this);
var min = $(this).data('min');
var max = $(this).data('max');
$('#mousearea').mousemove(function (e) {
var yPosition = e.pageY;
var windowHeight = window.innerHeight;
scrolled = (yPosition / windowHeight);
//percentageScrolled = scrolled * 100;
offsetRange = max - min;
offsetRangePercentage = scrolled * 20;
offset = min + offsetRangePercentage;
//// Debug
console.log('max: ' + max + ', Min:' + min);
console.log(yPosition + 'px');
console.log(windowHeight + 'px window height');
//console.log(percentageScrolled + '% scrolled');
console.log(offsetRange + 'px offset scroll');
console.log(offsetRangePercentage + '% offset percentage');
var transfromPosition = 'rotate(90deg) translate3d(' + offset + '%, 230%, 0)';
myEl.css('transform', transfromPosition);
});
});
};
})(jQuery);
And some HTML for clarity:
<div class="column"><h1 id="mouseshift-1" data-min="50" data-max="70">boo</h1></div>
<div class="column"><h1 id="mouseshift-2" data-min="20" data-max="90">bah</h1></div>
<div class="column"><h1 id="mouseshift-3" data-min="80" data-max="100">bing</h1></div>

I think what you are looking for is finding an average that your can distribute. The best way to do this is to divide by the maximum amount it can move, and multiply it by the maximum value it can have, so basically:
position / maxposition * maxvalue
The first bit will return a number between 0 and 1, while the last bit will make it the value between 0 and 60. Below I have built a simply (jquery-less) version of it to show how this would work:
var mousePointer = document.getElementById('test')
document.addEventListener('mousemove', function(e){
var x = e.pageX / window.innerHeight;
x = x * -60;
mousePointer.style.webkitTransform = 'translateX(' + x + '%)';
mousePointer.style.transform = 'translateX(' + x + '%)';
})
#test {
position: absolute;
left: 50%;
top: 50%;
width: 20px;
height: 20px;
background: red;
}
<div id="test"></div>
Update: Reusable Snippet
I don't really like using jQuery, so once again it will be vanilla javascript (but it's pretty simple). Is that what you were - sort of - trying to do with the reusable plugin?
var divs = Array.prototype.slice.call(document.querySelectorAll('[data-range]'));
document.addEventListener('mousemove', function(e){
var eased = e.pageX / window.innerWidth;
divs.forEach(function(div){
var range = div.getAttribute('data-range').split(',');
var min = parseFloat(range[0]);
var max = parseFloat(range[1]);
var ease = min + (eased * (max - min));
div.style.webkitTransform = 'translateX(' + ease + '%)';
div.style.transform = 'translateX(' + ease + '%)';
});
});
div {
position: absolute;
left: 50%;
top: 50%;
width: 200px;
height: 200px;
background: gray;
}
#d2 { background: yellow; }
#d3 { background: #666; }
<div data-range="60,70" id="d1"></div>
<div data-range="-70,70" id="d2"></div>
<div data-range="-60,-70" id="d3"></div>

From simple reading, I see that you're missing a % sign. Should be like this:
$('#mousearea').mousemove(function(e){
var x = e.pageY - this.offsetTop;
var transfromPosition = 'translate3d(' + x + '%, 230%, 0)';
console.log(transfromPosition);
if ((x <= 800)) {
//$('#mouseshift').css({'top': x});
$('#mouseshift').css('transform', transfromPosition);
}
});
This should be working like your first example, where you do use % for both values inside the translate3d string.
Update:
To coerce your x Value to something between 0 and 60, you need to find a pair of possible min and max values for x. Then you can do something like what's shown in this answer:
Convert a number range to another range, maintaining ratio

Related

Determine click position on progress bar?

Is it possible to determine the value/position of a user's click on a progress bar using plain javascript?
Currently, I can detect a click on the element but can only get the current position of the bar, not related to the user's click.
http://jsfiddle.net/bobbyrne01/r9pm5Lzw/
HTML
<progress id="progressBar" value="0.5" max="1"></progress>
JS
document.getElementById('progressBar').addEventListener('click', function () {
alert('Current position: ' + document.getElementById('progressBar').position);
alert('Current value: ' + document.getElementById('progressBar').value);
});
You can get the coordinates of where you clicked inside of the element like this:
Just subtract the offset position of the element from the coordinate of where the page was clicked.
Updated Example
document.getElementById('progressBar').addEventListener('click', function (e) {
var x = e.pageX - this.offsetLeft, // or e.offsetX (less support, though)
y = e.pageY - this.offsetTop, // or e.offsetY
clickedValue = x * this.max / this.offsetWidth;
console.log(x, y);
});
If you want to determine whether the click event occurred within the value range, you would have to compare the clicked value (in relation to the element's width), with the the value attribute set on the progress element:
Example Here
document.getElementById('progressBar').addEventListener('click', function (e) {
var x = e.pageX - this.offsetLeft, // or e.offsetX (less support, though)
y = e.pageY - this.offsetTop, // or e.offsetY
clickedValue = x * this.max / this.offsetWidth,
isClicked = clickedValue <= this.value;
if (isClicked) {
alert('You clicked within the value range at: ' + clickedValue);
}
});
<p>Click within the grey range</p>
<progress id="progressBar" value="5" max="10"></progress>
$(document).ready(function() {
$(".media-progress").on("click", function(e) {
var max = $(this).width(); //Get width element
var pos = e.pageX - $(this).offset().left; //Position cursor
var dual = Math.round(pos / max * 100); // Round %
if (dual > 100) {
var dual = 100;
}
$(this).val(dual);
$("#progress-value").text(dual);
});
});
.media-progress {
/*BG*/
position: relative;
width: 75%;
display: inline-block;
cursor: pointer;
height: 14px;
background: gray;
border: none;
vertical-align: middle;
}
.media-progress::-webkit-progress-bar {
/*Chrome-Safari BG*/
background: gray;
border: none
}
.media-progress::-webkit-progress-value {
/*Chrome-Safari value*/
background: #17BAB3;
border: none
}
.media-progress::-moz-progress-bar {
/*Firefox value*/
background: #17BAB3;
border: none
}
.media-progress::-ms-fill {
/*IE-MS value*/
background: #17BAB3;
border: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<progress value="5" max="100" class="media-progress"></progress>
<div id="progress-value"></div>
If you want the value clicked for a generic max value (a value between 0 and 1 in this case), you just need some simple math.
document.getElementById('progressBar').addEventListener('click', function (e) {
var value_clicked = e.offsetX * this.max / this.offsetWidth;
alert(value_clicked);
});
Fiddle
I tested your project, try this solution:
document.getElementById('progressBar').addEventListener('click', function (e) {
var x = e.pageX - this.offsetLeft;
//Uncomment the following line to activate alert
//alert('Current position: ' + document.getElementById('progressBar').position);
//Save position before the click
var startPos = document.getElementById('progressBar').position;
//Convert x value to progress range [0 1]
var xconvert = x/300; //cause width is 300px and you need a value in [0,1] range
var finalx = (xconvert).toFixed(1); //round up to one digit after coma
//Uncomment the following line to activate alert
//alert('Click value: ' + finalx);
//If you don't want change progress bar value after click comment the following line
document.getElementById('progressBar').value = finalx;
document.getElementById('result').innerHTML = ('Start position: ' + startPos + "<br/><br/>");
document.getElementById('result').innerHTML += ('Current position: ' + document.getElementById('progressBar').position + "<br/>");
document.getElementById('result').innerHTML += ('Current value: ' + document.getElementById('progressBar').value + "<br/></br/>");
document.getElementById('result').innerHTML += ('Real click value: ' + xconvert + "<br/>");
document.getElementById('result').innerHTML += ('Current value set in progressbar: ' + finalx + "<br/>");
});
#progressBar {
width:300px;
}
<progress id="progressBar" value="0.5" max="1"></progress>
<div id="result"></div>
I set your progress bar width to 300px (you can change it)
Get position x in progress bar
Convert x position range from [0,300] to [0,1]
Change value inside progress bar
Outputs:
Start Position
Current Position and Value (after click)
Real click value (not rounded up)
Value set in progressbar (rounded up)
Working demo:
http://jsfiddle.net/Yeti82/c0qfumbL
Thanks to bobbyrne01 for update corrections!
The top voted answer is not actually going to work universally.
This is because the you have to consider all the offsetLeft of all the offsetParents.
Here is an improved answer. I hope it helps.
__addProgressBarListener () {
document.getElementById('video-player-progress-bar').addEventListener('click', function (e) {
let totalOffset = this.offsetLeft
let parent = this.offsetParent
const maximumLoop = 10
let counter = 0
while (document.body !== parent && counter < maximumLoop) {
counter += 1
totalOffset += parent.offsetLeft
parent = parent.offsetParent
}
const x = e.pageX - totalOffset // or e.offsetX (less support, though)
const clickedValue = x / this.offsetWidth
console.log('x: ', x)
console.log('clickedValue: ', clickedValue)
})
},
I found a simple solution with pure javascript.
using getBoundingClientRect() there are all properties to calculate the percentage.
document.getElementById('progressBar').addEventListener('click', function (e) {
var bounds = this.getBoundingClientRect();
var max = bounds.width //Get width element
var pos = e.pageX - bounds.left; //Position cursor
var dual = Math.round(pos / max * 100); // Round %
console.log('percentage:', dual);
});
The click event actually takes a parameter that includes event information including the click position information. You can use this to determine where in the progress bar the click occured.
document.getElementById('progressBar').addEventListener('click', function (event) {
document.getElementById('result').innerHTML = ('Current position: ' + document.getElementById('progressBar').position + "<br/>");
document.getElementById('result').innerHTML += ('Current value: ' + document.getElementById('progressBar').value + "<br/>");
document.getElementById('result').innerHTML += ('Mouse click (absolute): ' + event.offsetX + ", " + event.offsetY + "<br/>");
});
<progress id="progressBar" value="0.5" max="1"></progress>
<div id="result"></div>
For those willing to use a slider instead of a progress bar, obtaining the value would be much easier:
HTML
<input type="range" min="0" max="100" value="50" id="slider">
JavaScript
const slider = document.getElementById('slider');
slider.onclick = () => alert('Current value: ' + slider.value);

How to scale DIV elements with CSS3 and keep the distances between them

I'm trying to scale some divs inside a 'workspace' div. The problem I have are with the distance between them (I lose it).
I have read a lot of post about CSS3 transform, in special about scale and translate and origin, but I can't solve the problem...
Can someone explain me how can I keep them? I show one code using a mousewheel plugin, regards.
HTML
<body>
<div id="workspace">
<div style="z-index: 101;"><img src="image1-300x300.jpg" /></div>
<div style="z-index: 102; left: 300px; top: 400px;"><img src="image2-400x400.jpg" /></div>
</div>
</body>
CSS
#workspace {
width: 1600px;
height: 900px;
position: absolute;
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: inline;
}
#workspace > div {
display: inline;
position: absolute;
}
JAVASCRIPT
$(document).ready(function () {
var scale = 1; // scale of the image
var xLast = 0; // last x location on the screen
var yLast = 0; // last y location on the screen
var xImage = 0; // last x location on the image
var yImage = 0; // last y location on the image
// if mousewheel is moved
$("#workspace").mousewheel(function (e, delta) {
// find current location on screen
var xScreen = e.pageX - $(this).offset().left;
var yScreen = e.pageY - $(this).offset().top;
// find current location on the image at the current scale
xImage = xImage + ((xScreen - xLast) / scale);
yImage = yImage + ((yScreen - yLast) / scale);
// determine the new scale
if (delta > 0) {
scale *= 2;
}
else {
scale /= 2;
}
scale = scale < 1 ? 1 : (scale > 64 ? 64 : scale);
// determine the location on the screen at the new scale
var xNew = (xScreen - xImage) / scale;
var yNew = (yScreen - yImage) / scale;
// save the current screen location
xLast = xScreen;
yLast = yScreen;
// redraw
$('#mosaicContainer > div').each(function() {
$(this).css('-webkit-transform', 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')')
.css('-webkit-transform-origin', (xImage) + 'px ' + (yImage) + 'px');
});
return false;
});
});

Add non-click function inside of a click function

I have the following problem. I have a .one("click") function with a variable that raises itself, and I need to add a function, that triggers, when the variable hits the wanted point. I mean, in the following code I need to use the connect function for the last 'last' img with the 'home' img, after the Result variable turns 9, which will produce a line between them, and I'll have a complete circle. Please read the code and try clicking on all img-es so that you can understand, what i need to achieve. Thanks in advance.
Here's the code:
$(document).ready(function() {
var Result = 0;
$('img').one("click", function(){
if( $('img.home').length == 0 ){
$(this).addClass('home');
}
if(Result <= 9){
var $elem2 = $('span.last');
var $elem1 = $(this).parent();
$(this).toggleClass('selected');
if ($elem2.length > 0) {
connect($elem1[0], $elem2[0], "#0F0", 5);
}
else {
$elem1.addClass('last');
}
$('span').removeClass('last');
$elem1.addClass('last');
Result++;
}
});
});
function connect(div1, div2, color, thickness) {
var off1 = getOffset(div1);
var off2 = getOffset(div2);
// bottom right
var x1 = off1.left + off1.width;
var y1 = off1.top + off1.height;
// top right
var x2 = off2.left + off2.width;
var y2 = off2.top;
// distance
var length = Math.sqrt(((x2-x1) * (x2-x1)) + ((y2-y1) * (y2-y1)));
distanz += parseInt(length);
// center
var cx = ((x1 + x2) / 2) - (length / 2);
var cy = ((y1 + y2) / 2) - (thickness / 2);
// angle
var angle = Math.atan2((y1-y2),(x1-x2))*(180/Math.PI);
// make hr
var htmlLine = "<div style='padding:0px; margin:0px; height:" + thickness + "px; background-color:" + color + "; line-height:1px; position:absolute; left:" + cx + "px; top:" + cy + "px; width:" + length + "px; -moz-transform:rotate(" + angle + "deg); -webkit-transform:rotate(" + angle + "deg); -o-transform:rotate(" + angle + "deg); -ms-transform:rotate(" + angle + "deg); transform:rotate(" + angle + "deg);' />";
htmlLine = $(htmlLine);
$('body').append(htmlLine);
return htmlLine;
}
function getOffset( el ) {
var x = 0;
var y = 0;
var w = el.offsetWidth|0;
var h = el.offsetHeight|0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
x += el.offsetLeft - el.scrollLeft;
y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: y, left: x, width: w, height: h };
}
jsfiddle: http://jsfiddle.net/CDQhX/4/
I want to execute the connect(home and span images) after the last line is done and the Result is 9. This can't be done inside the click function, since I'm not clicking anywhere to trigger it. My knowledge don't let me work the problem around. So I appreciate any help. I'll be really glad to receive answers.
First of all, what do you mean you are not clicking anywhere and you want it executed when the last img is clicked. Can't you just check if the img is last when it is clicked, and execute what you need?
Also, on the other hand, you can try setTimeout and setInterval as described here: http://www.w3.org/TR/2011/WD-html5-20110525/timers.html
So, for example, you could do something like this:
setInterval( function() {
//do your thing
}, 500);
Which will execute the function every 500 milliseconds, so you could use that for periodic checking of your variables.

define start to finish positions

I am creating a new "whack-a-mole" style game where the children have to hit the correct numbers in accordance to the question. So far it is going really well, I have a timer, count the right and wrong answers and when the game is started I have a number of divs called "characters" that appear in the container randomly at set times.
I have been given a theme of bubbles so they want me to make the "characters" start at the bottom and animate upwards. Any ideas how I would achieve this?
Here is the code that currently maps the divs to there positions in the canvas...
function moveRandom(id) {
var cPos = $('#container').offset();
var cHeight = $('#container').height();
var cWidth = $('#container').width();
var pad = parseInt($('#container').css('padding-top').replace('px', ''));
var bHeight = $('#' + id).height();
var bWidth = $('#' + id).width();
maxY = cPos.top + cHeight - bHeight - pad;
maxX = cPos.left + cWidth - bWidth - pad;
minY = cPos.top + pad;
minX = cPos.left + pad;
newY = randomFromTo(minY, maxY);
newX = randomFromTo(minX, maxX);
$('#' + id).css({
top: newY,
left: newX
}).fadeIn(1000, function() {
setTimeout(function() {
$('#' + id).fadeOut(1000);
window.cont++;
}, 7000);
});
Here is my most recent fiddle: http://jsfiddle.net/pUwKb/15/
The part below actually set the CSS (and thus the position of your element).
$('#' + id).css({
top: newY,
left: newX }).fadeIn(1000, function() {
setTimeout(function() {
$('#' + id).fadeOut(1000);
window.cont++;
}, 7000); });
You should add a function move who uses a movement variable. Small example:
function move(movement, id) {
$('#' + id).css({
top: this.css('top') + movement.y,
left: this.css('left') + movement.x
}).fadeIn(1000, function() {
setTimeout(function() {
$('#' + id).fadeOut(1000);
window.cont++;
}, 7000);
});
}
Where in movement should be an object something the like of {x: 30, y: 0} which would result in a 30 pixels movement to the right. Hope it helps!

How do I dynamically scale elements in a specific Javascript that only uses pixels?

I am trying to use the jQuery plugin: Floating boxes with easing and motion-blur in jQuery By: Marcell Jusztin.
I have it working just fine and understand how to tweak most attributes, but I am a Javascript rookie and really do not understand the mechanics involved in changing how it uses math to place the elements I want to animate. What I want to do is change the set x and y offset coordinates (which are in pixels of course) to a set of percentages so that the elements will dynamically scale in position based on screen resolution. Here is the script in its entirety:
jQuery.fn.floatingBox = function ( userOptions ) {
options = jQuery.extend ({
parent : 'backdrop',
stage : 'backdrop',
scale : 0.3,
xOffset : 0,
yOffset : 0,
blur : false,
isText : false,
blurColor : '#888',
frameRate : 40,
}, userOptions);
var parent = options.parent;
var stage = options.stage;
var scale = options.scale;
var xOffset = options.xOffset;
var yOffset = options.yOffset;
var blur = options.blur;
var isText = options.isText;
var blurColor = options.blurColor;
var frameRate = options.frameRate;
var midX = $('#' + stage).width() / 2;
var midY = $('#' + stage).height() / 2;
var _x = midX;
var _y = midY;
var xx = midX;
var yy = midY;
var objectId = $(this).attr('id');
$('#' + objectId).css('position','absolute');
shadowAmount = 0;
window["timer" + objectId] = window.setInterval(update,frameRate);
$('#' + parent).mousemove(function(event){
_x = event.pageX;
_y = event.pageY;
if( shadowAmount < 5 && blur == true ) shadowAmount += scale;
});
factor = scale * 0.5;
function update() {
xx += (((_x - midX) * -scale) - xx) * factor;
yy += (((_y - midY) * -scale) - yy) * factor;
$('#' + objectId).css('left', xx + xOffset + $('#' + parent).position().left);
$('#' + objectId).css('top', yy + yOffset + $('#' + parent).position().top);
if(blur){
if(!isText){
$('#' + objectId).css('box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
$('#' + objectId).css('-moz-box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
$('#' + objectId).css('-webkit-box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
$('#' + objectId).css('-o-box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
}else{
$('#' + objectId).css('text-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
}
if(shadowAmount > 0 ) shadowAmount -= scale;
}
}
}
Here is the script that initiates the javascript in the HTML document:
<script type="text/javascript">
jQuery(function(){
$('#biglogo').floatingBox({
scale : 0.09,
blur : false,
isText : false,
xOffset : 400,
yOffset: 200,
});
$('#biglogo2').floatingBox({
scale : 0.08,
blur : false,
isText : false,
xOffset : 405,
yOffset: 205,
});
});
</script>
I have two transparent png files that are layered over each other with a minor offset of 5 pixels (or maybe its considered 10), but would rather the two images be centered in all browser windows and not just mine. The scale indicates how fast and far the elements move. The xOffset and yOffset parameters are of course fixed numbers that don't scale based on browser window size.
I have attempted to research this but ultimately, I'm neither finding that it can't be done, nor that it can because no one response seems to address the specific issue I am having. Perhaps I am not wording it correctly.
Thanks!
From the looks of the script I would say that it already takes the necessary calculations into accout. Try setting the parent and stage options and leave out the offset parameters. I.e
$('#biglogo').floatingBox({
parent: 'container-id',
stage: 'container-id',
scale: 0.09,
blur: false,
isText: false
});
Edit: I created a fiddle with some modifications to the plugin that shows how to get centering working, http://jsfiddle.net/wwBJt/

Categories

Resources