I have a scrolling text div that I would like the user to be able to pause and resume with the click of a button. Here's how I'm creating the transition:
words.style.webkitTransform = "translate3d(0px, -"+(27 * (words.children.length-4))+"px, 0px)";
words.style.webkitTransition = ((27 * words.children.length)/speed)+"s all linear";
I've tried to set the transform to "none" in the pause function, but that just makes the div scroll back to where it previously was. It's the equivalent of doing translate3d(0px, 0px, 0px). Is there a method to simply pause the current animation, or would I have to somehow measure the current transition position?
Update: Here's a jsfiddle: http://jsfiddle.net/VAgXF/1/
Edit based on live example
Try this demo instead
You can use WebKitCSSMatrix in your case to get the translate3d values. I don't know all the selectors for it, but e is x and f is y, so this bit of code works since you don't change the z
var words = document.getElementById("words");
var speed = 10;
words.style.webkitTransform = "translate3d(0px, -"+(27 * (words.children.length))+"px, 0px)";
words.style.webkitTransition = ((27 * words.children.length)/speed)+"s all linear";
var paused = false;
document.getElementById("button").onclick = function() {
if(!paused) {
var translated3D = new WebKitCSSMatrix(window.getComputedStyle(words, null).webkitTransform);
words.style.webkitTransform = "translate3d(" + translated3D.e + "px, " + translated3D.f + "px, " + 0 + "px)";
paused = true;
button.innerHTML = "Start";
} else {
paused = false;
button.innerHTML = "Stop";
words.style.webkitTransform = "translate3d(0px, -"+(27 * (words.children.length))+"px, 0px)";
words.style.webkitTransition = ((27 * words.children.length)/speed)+"s all linear";
}
}
That being said I would avoid transform3d for some this simple, it over complicates the issue.
Related
I want to translateX() an element when the user pans it using Hammer.js. When the user drags the content left, I want to translate the content left. The same for right.
Current code:
var manager = new Hammer.Manager(elem);
var panner = new Hammer.Pan({ direction: Hammer.DIRECTION_HORIZONTAL, threshold: 0 });
manager.add(panner);
manager.on("panleft", function(e) {
elem.style.transform = "translateX(" + (e.distance * -1) + "px)";
});
manager.on("panright", function(e) {
elem.style.transform = "translateX(" + e.distance + "px)";
});
It works except if the user pans left then goes back right, it glitches and goes negative. How can I make it work?
I solved it by binding to the panmove event and using the e.deltaX property:
manager.on("panmove", function(e) {
elem.style.transform = "translateX(" + e.deltaX + "px)";
});
I need to detect if a user is hovering over an element, which is straightforward. However, these events don't seem to fire when the element is animating. If you check out my fiddle, just have the element animate past your mouse without moving your mouse, and you'll see that the events don't fire. It makes sense why this would happen, but I haven't been able to find a good way to get the behavior I want, which is to detect hovering even if the user doesn't move his/her mouse and the element animates under it.
Any thoughts?
Thanks!
Note: solutions without use of external libraries are optimal, but any help is still appreciated :)
HTML
<div id='moving'></div>
<ul id="message"></ul>
CSS
#moving {
width: 50px;
height: 50px;
background-color: red;
animation: move 7s linear;
}
#keyframes move {
from {transform: translateX(0px)}
to {transform: translateX(500px)}
}
JS
var counter = 0;
document.getElementById("moving").addEventListener("mouseover", function(){
counter++;
var node = document.createElement("LI");
var textnode = document.createTextNode("Entered " + counter);
node.appendChild(textnode);
document.getElementById("message").appendChild(node);
});
document.getElementById("moving").addEventListener("mouseout", function(){
var node = document.createElement("LI");
var textnode = document.createTextNode("Left " + counter);
node.appendChild(textnode);
document.getElementById("message").appendChild(node);
});
Here's a fiddle of it:
https://jsfiddle.net/w5j842Lx/
You can check if the mouse is in or out within an interval. Here is a working fiddle extending from your fiddle.
// This is the helper method I have written
var addMoveListener = function(element, onmouseover, onmouseout) {
var over = false;
var mouseX, mouseY;
var checkOver = function(ev) {
if (ev) {
mouseX = ev.clientX;
mouseY = ev.clientY;
}
if (mouseX == null || mouseY == null) return;
var rect = element.getBoundingClientRect();
var isInside = mouseX >= rect.left && mouseX < rect.right && mouseY >= rect.top && mouseY < rect.bottom;
if (over && !isInside && onmouseout) onmouseout();
if (!over && isInside && onmouseover) onmouseover();
over = isInside;
}
document.addEventListener("mousemove", checkOver);
var interval = setInterval(checkOver.bind(null, null), 100);
}
// Code below is for the sake of demonstration
var counter = 0;
var mouseovercallback = function() {
counter++;
console.log("Entered " + counter);
};
var mouseoutcallback = function() {
console.log("Left " + counter);
};
addMoveListener(document.getElementById("moving"), mouseovercallback, mouseoutcallback);
#moving {
width: 50px;
height: 50px;
background-color: red;
animation: move 7s linear;
}
#keyframes move {
from {
transform: translateX(0px)
}
to {
transform: translateX(500px)
}
}
<div id='moving'></div>
The code checks if the mouse is contained for every 100 miliseconds and also if the mouse is moved. If you want to handle cases where the element is not a rectangle or is rotated, skewed etc., you have to improve the code.
Take a look at this jsfiddle https://jsfiddle.net/3vpaoj59/
It includes a function like this
setInterval(checkMouse, 100);
that basically calls a function 10 times a second to check if the mouse's coordinates are within the animated shape. Your shape is a square and not a circle, so you would have to do some different math. This code is nice because it doesn't use a plugin, but it's probably CPU intensive and might have poor performance in some cases.
I'm trying to write a very very simple zoom plugin that should have just a button to zoom in, zoom out, and the pan function to move the image around.
For now I've writte the part to zoom in and zoom out.
My problem is that I can't find a way to center the image inside the "zoombox".
This is my code so far:
$.fn.zoom = function() {
var img = this;
img.attr("style", "-ms-transform: scale(1); -ms-transform-origin: 0% 0%; -webkit-transform: scale(1); -webkit-transform-origin: 0% 0%").wrap('<div style="width: 400px; height: 400px; overflow: hidden;" class="zoombox" data-scale="1"></div>');
$("body").on("click.zoom", ".zoomin, .zoomout", function() {
if( $(this).hasClass("zoomin") ) {
var zoomFactor = (Number(img.parent().attr("data-scale")) + 0.1).toFixed(1);
} else {
var zoomFactor = (Number(img.parent().attr("data-scale")) - 0.1).toFixed(1);
}
img.parent().attr("data-scale", zoomFactor);
console.log(zoomFactor);
img.css({"-webkit-transform": "scale(" + zoomFactor + ")", "-ms-transform":"scale(" + zoomFactor + ")"});
});
};
Fiddle:
http://jsfiddle.net/xM7r4/1/
I know the style is not the best but I'm just trying to make it works without think about the style of the code.
How can I center the image inside the box, thinking that I will have to apply a pan effect later that will change the transform-origin values?
PS: I care about compatibility only on Chrome and IE9 for now.
edit for comment
You are correct. Here I've updated to work with transform-origin. It takes the dimensions of the containing div and divides by two (to get the centerpoint of the containing div) and passes these into the image's css transform-origin property:
http://jsfiddle.net/xM7r4/23/
I've tested with different dimensioned images, and it works.
original
You'll need to move the image using margin-left and margin-top depending on if you are zooming in or out.
http://jsfiddle.net/xM7r4/21/
Since you are increasing your image by a scale of 1%, you need to move the margins accordingly, negative for zoom-in, position for zoom-out.
$("body").on("click.zoom", ".zoomin, .zoomout", function() {
var imgWidth = $(img).width();
var imgHeight = $(img).height();
var scaleWidth = Math.floor(imgWidth * 0.01);
var scaleHeight = Math.floor(imgHeight * 0.01);
if( $(this).hasClass("zoomin") ) {
var zoomFactor = (Number(img.parent().attr("data-scale")) + 0.1).toFixed(1);
moveLeft -= scaleWidth;
moveTop -= scaleHeight;
} else {
var zoomFactor = (Number(img.parent().attr("data-scale")) - 0.1).toFixed(1);
moveLeft += scaleWidth;
moveTop += scaleHeight;
}
console.log(moveTop);
console.log(moveLeft);
img.parent().attr("data-scale", zoomFactor);
console.log(zoomFactor);
img.css({"-webkit-transform": "scale(" + zoomFactor + ")", "-ms-transform":"scale(" + zoomFactor + ")", "marginLeft": moveLeft, "marginTop": moveTop});
});
Here I tried to make simple zoom in and out functions on button click.
HTML
<input type="button" value ="-" onClick="zoom(0.9)"/>
<input type="button" value ="+" onClick="zoom(1.1)"/>
<div id="thediv">
<img id="pic" src="http://cdn1.iconfinder.com/data/icons/VistaICO_Toolbar-Icons/256/Zoom-in.png"/>
</div>
SCRIPT
var zoomLevel = 100;
var maxZoomLevel = 105;
var minZoomLevel = 95;
function zoom(zm) {
var img=document.getElementById("pic");
if(zm > 1){
if(zoomLevel < maxZoomLevel){
zoomLevel++;
}else{
return;
}
}else if(zm < 1){
if(zoomLevel > minZoomLevel){
zoomLevel--;
}else{
return;
}
}
wid = img.width;
ht = img.height;
img.style.width = (wid*zm)+"px";
img.style.height = (ht*zm)+"px";
img.style.marginLeft = -(img.width/2) + "px";
img.style.marginTop = -(img.height/2) + "px";
}
But the problem is, whenever I click the zoom-in function the image moves to the top corner of the page. I tried to solve this but no solution was effective.
Here is the BIN I am working on which may be useful to find my mistake.
And also another question: Is there a way to apply mousewheel to this function?
UPDATE
The problem of zoom has been changed. But now the mousewheel also done here but the problem is we can't give the maximum value for the mousewheel.
UPDATED BIN
img.style.marginLeft = -(img.width/2) + "px"; // you have negation sign here
img.style.marginTop = -(img.height/2) + "px"; // you have negation sign here
Change it TO :
img.style.marginLeft = (img.width/2) + "px";
img.style.marginTop = (img.height/2) + "px";
JS BIN LINK
Judging by your marginLeft and marginTop calculation, I guess that you want to zoom in and out of the image while preserving the center point.
So try this:
http://jsbin.com/itekek/4
Preserved an initial width and height value, and slightly modified the zoom limit value.
Edit:
http://jsbin.com/itekek/46
Added mouse wheel support.
See this : http://jsbin.com/itekek/14/edit
You have unstripped zoom plus Mousewheel here..
Update: To get elements by class name use function below:
function findElementByClass(matchClass) {
var elems = document.getElementsByTagName('*'),i;
for (i in elems) {
if ((" " + elems[i].className + " ").indexOf(" " + matchClass + " ") > -1) {
return elems[i];
}
}
return null;
}
See sample
I have a script that I put together, which a button is clicked it rotates 45 degrees, I also would like it to toggle a paragraph open and closed. I don't have access to the CSS because the content management system interwoven wont' let me have accerss, so this is why it's all done with the javascript and it has to stay that way. The script is:
var img = document.images[0];
effects_of_yoga_info.style.setProperty("-webkit-transition", "-webkit-transform 0.3s ease-in-out");
var deg = 0;
effects_of_yoga_info.addEventListener('click', function() {
deg += 45;
effects_of_yoga_info.style.setProperty('-webkit-transform', 'rotateZ('+deg+'deg)');
and the part I'd like to incorporate into it so that they happen at the same time is:
$("#effects_of_yoga_info").click(function () {
$("p#effects_of_yoga_text").slideToggle("fast");
});
I'm sure it's very simple but I've been having a hard time with it, thanks in advance.
You mean something like this:
$(img).click(function () {
deg += 45;
$(this).css('-webkit-transform', 'rotateZ(' + deg + 'deg)');
$('#KittenText').slideToggle("fast");
});
got it working:
var img = document.images[0];
effects_of_yoga_info.style.setProperty("-webkit-transition", "-webkit-transform 0.3s ease-in-out");
var deg = 0;
effects_of_yoga_info.addEventListener('click', function() {
$("p#effects_of_yoga_text").slideToggle("fast");
deg += 45;
effects_of_yoga_info.style.setProperty('-webkit-transform', 'rotateZ('+deg+'deg)');
});