I've found a simple example about zooming a HTML image on mouse wheel. Unfortunately in my case I cannot use CSS "transform/translate" and "transformOrigin" because image's position top/left stays the same, but it has to be changed (for example, when the image becomes large enough and reaches left screen side - 'left' position must be "0", not "500px" as in my example).
My code:
<!doctype html>
<html lang="en">
<head>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
window.onload = function() {
scale = 1; // scale of the image
xLast = 0; // last x location on the screen
yLast = 0; // last y location on the screen
xImage = 0; // last x location on the image
yImage = 0; // last y location on the image
var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
if (document.attachEvent) //if IE (and Opera depending on user setting)
document.attachEvent("on"+mousewheelevt, zoomImg)
else if (document.addEventListener) //WC3 browsers
document.addEventListener(mousewheelevt, zoomImg, false)
}
function zoomImg(e){
var evt = window.event || e // equalize event object
var delta = evt.detail? evt.detail*(-120) : evt.wheelDelta // check for detail first so Opera uses that instead of wheelDelta
var imgg = document.getElementById('imgg');
// find current location on screen
var xScreen = e.pageX - imgg.offsetLeft;
var yScreen = e.pageY - imgg.offsetTop;
// 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)
{
if (scale < 5)
scale += 0.1;
}
else
{
if (scale > 1)
scale -= 0.1;
}
// 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;
imgg.style.transform = 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')';
imgg.style.transformOrigin = xImage + 'px ' + yImage + 'px';
}
</script>
</head>
<body>
<img id="imgg" src="http://www.baytrail.org/vtour/map4/access/CyteHils/Bayview_Tr_Grn_Hills.JPG" style="position:absolute; top:300px; left:500px;">
</body>
</html>
In my opinion all coefficients are known and I just need to replace these 2 lines to affect position, but I cannot find the right way:
imgg.style.transform = 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')';
imgg.style.transformOrigin = xImage + 'px ' + yImage + 'px';
How can I do that? If possible, please show an example with CSS "scale" and "zoom" functions.
Related
I have to implement the rotation of an image even on mobile devices. Currently if we place the mouse on the image simulates a 3D rotation but on mobile devices nothing happens.
I saw that I have to add:
if (window.DeviceMotion) {// Do something}
But I do not understand how to implement it.
Does anyone have any ideas?
Thank you
use strict';
$(document).on('mousemove', function (e) {
$('.light').css({
left: e.pageX - 300,
top: e.pageY - 300
});
});
var el = $('.js-tilt-container');
el.on('mousemove', function (e) {
var _$$offset = $(this).offset();
var left = _$$offset.left;
var top = _$$offset.top;
var cursPosX = e.pageX - left;
var cursPosY = e.pageY - top;
var cursFromCenterX = $(this).width() / 2 - cursPosX;
var cursFromCenterY = $(this).height() / 2 - cursPosY;
$(this).css('transform', 'perspective(500px) rotateX(' + cursFromCenterY / -40 + 'deg) rotateY(' + -(cursFromCenterX / -40) + 'deg) translateZ(-45px)');
var invertedX = Math.sign(cursFromCenterX) > 0 ? -Math.abs(cursFromCenterX) : Math.abs(cursFromCenterX);
//Parallax transform on image
$(this).find('.js-perspective-neg').css('transform', 'translateY(' + cursFromCenterY / 10 + 'px) translateX(' + -(invertedX / 10) + 'px) scale(1.15)');
$(this).removeClass('leave');
});
el.on('mouseleave', function () {
$(this).addClass('leave');
});
OK thanks. I've tried setting the "deviceorientation" code in various ways but it does not work. I used these variables. How could I integrate them in my code? thank you
if (!('ondeviceorientation' in window)) {
document.getElementById('do-unsupported').classList.remove('hidden');
} else {
document.getElementById('do-info').classList.remove('hidden');
window.addEventListener('deviceorientation', function(event) {
document.getElementById('cube').style.webkitTransform =
document.getElementById('cube').style.transform =
'rotateX(' + event.beta + 'deg) ' +
'rotateY(' + event.gamma + 'deg) ' +
'rotateZ(' + event.alpha + 'deg)';
document.getElementById('beta').innerHTML = Math.round(event.beta);
document.getElementById('gamma').innerHTML = Math.round(event.gamma);
document.getElementById('alpha').innerHTML = Math.round(event.alpha);
document.getElementById('is-absolute').innerHTML = event.absolute ? "true" : "false";
});
}
On mobile, you need to listen for the touchmove or pointermove events. See caniuse for the corresponding browser support: Touch events, Pointer events
By the way, from a user experience perspective you might want to try rotating based on device orientation (the deviceorientation event), rather than touch.
This is how I get the click position when clicking on an image to do some image transformation. But my problem is, that the image has the CSS attribute max-width: 1000px. So the code works only for images which are smaller. For larger images the position result is not the real pixel which was clicked on.
My question is, if it is possible to calculate the correct click position for the natural sized image. An alternative would be to set some data attributes with the real image size like data-width: '1200px' and data-height: '1000px'. But still I have to do some calculation.
parentPosition = getPosition(event.currentTarget),
x = event.clientX - parentPosition.x,
y = event.clientY - parentPosition.y;
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
while (element) {
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
If you know natural size and current size, i think you can just do this:
naturalClickPosX = (naturalWidth / currentWidth) * currentClickPosX;
naturalClickPosY = (naturalHeight / currentHeight) * currentClickPosY;
Have a look at this JSFiddle
HTML
<img src="http://placehold.it/1200x1000" width="1000">
JavaScript
$('img').on("click", function(e){
var $img = $(this);
var currentClickPosX = e.pageX - $img.offset().left;
var currentClickPosY = e.pageY - $img.offset().top;
var currentWidth = $img.width();
var currentHeight = $img.height();
var naturalWidth = this.naturalWidth;
var naturalHeight = this.naturalHeight;
var naturalClickPosX = ((naturalWidth / currentWidth) * currentClickPosX).toFixed(0);
var naturalClickPosY = ((naturalHeight / currentHeight) * currentClickPosY).toFixed(0);
alert("Current X: " + currentClickPosX + " Current Y: " + currentClickPosY +
"\r\nNatural X: " + naturalClickPosX + " Natural Y: " + naturalClickPosY);
});
try this , will work on all sizes
$('.img-coordinate').click(function(e){
var parentOffset = $(e.target).parent().offset();
// here the X and Y on Click
X = e.pageX - $(e.target).offset().left;
Y = e.pageY - $(e.target).offset().top;
alert(X + ' , ' + Y );
});
working fiddel : https://jsfiddle.net/h09kfsoo/
Javascript:
(function($) {
var x = 0;
var y = 0;
//cache a reference to the banner
var banner = $("#banner");
// set initial banner background position
banner.css('backgroundPosition', x + 'px' + ' ' + y + 'px');
// scroll up background position every 90 milliseconds
window.setInterval(function() {
banner.css("backgroundPosition", x + 'px' + ' ' + y + 'px');
y--;
//x--;
//if you need to scroll image horizontally -
// uncomment x and comment y
}, 90);
})(jQuery);
CSS:
div#banner {
width: 960px;
height: 200px;
margin: auto;
background: url(../images/fotogrph-skyscraping.jpg) repeat 0 0;
}
HTML:
<div id="banner"></div>
I can not get the position change to stop when the background image reaches the bottom.
http://jsfiddle.net/naeemshaikh27/u0x15oj3/
calculate the real height of the image.
subtract the height of the div shown, this is the threshold.
clear the interval when this threshold is reached
Do you mean something like this:
(function($) {
var x = 0;
var y = 0;
//cache a reference to the banner
var banner = $("#banner");
// set initial banner background position
banner.css('backgroundPosition', x + 'px' + ' ' + y + 'px');
// scroll up background position every 90 milliseconds
var timer = window.setInterval(function() {
if(y > -200){
banner.css("backgroundPosition", x + 'px' + ' ' + y + 'px');
y--;
//x--;
//if you need to scroll image horizontally -
// uncomment x and comment y
} else {
clearInterval(timer);
}
}, 90);
})(jQuery);
The following code loops through an array of images and creates them based on the position of Highcharts marker ( a text that is associated with a point on a chart ). It works great in Chrome, FF, IE on desktop but does not work in Safar both Desktop or iOS and even Chrome iOS does not show the images.
The error I am getting is : main.js:453 - TypeError: 'undefined' is not an object (evaluating 'markerOffset.left')
$.each(value, function(k, v){
var z = i;
// Store the current marker
var marker = $('text').filter(function() { if($(this).html() === k) { return $(this) } });
// Get the markers offset
var markerOffset = marker.offset();
// If in Firefox, set the marker height to 13 px
if(marker.height() == 0){
markerHeight = 13;
}
else{
markerHeight = marker.height();
}
// Get the image dimensions
// Create new image object and get the width and height
// The image has to be downloaded first
var img = new Image();
// Set the image location
img.src = v.img;
// When the image is downloaded, you can get the dimensions
img.onload = function(){
var imgHeight = img.height;
var imgDivHeight = img.height;
var imgWidth = img.width;
// If the image Width is more than 90px, resize it
if(imgWidth > 50){
imgDivHeight = imgHeight / (imgWidth / 50);
imgHeight = (imgHeight / (imgWidth / 50)) + 5;
imgWidth = 50;
}
// Create the offset values based on the image sizes
**// THIS IS LINE 453**
var imgLeft = markerOffset.left - ((imgWidth - marker[0].getComputedTextLength()) / 2);
var imgTop = markerOffset.top - (imgHeight - (markerHeight / 4));
// Create an element for each value.img and make it position absolute and set the offset of the marker
$('.charts-inner').prepend('<div class="series-data series-picture-wrapper ' + hidden + ' image-on-chart" data-id="' + k + '" data-series="' + key + '" data-position-top="' + (imgTop - $('.app-ui-top').height() - (markerHeight)) + '" data-position-left="' + (imgLeft - ($('.app-ui-menu').width() + 3)) + '" data-hidden="' + hiddenAttr + '" style="z-index: ' + (5555 + z) + '; top:' + (imgTop - $('.app-ui-top').height() - (markerHeight)) + 'px; left:' + (imgLeft - ($('.app-ui-menu').width() + 3)) + 'px; width:' + imgWidth + 'px; height:' + imgDivHeight + 'px"><img src="' + v.img + '" style="width:' + imgWidth + 'px" /><div class="app-tooltip-stock nodisplay">' + v.tooltip + '</div></div>');
}
})
Right, so the problem was not the OFFSET but that $('text') is an SVG element and in Safari you cant get its content by html().
I changed the filter part to
var marker = $('text').filter(function() {
if($(this)[0].textContent === k) { return $(this) }
});
and it is working now...
Ok, so I am trying to use jQuery to get the innerWidth() of an element #preview. I want to create a conditional that says IF x offset LEFT + #preview width is greater than page width, give it style right: z where z = #preview width + xOffset.
I apologize my code below is a mess and the syntax for .css ("right", (rightFloat + xOffset) + "px") (line 125) is off, but that's part of my problem.
<script>
$(document).ready(function(){
//append "gallery" class to all items with "popup" class
imagePreview();
$(".popup").addClass("gallery");
});
//The overlay or pop-up effect
this.imagePreview = function() { /* CONFIG */
xOffset = 40;
yOffset = 40;
// these 2 variable determine popup's distance from the cursor
// you might want to adjust to get the right result
/* END CONFIG */
$("a.preview").click(function(e) {
return false;
});
$("a.preview").hover(function(e) {
this.t = this.title;
this.title = "";
var c = (this.t != "") ? "<br/>" + this.t : "";
var rightFloat = e.pageX + ("#preview").innerWidth;
$("body").append("<p id='preview'><img src='" + this.href + "' alt='Image preview' />" + c + "</p>");
$("#preview").hide().css("top", (e.pageY - yOffset) + "px").css("left", (e.pageX + xOffset) + "px").fadeIn("2000");
while ((left + 400) > window.innerWidth) {.css("right", (rightFloat + xOffset) + "px")
}
}, function() {
this.title = this.t;
$("#preview").remove();
});
$("a.preview").mousemove(function(e) {
var top = e.pageY - yOffset;
var left = e.pageX + xOffset;
var rightFloat = e.pageX + ("#preview").innerWidth;
//flips the image if it gets too close to the right side
while ((left + 400) > window.innerWidth) {.css("right", +(rightFlaot + xOffset) + "px")
}
$("#preview").css("top", top + "px").css("left", left + "px");
});
};
</script>
Try using http://api.jquery.com/offset/
if($('#preview').offset().right<0){
var right = parseInt($(window).width()) - e.pageX + xOffset;
$("#preview").css("top", top + "px").css("right", right + "px");
}else{
var left = e.pageX + xOffset;
$("#preview").css("top", top + "px").css("left", left + "px");
}
I made these fixes because I couldn't get your code to work in jsfiddle:
var xOffset = 40;
var yOffset = 40;
$("a.preview").bind('mouseover',function(e){
var rightFloat = parseFloat(e.pageX)+$("#preview").innerWidth();
var ptop = parseFloat(e.pageY) - yOffset;
var pleft = parseFloat(e.pageX) + xOffset;
$("#preview").css({"top":ptop + "px","left":pleft + "px"});
});
There's the fixes for the top half but I have no idea what you're trying to do with the bottom part (with the while loop). Can you explain what functionality you want?