Multiple Transforms on mousemove jquery - javascript

Probably an easy fix, but for the life of me I can't figure it out or may be overthinking it. In short I have a div that rotatesY based on mousemove. I have that working, but I also need it to translate across the X axis as well. So I know I have to use transform: translateX(value), but not sure how to apply two transforms the best way in jquery. Thanks for the help. Fiddle link below.
Also is there a way to change the rotationY directions?
var $window = $(window),
$box = $('#box')
rotation = 0;
$window.on('mousemove', function(event){
rotation = (event.pageX/$window.width()*90) - 45;
$box.css('transform', 'perspective( 600px ) rotateY(' + rotation + 'deg)');
});
#box{
width: 300px;
height: 300px;
margin: 30px auto;
background: #aaa;
}
<div id="box"></div>
http://jsfiddle.net/6gbhfxrx/

Just apply it at the same time:
var $window = $(window),
$box = $('#box');
$window.on('mousemove', function(event){
var rotation = (event.pageX/$window.width()*90) - 45;
var transX= (event.pageX/$window.width()*500) - 250;
$box.css('transform', 'perspective( 600px ) rotateY(' + rotation + 'deg) translateX(' + transX + 'px)');
});
Here's a fiddle: http://jsfiddle.net/6gbhfxrx/2/

Related

How to recalculate position of marker inside div with vh html,css,js

I trying to create a map framework for some games and i have a problem with recalc position of marker. Look url to test, with wheel you can resize div with image but the dot red not come back to own position. Sorry but im new on this y trying to learn more about js and css. Thanks
$('.map-live').css('width', "928px");
$('.map-live').css('height', "928px");
$('.map-live').css('background-size', "100%");
$('.map-live').bind('mousewheel DOMMouseScroll', function(event) {
var divSize = $('.map-live').css('width');
console.log(divSize);
divSize = divSize.replace('px', '')
divSize = parseInt(divSize);
console.log("oldSize: " + divSize);
var delta_px = event.originalEvent.wheelDelta > 0 ? (divSize + (divSize * 0.15)) : (divSize - (divSize * 0.15));
console.log("NewSize: " + delta_px);
$(this).css('width', delta_px + "px");
$(this).css('height', delta_px + "px");
$(this).css('background-size', "100%");
UpdatePoints();
});
$(function() {
$("#map-live").draggable();
});
document.getElementById('map-live').addEventListener('click', printPosition)
function getPosition(e) {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
return {
x,
y
}
}
function printPosition(e) {
var position = getPosition(e);
console.log('X: ' + position.x + ' Y: ' + position.y);
var divX = parseInt($('.map-live').css('width').replace('px', ''));
var divY = parseInt($('.map-live').css('height').replace('px', ''));
var vhX = (position.x / divX) * 100;
var vhY = (position.y / divY) * 100;
console.log('vhX: ' + vhX + ' vhY: ' + vhY);
}
function UpdatePoints() {
$('.point').css('top', '2.477565353101834vh');
$('.point').css('left', '2.477565353101834vh');
$('.point').css('position', 'absolute');
}
body {
margin: 0;
overflow: hidden;
}
.map-live {
position: absolute;
left: 10px;
z-index: 9;
background-image: url(https://i.ibb.co/d2y5G1y/map.jpg);
width: 222px;
height: 222px;
transition: all 0.2s linear;
}
.point {
position: absolute;
left: 2.477565353101834vh;
top: 2.477565353101834vh;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="map-live ui-widget-content" id="map-live">
<div class="point"></div>
</div>
jsfiddle.net/f84mto52
Someone can correct me, but I believe your use of position: absolute is what is making the <div class="point"></div> stay in place.
Your UpdatePoints is setting always the same position in the div. With 'vh' you are calculating and absolute position proportional to viewport, no to parent container.
So, you are zooming the background image but the position (x, y) will be always be (x, y), positions are not zoomed. You need to recalculate which is the new position.
So you need to calculate new position.
function UpdatePoints(){
var divW = parseInt($('.map-live').css('width').replace('px',''));
var divH = parseInt($('.map-live').css('height').replace('px',''));
var topPosition = (2.477565353101834 / 928) * divH;
var leftPosition = (2.477565353101834 / 928) * divW;
$('.point').css('top', topPosition+'vh');
$('.point').css('left', leftPosition+'vh');
$('.point').css('position', 'absolute');
}
Also, instead using 'vh' I recommend to calculate the px position instead. I have added the already calculated delta_px parameter to UpdatePoints function:
<style>
.point {
position: absolute;
left: 22.99180647678502px;
top: 22.99180647678502px;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
</style>
<script>
function UpdatePoints(delta_px){
var position = (delta_px/100)*2.477565353101834;
$('.point').css('top', position+'px');
$('.point').css('left', position+'px');
$('.point').css('position', 'absolute');
}
</script>
Also, here we are calculating the top-left position of the .point element, not the position for the center. As it is a circle, it work fine, but if you use any other shape the position translation should be calculated from its center.
I recommend to do some research about how to translate elements. You can start here:
Calculating relative position of points when zoomed in and enlarged by a rectangle!
Zoom in on a point (using scale and translate)!
How do I effectively calculate zoom scale?!

Scale div inside another div with overflow scroll and center

I'm coding a very tiny small feature, but I'm having problems with the scroll. I need to do a zoom of a div scaling with css:
transform: scale(X,Y)
But my problem is that I don't have a correct left and top scroll in the parent div. I need to know how to calculate the new left and top each time the user press the button "More zoom", I could use translate css property if it is mandatory.
I can use jQuery, but I think this is just a math problem :)
One detail: I need that the image grow from the center.
Picture:
Here is the fiddle:
Fiddle example
i believe you need to mind transform-origin too:
// get element references
var foo = document.querySelector('#foo');
var bar = document.querySelector('#bar');
// fit bar into foo
// the third options argument is optional, see the README for defaults
// https://github.com/soulwire/fit.js
var zoom = 1;
var trans = 50;
var moreZoom = document.querySelector('#moreZoom');
moreZoom.onclick = function(e){
console.log(foo);
bar.style.transform = 'scale(' + (zoom + 0.1) + ',' + (zoom + 0.1) + ')';
zoom = (zoom + 0.1);
bar.style.transformOrigin = (50 / zoom) +'px ' +(50 / zoom )+'px';
}
#foo {
background: #36D7B7;
height: 200px;
width: 400px;
padding: 50px;
overflow: auto;
}
#bar {
background-image: url('http://www.space.com/images/i/000/028/001/original/wing-small-magellanic-cloud-galaxy-1920.jpg?interpolation=lanczos-none&fit=around%7C1440:900&crop=1440:900;*,*');
background-size:cover;
height: 100%;
transform:scale(1);
width: 100%;
}
<script src="https://rawgithub.com/soulwire/fit.js/master/fit.js"></script>
<button id="moreZoom">
More Zoom
</button>
<div id="foo">
<div
http://jsfiddle.net/as20h6t4/5/

Draggable square/rectangle that snaps to grid in JQuery/Javascript

I want to create a rectangle on mousedown that drags across a grid and remains there on mouseup, snapping to the gridlines and outputting the coordinates for top left and bottom right of the it's position (x1,x2,y1,y2). Any help on starting to build this would be much appreciated.
I have a 500x500 grid with squares of 10x10 (example - jsFiddle).
Grid Code:
function creategrid(size){
var standardW = Math.floor((500) / size),
standardH = Math.floor((500) / size);
var standard = document.createElement('div');
standard.className = 'grid';
standard.style.width = (standardW * size) + 'px';
standard.style.height = (standardH * size) + 'px';
for (var i = 0; i < standardH; i++) {
for (var p = 0; p < standardW; p++) {
var cell = document.createElement('div');
cell.style.height = (size - 1) + 'px';
cell.style.width = (size - 1) + 'px';
cell.style.position = 'relative'
cell.style.zIndex= '2';
standard.appendChild(cell);
}
}
document.body.appendChild(standard);
}
creategrid(10);
CSS for grid:
.grid {
margin: 0px auto auto;
border: 1px solid #000;
border-width: 0 1px 1px 0;
background-color: #CCC;
}
.grid div {
border: 1px solid #000;
border-width: 1px 0 0 1px;
float: left;
}
#tooltip {
text-align:center;
background:black;
color:white;
padding:3px 0;
width:150px;
position:fixed;
display:none;
white-space:nowrap;
z-index:3;
}
I've found some snapping code through google http://jqueryui.com/draggable/#snap-to but I am literally stuck (I'm a complete beginner at JQuery).
Alternatively if anyone has a better idea of how to do this then that would be more than welcome.
Some background if you want to suggest a different way to do it: This is for a website running off of an SQL server built in python and django. The data it outputs are jSON objects but otherwise I'm just using html, css and javacript/jQuery for the front end. -- Not sure if that info is useful or not.
EDIT added code for mouseover grid coordinates in jQuery
$(window).load(function() {
var tooltip = $('<div id="tooltip">').appendTo('body')[0];
$('.coords').
each(function() {
var pos = $(this).offset(),
top = pos.top,
left = pos.left,
width = $(this).width(),
height = $(this).height();
$(this).
mousemove(function(e) {
var x = ((e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft) - left).toFixed(0),
y = (((e.clientY + document.body.scrollTop + document.documentElement.scrollTop) - top)).toFixed(0);
$(tooltip).text( x + ', ' + y).css({
left: e.clientX + 20,
top: e.clientY + 10
}).show();
}).
mouseleave(function() {
$(tooltip).hide();
});
});
});
If i understood your question correctly, you don't really need jQueryUI for that.
You need to find mouse position snapped to the cell of the grid on mousemove and resize your selection rectangle.
function getMousePos (e) {
return {
'left': Math.floor((e.pageX - gridOffset.left) / cellSpacing) * cellSpacing,
'top': Math.floor((e.pageY - gridOffset.top) / cellSpacing) * cellSpacing
}
}
Here is an example - http://jsfiddle.net/4efTV/
I recommend you to use that plugin, jQuery UI, its really simple to use take a look at this fiddle: http://jsfiddle.net/promatik/hBQxb/
HTML
<div class="snap-box">snap box</div>
Javascript:
$( ".snap-box" ).draggable({ grid: [ 10,10 ] });
CSS:
.snap-box {
width: 50px;
height: 50px;
position: absolute;
z-index: 10;
}

jQuery .position() strangeness while using CSS3 rotate attribute

I'm getting absolutely positioned rotated elements position with jQuery .position() method, then setting position-related attributes (top, left) with jQuery .css(pos), where pos is the data returned by .position(). I think it'll leave the element in it's place, but elements position is changing.
How can I use set rotated elements position, so that it'll be placed as expected? Maybe there is a coefficient depended on angle that changes position?
I'm testing in Google Chrome v.9, Windows XP.
HTML
<div id="container">
<div id="element">
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcS0Fawya9MVMez80ZusMVtk_4-ScKCIy6J_fg84oZ37GzKaJXU74Ma0vENc"/>
</div>
</div>
CSS
#container {
position: relative;
border: 1px solid #999;
padding: 5px;
height: 300px;
width:300px;
}
#element {
position: absolute;
top:50px;
left: 60px;
width: auto;
border: 1px solid #999;
padding: 5px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
}
JS
$(document).ready(function(){
var $el = $('#element'),
// getting position
pos = $el.position();
alert(pos.left + '/' + pos.top);
// alerts 37/11
// setting css position attributes equal to pos
$el.css(pos);
// re-getting position
pos = $el.position();
alert(pos.left + '/' + pos.top);
// alerts 14/-28
});
View it http://jsfiddle.net/Antaranian/2gVL4/
// Needed to read the "real" position
$.fn.adjustedPosition = function() {
var p = $(this).position();
return {
left: p.left - this.data('dx'),
top: p.top - this.data('dy')
}
};
$(function() {
var img = $('img'),
pos;
// Calculate the delta
img.each(function() {
var po = $(this).position(), // original position
pr = $(this).addClass('rot').position(); // rotated position
$(this).data({
dx: pr.left - po.left, // delta X
dy: pr.top - po.top // delta Y
});
});
// Read the position
pos = img.adjustedPosition();
alert(pos.left + '/' + pos.top);
// Write the position
img.css(pos);
// Read the position again
pos = img.adjustedPosition();
alert(pos.left + '/' + pos.top);
});
Live demo: http://jsfiddle.net/2gVL4/4/
So what is going on here:
The CSS code that rotates the image is stored inside a special CSS class. I do this because I want to read the original position of the image (before rotating). Once I read that original position, I apply the .rot class, and then read the position again to calculate the difference (delta), which is stored inside the element's data().
Now, I can read the position via the custom method adjustedPosition (which is defined above). This method will read the position of the element and then subtract the delta values stored inside the data() of the element.
To write the position, just use the css(pos) method like normally.
Had similar problem. There is simple solution (not elegant, but working):
set current angle to 0
read X/Y position
revert angle back to its value
var temp = $(this).position();
temp.angle = getRotationDegrees( $(this) ); // remember current angle
rotateObject($(this), 0); // set angle to 0
temp.left = Math.round($(this).position().left); // proper value
temp.top = Math.round($(this).position().top); // proper value
// revert back the angle
rotateObject($(this), temp.angle);
Used functions:
function rotateObject(obj, angle) {
obj.css({ '-webkit-transform': 'rotate(' + angle + 'deg)'});
obj.css({ '-moz-transform': 'rotate(' + angle + 'deg)'});
obj.css({ '-ms-transform': 'rotate(' + angle + 'deg)'});
obj.css({ 'msTransform': 'rotate(' + angle + 'deg)'});
obj.css({ '-o-transform': 'rotate(' + angle + 'deg)'});
obj.css({ '-sand-transform': 'rotate(' + angle + 'deg)'});
obj.css({ 'transform': 'rotate(' + angle + 'deg)'});
}
function getRotationDegrees(obj) {
var matrix = obj.css("-webkit-transform") ||
obj.css("-moz-transform") ||
obj.css("-ms-transform") ||
obj.css("-o-transform") ||
obj.css("transform");
if(matrix !== 'none') {
var tr;
if (tr = matrix.match('matrix\\((.*)\\)')) {
tr = tr[1].split(',');
if(typeof tr[0] != 'undefined' && typeof tr[1] != 'undefined') {
var angle = Math.round(Math.atan2(tr[1], tr[0]) * (180/Math.PI));
}else{
var angle = 0;
}
}else if(tr = matrix.match('rotate\\((.*)deg\\)')){
var angle = parseInt(tr[1]);
}
} else { var angle = 0; }
return (angle < 0) ? angle + 360 : angle;
}

Relative mouse movement in HTML5

I'm (still) porting an old Macintosh game to HTML5 and JavaScript. The game is a Tempest clone. (Wikipedia article on Tempest) (Shameless pimp of my project)
While it's certainly possible to implement controls using the keyboard, I'm also wondering if it's possible to make relative mouse movement work in HTML5.
The typical ways that I've seen this implemented (outside of HTML5) is to repeatedly warp the mouse to the screen's center and look for deviations, or to somehow capture raw mouse movement events. As far as I know, but I could be wrong, neither of these methods are possible in HTML5.
The odds are slim, but I figure I shouldn't completely write it off without asking the clever minds of StackOverflow. :)
I'm pretty sure that the only way to get relative mouse coords in JavaScript (HTML5 specs have no changes to this) is to calculate it from the current mouse position and the previous mouse position - or using onmousemove. As you probably are aware of, this won't work when the cursor can't physically move (eg. is touching window borders)
In the off chance that I'm wrong, you could take a search for WebGL demos. Since there's bound to be a 3D shooter demo, perhaps they have a mouse based control solution you can apply.
I don't think you need HTML5 really, but if you have an element and your game board is in the center, you could do something like this:
<html>
<head>
<title>Cursor Position Radius</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<style type="text/css" media="screen">
#square {
height: 400px;
width: 400px;
background-color: #000;
margin: auto;
position: absolute;
overflow: hidden;
top: 10px;
left: 300px;
}
#log {
height: 100%;
width: 200px;
position: absolute;
top: 0;
left: 0;
background-color: #ccc;
color: #000;
font-size: small;
overflow: auto;
}
</style>
<!-- here's the real code, the JavaScript -->
<script type="text/javascript">
$(document).ready(function() {
var centerTop = a = $('#square').height() / 2;
var centerLeft = $('#square').width() / 2;
var squareTop = $('#square').offset().top;
var squareLeft = $('#square').offset().left;
// draw a center point
$('<div />').css({
width: '1px', height: '1px',
backgroundColor: '#fff',overflow:'hidden',
position:'absolute',
top: centerTop,left: centerLeft
}).attr('id', 'center').appendTo('#square');
$('#square').bind('mousemove', function(event) {
var mouseLeft = (event.pageX - squareLeft);
var mouseTop = (event.pageY - squareTop);
var correctTop = (centerTop - mouseTop);
var correctLeft = (mouseLeft - centerLeft);
var rawAngle = (180/Math.PI) * Math.atan2(correctTop,correctLeft);
var intAngle = parseInt(rawAngle, 10);
var msg = '';
msg += (mouseTop >= centerTop) ? ' lower ' : ' upper ';
msg += (mouseLeft >= centerLeft) ? ' right ' : ' left ';
msg += intAngle;
$('#log').prepend('<div>' + msg + '</div>');
});
/* create a dot along a radius for every degree
(not necessary for the mousemove) */
var sensitivity = (2 * Math.PI) / 360;
var radius = ($('#square').height() / 2) - 10;
var degrees = 0;
for (var t = 0; t<= (2 * Math.PI); t+=sensitivity) {
var x = radius * Math.cos(t) + a;
var y = radius * Math.sin(t) + a;
$('<div />').css({
width: '1px', height: '1px',
backgroundColor: '#ccc',overflow:'hidden',
position:'absolute',top: x,left: y
}).attr('id', 'cursor-' + t).appendTo('#square');
}
});
</script>
<!-- and the body -->
</head>
<body>
<div id="square"></div>
<div id="log"></div>
</body>
</html>
So the idea here is that you would do something with that angle around the center of the game board. If you know that the angle is 90 degrees you know that the game piece is at the far right.
I'm really interested in JavaScript for games, I'll check out your git project. Feel free to contact me and I'll do what I can. I wish I could promise real help, but I'm a newbie myself. There's probably more efficient ways to do the math I do in my sample, I did it mostly as an exercise for myself anyway. Best of luck!
Here's another tack at it, showing an avatar (really just a a bunch of points) that follow the mouse: http://gist.github.com/464974

Categories

Resources