I want to create an effect that when I click on an image element, it will rotate the content inside it but not the element's width and height(My img is 400x300). I want the element dimensions stay but the image rotate. Compressing the height or the width of the image based on the position is fine with me, as long as it does not rotate the element itself.
I have tried jQueryRotate but it seems it's only rotating the element, not the image inside it.
Is there any plugin or way for me to rotate the image without rotating the element itself?
EDIT:
My code:
$('#rotate-btn').click(function (e) {
value += 90;
if (value == 90) {
var img = document.getElementById('image_canv');
var width = img.clientWidth;
var height = img.clientHeight;
$('#image_canv').height(height);
$('#image_canv').width(width); {
animateTo: value
}
}
$('#image_canv').rotate(value);
});
});
It does rotate the image, but the position of the element moves, so it's not working out.
i take image with id myimg wrap it in div and then rotate it.
http://jsfiddle.net/D5Sz8/
Be carefull all styles applied to image maybe needed to apply on div if you dont want them to rotate along the image.
jQuery.fn.rotate = function(degrees) {
$(this).css({'-webkit-transform' : 'rotate('+ degrees +'deg)',
'-moz-transform' : 'rotate('+ degrees +'deg)',
'-ms-transform' : 'rotate('+ degrees +'deg)',
'transform' : 'rotate('+ degrees +'deg)'});
};
var i= $('img'), d= document.createElement('div'), rotation=0;
d.id='myimg'; i[0].id='';
i.wrap(d);
$('#myimg').css({'display':'inline-block', 'overflow':'hidden'});
ani();
function ani (){
i.rotate(++rotation);
requestAnimationFrame(ani);
}
Ok, so I'm assuming that you have a global variable defined as value
You can use the following code to rotate by 90 degree increments if that is what you want:
var value = 0;
$('#rotate-btn').click(function (e) {
var element = $("#image_canv");
var startDegree = value;
var endDegree = value + 90;
value += 90;
$({ i:startDegree }).animate({ i: endDegree }, {
step: function(now,fx) {
element.css({transform : 'rotate('+ now + 'deg)' });
},
duration: 1000
});
});
And here is an example of it working: http://jsfiddle.net/hQHhf/4/
If you need to rotate by some other increment, than the code will need to be changed slightly to fit those needs. But basically, your value variable should always end up being the same as endDegree so that the next rotation will start at the proper place for the image.
Here's an example of how to use it if you are wanting to do varying degrees of rotation, both positive and/or negative (For this, I changed id of rotate-btn to a class instead, and gave it its own function for rotating on any degrees):
var value = 0;
$('.rotate-btn').click(function (e) {
doRotate($(this).val(), 1000);
});
function doRotate(degrees, delay) {
var element = $("#image_canv");
var startDegree = value;
var endDegree = value + parseInt(degrees);
value = value + parseInt(degrees);
$({ i:startDegree }).animate({ i: endDegree }, {
step: function(now,fx) {
element.css({transform : 'rotate('+ now + 'deg)' });
},
duration: delay
});
}
And here is an example: http://jsfiddle.net/hQHhf/6/
Also made some minor edits to the HTML as well, like using <button> instead of <input> to send a proper value to the doRotate function and some other minor edits.
Hope this helps you get the jist of it and apply it for your needs. Also, because you are setting a width of 400, and a height of 300 on the images, while chrome does not seem effected by this, but some other browsers like firefox will be. For example, as the image rotates, the size rotates with it, this is because you don't have an equal size on both width and height of your image, so it won't look as tho its rotating naturally in all browsers. If you give both, width and height, the same size you won't have this problem.
You can use this javascript code so you can rotate your image easily. But you have only to change the image destination.
var looper;
var degrees = 0;
function rotateAnimation(el,speed){
var elem = document.getElementById(el);
if(navigator.userAgent.match("Chrome")){
elem.style.WebkitTransform = "rotate("+degrees+"deg)";
} else if(navigator.userAgent.match("Firefox")){
elem.style.MozTransform = "rotate("+degrees+"deg)";
} else if(navigator.userAgent.match("MSIE")){
elem.style.msTransform = "rotate("+degrees+"deg)";
} else if(navigator.userAgent.match("Opera")){
elem.style.OTransform = "rotate("+degrees+"deg)";
} else {
elem.style.transform = "rotate("+degrees+"deg)";
}
looper = setTimeout('rotateAnimation(\''+el+'\','+speed+')',speed);
degrees++;
if(degrees > 359){
degrees = 1;
}
document.getElementById("status").innerHTML = "rotate("+degrees+"deg)";
}
And now use the HTML code for the image:
<img id="exe" style='position:absolute;left:450px;height:300px;' src="images/example.png" alt="exe">
And it's about to finish just add another script tag:
rotateAnimation("exe",30);
This function above will move the image 30deg you can change it to 40,50... and the "exe" is the id of the image.
Related
I'm using the svg-pan-zoom code https://github.com/ariutta/svg-pan-zoom to make an svg map of some kind, now it is time to add a feature to pan & zoom to an art component of the svg on a click event. However, I'm not sure how to use the panBy() function to get to a desired svg art item: I tried to use the getBBox() on the group I'm looking to pan to and use that with the panZoomInstance.getPan() and getSizes() information, but my experiments are not working out.
I'd like to accomplish the same king of animation as their example (http://ariutta.github.io/svg-pan-zoom/demo/simple-animation.html) but center the viewport to the item.
Against all odds I was able to figure out this part of it!
function customPanByZoomAtEnd(amount, endZoomLevel, animationTime){ // {x: 1, y: 2}
if(typeof animationTime == "undefined"){
animationTime = 300; // ms
}
var animationStepTime = 15 // one frame per 30 ms
, animationSteps = animationTime / animationStepTime
, animationStep = 0
, intervalID = null
, stepX = amount.x / animationSteps
, stepY = amount.y / animationSteps;
intervalID = setInterval(function(){
if (animationStep++ < animationSteps) {
panZoomInstance.panBy({x: stepX, y: stepY})
} else {
// Cancel interval
if(typeof endZoomLevel != "undefined"){
var viewPort = $(".svg-pan-zoom_viewport")[0];
viewPort.style.transition = "all " + animationTime / 1000 + "s ease";
panZoomInstance.zoom(endZoomLevel);
setTimeout(function(){
viewPort.style.transition = "none";
$("svg")[0].style.pointerEvents = "all"; // re-enable the pointer events after auto-panning/zooming.
panZoomInstance.enablePan();
panZoomInstance.enableZoom();
panZoomInstance.enableControlIcons();
panZoomInstance.enableDblClickZoom();
panZoomInstance.enableMouseWheelZoom();
}, animationTime + 50);
}
clearInterval(intervalID)
}
}, animationStepTime)
}
function panToElem(targetElem) {
var initialSizes = panZoomInstance.getSizes();
var initialLoc = panZoomInstance.getPan();
var initialBounds = targetElem.getBoundingClientRect();
var initialZoom = panZoomInstance.getZoom();
var initialCX = initialBounds.x + (initialBounds.width / 2);
var initialCY = initialBounds.y + (initialBounds.height / 2);
var dX = (initialSizes.width / 2) - initialCX;
var dY = (initialSizes.height / 2) - initialCY;
customPanByZoomAtEnd({x: dX, y: dY}, 2, 700);
}
The key was in calculating the difference between the center of the viewport width & height from panZoomInstance.getSizes() and the center of the target element's client bounding rectangle.
Now the issue is trying to make an animated zoom. For now I've made it do a zoom to a specified location with a command at the end of the panning animation and set some css to make the zoom a smooth transition. The css gets removed after some time interval so normal zooming and panning isn't affected. In my attempts to make the zoom a step animation it always appeared to zoom past the intended max point.
I've just built my first RevealJS presentation and while all seemed to work at glance I ran into an game breaking issue with a HighChart that is caused by the way RevealJS scales/moves and elements and SVG related (at least I think so).
There's a similar issue report here, at least it seems related, though I've been unable to resolve my issue as the suggested code is not a drop-in and I'm my JS skills are lacking at best ->
Mouse position in SVG and RevealJS
I was hoping someone could help me pinpoint a potential solution, maybe that of the other stack easily can be adapted (I do need the scaling function, I know I could initialize RevealJS with a percentage option, but that will effectively break scaling on any smaller devices).
This is the code part that seems related, in my case the second else if( scale > 1 && features.zoom ) { ... } is triggered and the scaling creates a bad offset depending on resolution.
var size = getComputedSlideSize();
// Layout the contents of the slides
layoutSlideContents( config.width, config.height );
dom.slides.style.width = size.width + 'px';
dom.slides.style.height = size.height + 'px';
// Determine scale of content to fit within available space
scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height );
console.log("Size:"+size.presentationWidth);
console.log("Size:"+size.width);
console.log("1:"+scale);
// Respect max/min scale settings
scale = Math.max( scale, config.minScale );
console.log("2:"+scale);
scale = Math.min( scale, config.maxScale );
console.log("3:"+scale);
// Don't apply any scaling styles if scale is 1
if( scale === 1 ) {
dom.slides.style.zoom = '';
dom.slides.style.left = '';
dom.slides.style.top = '';
dom.slides.style.bottom = '';
dom.slides.style.right = '';
transformSlides( { layout: '' } );
}
else {
// Prefer zoom for scaling up so that content remains crisp.
// Don't use zoom to scale down since that can lead to shifts
// in text layout/line breaks.
if( scale > 1 && features.zoom ) {
dom.slides.style.zoom = scale;
dom.slides.style.left = '';
dom.slides.style.top = '';
dom.slides.style.bottom = '';
dom.slides.style.right = '';
transformSlides( { layout: '' } );
}
// Apply scale transform as a fallback
else {
dom.slides.style.zoom = '';
dom.slides.style.left = '50%';
dom.slides.style.top = '50%';
dom.slides.style.bottom = 'auto';
dom.slides.style.right = 'auto';
transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
}
}
I've created a codepen to illustrate the issue, resize it from small to max size and check the mouse tooltip, there will be a small to massive offset between where the mouse is and what tooltip point shows except when the scale is 1:1.
https://codepen.io/anon/pen/MVLazG
Any and all help would be welcome. If there's a way to process the graph in a way that would retain a better mouse position I'd be grateful both suggestions and code (banged my head for a couple of hours on different approaches without luck).
It is caused by setting transform's scale on the wrapping div. You can read more about on Highcharts github here.
There is a workaround for this which seems to work in your example:
Highcharts.wrap(Highcharts.Pointer.prototype, 'normalize', function (proceed, event, chartPosition) {
var e = proceed.call(this, event, chartPosition);
var element = this.chart.container;
if (element && element.offsetWidth && element.offsetHeight) {
var scaleX = element.getBoundingClientRect().width / element.offsetWidth;
var scaleY = element.getBoundingClientRect().height / element.offsetHeight;
if (scaleX !== 1) {
e.chartX = parseInt(e.chartX / scaleX, 10);
}
if (scaleY !== 1) {
e.chartY = parseInt(e.chartY / scaleY, 10);
}
}
return e;
});
live example: https://codepen.io/anon/pen/GxzPKq
Hi currently i write code to text rotate using jquery ,
var rotation = 0;
jQuery.fn.rotate = function(degrees) {
$(this).css({'transform' : 'rotate('+ degrees +'deg)'});
};
$('.resizeButton').click(function() {
rotation += 5;
$('.new-div').rotate(rotation);
});
Please see this . https://jsfiddle.net/felixtm/2mpjkxad/3/
But here text rotation happening on mouse click to that resize button . Instead of that mouse click user able to rotate the text as usual rotation event. ie. use click the button rotate it as he wish . Here he need to click it many times for one major rotation . How it can be done ?
UPDATE : I see this question that is exactly what i wanted .But i
don't know how to implement it .
jQuery: Detecting pressed mouse button during mousemove event
Try something like this:
var rotation = 0;
jQuery.fn.rotate = function(degrees) {
$(this).css({'transform' : 'rotate('+ degrees +'deg)'});
};
$('.resizeButton').on("mousedown", function(e) {
var startX = e.pageX;
$(document).mousemove(function(e){
rotation = startX - e.pageX;
$('.new-div').rotate(rotation);
});
});
$('.resizeButton').on("mouseup", function(){
$(document).unbind( "mousemove" );
});
https://jsfiddle.net/p9wtmfhp/
I'm trying to rotate an image 180 degrees counterclockwise every time the user click's the image's parent element. I'm using JQueryRotate v2.3.
My code:
$('.material').click(function () {
var thisPic = $(this).find('.fanpic');
thisPic.rotate({ animateTo: -180 });;
});
This works at first, but the image starts spinning clockwise with the second click onward. How can I fix this so the image always spins counterclockwise?
Try keeping the rotate value at somewhere for example in the parent element:
$('.material').click(function () {
if(!this.animateTo) this.animateTo = 0;
this.animateTo = this.animateTo + -180;
var thisPic = $(this).find('.fanpic');
thisPic.rotate({ animateTo: this.animateTo });;
});
Try this jsfiddle
Hope this helps,
Yo can keep a variable with the angle.
var angle = -180;
$('.material').click(function () {
var thisPic = $(this).find('.fanpic');
thisPic.rotate({ animateTo: angle });
angle -= 180;
});
Ok so i have this triangle div and when i click it, it only rotates 180deg. Ok so far so good but if i click it again it stays the same here is my code.
$('.Triangle').click(function()
{
var Location = $('.Triangle').offset().left;
$('#Account').css({"left" : Location});
$('#Account').slideToggle('fast');
$('.Triangle').css({"transform" : "rotate(180deg)"});
});
Transforms don't work that way (i.e. you can't apply it twice). You have to keep track of state:
$(".Triangle").on('click', function () {
if ($(this).data('flipped') {
$(this).data('flipped', false).css('transform', 'rotate(0deg)');
}
The 'transform' style sets the rotation of the element from it's original position. When you click it the first time, it rotates the element from 0deg to 180deg. When you click it again, it changes the rotation from 180deg to 180deg.
You need to keep a counter for the number of clicks and multiply that by your rate of rotation. Something like this should do the trick:
var count = 1;
$('.Triangle').click(function() {
var Location = $('.Triangle').offset().left;
$('#Account').css({"left" : Location});
$('#Account').slideToggle('fast');
$('.Triangle').css({"transform" : "rotate(" + (180 * count++) + "deg)"});
});`
var i = 0;
$('.Triangle').click(function() {
i++;
var Location = $('.Triangle').offset().left;
$('#Account').css({"left" : Location});
$('#Account').slideToggle('fast');
$('.Triangle').css({"transform" : "rotate(" + (i % 2 ? 0 : 180 + "deg)"});
});