Horizontal scrolling menu with Javascript - javascript

I have created a menu that it is bigger than the width of the page.
And I want when it goes to it's last item, the first will appear again like a circle with no end.
here is the css code of the menu
`.slider
width: 200%
height: 65vh
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)
display: flex
align-items: center
user-select: none
transition: all 0s
&:hover
cursor: grab`
and this is the js
var isDown = false;
var startX;
var mousePosition;
var offset = [0,0];
$('.slider').mousedown(function(e) {
$(this).css('cursor', 'grabbing');
$('.pointer').css({'width': '55px', 'height': '55px'});
isDown = true;
startX = e.clientX;
offset = [
this.offsetLeft - e.clientX,
this.offsetTop - e.clientY
];
// var startX = e.pageX;
// var math = Math.round(Math.sqrt(Math.pow(startX - event.clientX, 2))) + 'px';
// $(this).css('transform', 'translate(' + math + 'px, -50%)');
// console.log(math);
});
$('.slider').mousemove(function(e) {
// e.preventDefault();
if (isDown){
// var tap = $('.slider').offset().left;
// console.log(e.pageX - tap);
mousePosition = e.clientX ;
console.log(mousePosition);
// $(this).css('transform', 'translate(' + mousePosition + ', -50%)');
// console.log(e);
this.style.left = (mousePosition + offset[0]) + 'px';
startX = mousePosition;
// this.style.transform = "translate3d(" + 0 + "1110px, " + 0 + "0px, 0)";
// div.style.left = (mousePosition.x + offset[0]) + 'px';
}
});
$('.slider').mouseup(function() {
$(this).css('cursor', 'grab');
$('.pointer').css({'width': '30px', 'height': '30px'});
isDown = false;
});
When the slider goes to it's last item it ends, but I want the first one to appear again.

May I suggest using an already existing library?
There is a library called Endless.js, and this does exactly what you asked for. The demo can be found here.

Related

Get the current position of moving element - on mouse click

I have an HTML element that is moving from point A to point B.
I want to get the specific position of this element when I click the mouse while the element is moving to point B.
How can I do this?
HTML
<div id="contentContainer">
<div id="thing"></div>
</div>
css
#thing {
border-radius: 50%;
position: absolute;
width: 40px;
height: 40px;
left: 0px;
top: 0px;
background-color: red;
transition: 1s cubic-bezier(.5, .51, .7, .68),
1s cubic-bezier(.5, .51, .7, .68);
}
js
var theThing= document.querySelector("#thing");
var container = document.querySelector("#contentContainer");
//create random position to move the #thing to it
var xPosition = Math.random()*(container.clientWidth-40);
var yPosition = Math.random()*(container.clientHeight-40);
// add the new position
theThing.style.left = xPosition + "px";
theThing.style.top = yPosition + "px";
container.addEventListener("click", function(event) {
//here i want to click to get current specific position of #thing
}
Check this code:
// Code goes here
window.onload = function() {
var theThing = document.querySelector("#thing");
var container = document.querySelector("#contentContainer");
//create random position to move the #thing to it
var xPosition = Math.random() * (container.clientWidth - 40);
var yPosition = Math.random() * (container.clientHeight - 40);
// add the new position
theThing.style.left = xPosition + "px";
theThing.style.top = yPosition + "px";
document.body.addEventListener("click", function(event) {
var pos = getPosition(theThing);
alert(pos.top + "," + pos.left);
});
}
function getPosition(element) {
var x = window.scrollX + element.getBoundingClientRect().left;
var y = window.scrollY + element.getBoundingClientRect().top;
return {
top: x,
left: y
};
}

On mousemove translate div position within a specified range

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

Resizing div top left corner using jquery

I have a div which I want to resize from all sides and corners, i.e. nw, n, ne, e, w, sw, s, se. I have tried jquery ui's resizable plugin but in my code that is not working. I have removed complexity from my code and placed it in a very basic fiddle.
I have tried to resize only north-west corner of a div and put that logic in fiddle. Logic seems correct to me but mouse interaction is working in a weird way.
Can you guys tell me what am I doing wrong here? If I get it correct for top left corner I can manage for the remaining ones. Thanks.
HTML:
<div id="box">
<div id="nw"></div>
<div id="n"></div>
<div id="ne"></div>
<div id="w"></div>
<div id="e"></div>
<div id="sw"></div>
<div id="s"></div>
<div id="se"></div>
</div>
<p class="one"></p>
<p class="two"></p>
CSS:
#box{border:1px solid #000;width:100px;height:100px;background-color:red;position:absolute;top:100px;left:100px}
#box > div{height:10px;width:10px;background-color:#000;position:absolute}
#nw{top:-5px;left:-5px;cursor:nw-resize}
#n{top:-5px;left:45px;cursor:n-resize}
#ne{top:-5px;right:-5px;cursor:ne-resize}
#w{top:45px;left:-5px;cursor:w-resize}
#e{top:45px;right:-5px;cursor:e-resize}
#sw{bottom:-5px;left:-5px;cursor:sw-resize}
#s{bottom:-5px;left:45px;cursor:s-resize}
#se{bottom:-5px;right:-5px;cursor:se-resize}
p{margin-top:250px;font-size:8px}
JS:
$(function(){
var mousepress = false;
$("#box > div").mousedown(function(e){
mousepress = true;
});
$("#box > div").mousemove(function(e){
if(mousepress) {
var boxX = $("#box").position().left;
var boxY = $("#box").position().top;
var boxW = $("#box").width();
var boxH = $("#box").height();
var x = boxX - e.pageX;//$(this).position().left;
var y = boxY - e.pageY;//$(this).position().top;
$("p.two").append("x: "+x+"<br />");
$(this).css({
"top":y+"px",
"left":x+"px"
});
$("#box").css({
"top":(boxY+y-5)+"px",
"left":(boxX+x-5)+"px",
"width":(boxW+x)+"px",
"height":(boxH+y)+"px",
});
}
});
$("#box > div").mouseup(function(){
mousepress = false;
});
});
**JSFIDDLE: **http://jsfiddle.net/ashwyn/v8qoLj76/2/
I didn't quite understand how you calculated the size and position of the box, without knowing which of the inside divs the user pressed.
I have changed it to use the mouse event position.
I also moved the mousemove and mouseup events to the document, because when dragging using the mouse, it may move faster then the DOM and got out of the box.
I also changed positions of inside divs to use 50% so it will always be in the middle. You may need to add a bit of margin to have it better centered. (See north vs south - I added margin-left to one of them)
This works fine for me.
http://jsfiddle.net/v8qoLj76/4/
var prev_x = -1;
var prev_y = -1;
var dir = null;
$("#box > div").mousedown(function(e){
prev_x = e.clientX;
prev_y = e.clientY;
dir = $(this).attr('id');
});
$(document).mousemove(function(e){
if (prev_x == -1)
return;
var boxX = $("#box").position().left;
var boxY = $("#box").position().top;
var boxW = $("#box").width();
var boxH = $("#box").height();
var dx = e.clientX - prev_x;
var dy = e.clientY - prev_y;
//Check directions
if (dir.indexOf('n') > -1) //north
{
boxY += dy;
boxH -= dy;
}
if (dir.indexOf('s') > -1) //south
{
boxH += dy;
}
if (dir.indexOf('w') > -1) //west
{
boxX += dx;
boxW -= dx;
}
if (dir.indexOf('e') > -1) //east
{
boxW += dx;
}
$("#box").css({
"top":(boxY)+"px",
"left":(boxX)+"px",
"width":(boxW)+"px",
"height":(boxH)+"px",
});
prev_x = e.clientX;
prev_y = e.clientY;
});
$(document).mouseup(function(){
prev_x = -1;
prev_y = -1;
});
Is it something that you need (see the snippet below)?
$(function() {
var ORIGINAL_TOP = 100, ORIGINAL_LEFT = 100, ORIGINAL_WIDTH = 100, ORIGINAL_HEIGHT = 100, OFFSET = 5;
$('.top').css({top: (ORIGINAL_TOP - OFFSET) + 'px'});
$('.left').css({left: (ORIGINAL_LEFT - OFFSET) + 'px'});
$('.bottom').css({top: (ORIGINAL_TOP + ORIGINAL_HEIGHT - OFFSET) + 'px'});
$('.right').css({left: (ORIGINAL_LEFT + ORIGINAL_WIDTH - OFFSET) + 'px'});
$('.control-element').css({height: (2 * OFFSET) + 'px', width: (2 * OFFSET) + 'px'});
var moveMiddleControls = function(top, left, width, height) {
['top', 'bottom'].forEach(function(coordinate) {
$('#' + coordinate).css({left: (left + width / 2 - OFFSET) + 'px'});
});
['left', 'right'].forEach(function(coordinate) {
$('#' + coordinate).css({top: (top + height / 2 - OFFSET) + 'px'});
});
};
var resizeBox = function(top, left, width, height) {
$('#box').css({
top: top + 'px',
left: left + 'px',
width: width + 'px',
height: height + 'px'
});
};
var updateStatus = function(top, left, width, height) {
$('#status-top').html(Math.round(top));
$('#status-left').html(Math.round(left));
$('#status-width').html(Math.round(width));
$('#status-height').html(Math.round(height));
};
var updatePosition = function(top, left, width, height) {
resizeBox(top, left, width, height);
moveMiddleControls(top, left, width, height);
updateStatus(top, left, width, height);
};
var update = function() {
updatePosition(
$('#top').position().top + OFFSET,
$('#left').position().left + OFFSET,
$('#right').position().left - $('#left').position().left,
$('#bottom').position().top - $('#top').position().top
);
};
update();
var activeElement;
$('.control-element').mousedown(function(e) {
activeElement = this;
e.preventDefault();
return false;
});
$(document).mousemove(function(e) {
if(activeElement !== undefined) {
['top', 'bottom'].forEach(function(className) {
if($(activeElement).hasClass(className)) {
$('.' + className).css({top: e.pageY + 'px'});
}
});
['left', 'right'].forEach(function(className) {
if($(activeElement).hasClass(className)) {
$('.' + className).css({left: e.pageX + 'px'});
}
});
update();
}
});
$(document).mouseup(function() {
activeElement = undefined;
});
});
#box {
border:1px solid #000;
background-color:red;
position: fixed;
}
.control-element {
background-color: #000;
position: fixed;
}
#top-left {
cursor: nw-resize;
}
#top {
cursor:n-resize;
}
#top-right {
cursor:ne-resize;
}
#left {
cursor:w-resize;
}
#right {
cursor:e-resize;
}
#bottom-left {
cursor:sw-resize;
}
#bottom {
cursor:s-resize;
}
#bottom-right {
cursor: se-resize;
}
.status {
position:fixed;
right: 5px;
bottom: 10px;
width: 80px;
height: 80px;
z-index: 999;
font-size:8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="box"></div>
<div id="top-left" class="control-element top left"></div>
<div id="top" class="control-element top"></div>
<div id="top-right" class="control-element top right"></div>
<div id="right" class="control-element right"></div>
<div id="bottom-right" class="control-element bottom right"></div>
<div id="bottom" class="control-element bottom"></div>
<div id="bottom-left" class="control-element bottom left"></div>
<div id="left" class="control-element left"></div>
<div class="status">
<div>top: <span id="status-top"></span>px</div>
<div>left: <span id="status-left"></span>px</div>
<div>width: <span id="status-width"></span>px</div>
<div>height: <span id="status-height"></span>px</div>
</div>

How to resize a div on drag? [Issue with rotation]

I need to be able to re-size a div when dragging two handlers.
Please use the following link
http://jsbin.com/lopumaheyu/1/
Click the green box, after drag orange boxes, the script work correctly and green box is re-sized.
I have an issue when CSS rotation is being applied to the green box, example:
http://output.jsbin.com/zirugeroju/1/
As you can notice there is a swift for the opposite knob an user is dragging.
What could be wrong here and how to fix it?
A better solution also with jQuery is also welcome
resize: function (handler, event) {
if (event.clientX <= 0) { // cover bug
return;
}
var elm = document.getElementById(this.config.elm);
switch (handler) {
case 'tl':
// x
var marginR = elm.offsetLeft + elm.clientWidth,
newW = marginR - event.clientX,
xPos = event.clientX;
elm.style.left = xPos + 'px';
elm.style.width = newW + 'px';
// y
var marginT = elm.offsetTop + elm.clientHeight,
newH = marginT - event.clientY,
yPos = event.clientY;
elm.style.top = yPos + 'px';
elm.style.height = newH + 'px';
this.setPositionHandlers();
break;
case 'tr':
break;
case 'bl':
break;
case 'br':
var newW = event.clientX - this.config.x,
newH = event.clientY - this.config.y;
elm.style.width = newW + 'px';
elm.style.height = newH + 'px';
this.setPositionHandlers();
break;
}
},
I think you can add:
-webkit-transform-origin: left top;
on #target to avoid the little swift on top left orange handler.
#target {
background-color: lightgreen;
-ms-transform: rotate(10deg);
-webkit-transform: rotate(10deg);
-webkit-transform-origin: left top;
transform: rotate(10deg);
}

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!

Categories

Resources