How to make Coin Slider responsive? - javascript

After being created, the slider seems not to have a way to be resized, which is really bad for a responsive layout.
Is there a way to actually resize the Coin Slider plugin according to Twitter Bootstrap 3's media queries?
You might consider Coin Slider's demo as a fiddle.

Indeed, there is no way to resize it with the current plugin version. So, I wrote a script to resize the Coin Slider (you can test it on Coin Slider's demo site):
var resizeCoinSliderTo = function(coinSlider, toWidth, toHeight) {
var csColumns = 7;
var csRows = 5;
var imgWidth = toWidth;
var imgHeight = toHeight;
var cellWidth = imgWidth/csColumns;
var cellHeight = imgHeight/csRows;
var coinSliderId = coinSlider.attr("id");
coinSlider.css({
'width': imgWidth,
'height': imgHeight
});
$('.cs-'+coinSliderId).css({
'width': (cellWidth + 'px'),
'height': (cellHeight + 'px'),
'background-size': (imgWidth + 'px ' + imgHeight + 'px')
}).each(function() {
var cellOffsets = $(this).attr("id").replace("cs-"+coinSliderId,"");
var hOffSet = cellHeight * (Math.floor(parseInt(cellOffsets[0])-1) % csRows);
var wOffSet = cellWidth * (parseInt(cellOffsets[1])-1);
$(this).css({
"left": (wOffSet + 'px'),
"top": (hOffSet + 'px'),
"background-position": ((-wOffSet) + 'px ' + (-hOffSet) + 'px')
});
});
$('#cs-navigation-'+coinSliderId).children("a").css("top", (((imgHeight/2)-15)+'px'));
};
So, we just need to call the created resizeCoinSliderTo after each media queries breakpoints, handling the resize, without losing its ratio, to fit the screen properly:
<span id="mq-detector">
<span class="visible-xs"></span>
<span class="visible-sm"></span>
<span class="visible-md"></span>
<span class="visible-lg"></span>
</span>
#mq-detector {
visibility: hidden;
}
var coinSlider = $("#coin-slider");
var baseWidthDisplay = undefined;
var baseHeightDisplay = undefined;
var currentRatio = undefined;
var mqRatios = [0.75, 0.95, 0.8, 1];
var mqDetector = $("#mq-detector");
var mqSelectors = [
mqDetector.find(".visible-xs"),
mqDetector.find(".visible-sm"),
mqDetector.find(".visible-md"),
mqDetector.find(".visible-lg")
];
var checkCoinSliderForResize = function() {
for (var i = 0; i <= mqSelectors.length; i++) {
if (mqSelectors[i].is(":visible")) {
if (currentRatio == undefined) {
baseWidthDisplay = parseInt(coinSlider.css("width"));
baseHeightDisplay = parseInt(coinSlider.css("height"));
}
if (i == 0) {
var specialWidth = Math.floor(parseInt($("body").css("width"))*0.75);
if (specialWidth < 300){
specialWidth = 300;
}
var specialHeight = Math.floor(baseHeightDisplay * specialWidth / baseWidthDisplay);
resizeCoinSliderTo(coinSlider, specialWidth, specialHeight);
}
if (currentRatio != mqRatios[i]) {
currentRatio = mqRatios[i];
if (i > 0) {
resizeCoinSliderTo(coinSlider, baseWidthDisplay*currentRatio, baseHeightDisplay*currentRatio);
}
}
break;
}
}
};
$(window).on('resize', checkCoinSliderForResize);
checkCoinSliderForResize();
Make sure to place all JavaScript code after the DOM is ready, and after the coinslider was created.

Related

Fabricjs - How to detect canvas on mouse move?

In my fabricjs application, I had created dynamic canvases(variable's also dynamic). Here, I need to detect particular canvas while mouse move on canvas.
Sample code,
var i = 0, canvasArray = [];
$(this).find('canvas').each(function() {
i++;
var DynamicCanvas = 'canvas_'+i;
canvasArray[DynamicCanvas] = new fabric.Canvas('canvas_'+i,{
width : '200',
height : '200'
});
});
after this, I have 4 different canvases. Last added canvas has been activated. But i need to add object on any canvas.
So that i have to activate canvas using mouse move event. How can i achieve it.? Please help me on this.
Mullainathan,
Here some quick solution using jQuery:
var canvasStr = '';
var canvasArray = [];
var fabricCanvasArray = [];
var htmlStr = '';
var canvas = null;
//generate canavases
for (var i = 0; i < 4; i++){
canvasArray.push('c' + i);
htmlStr += '<canvas id="c' + i + '" width="200" height="200"></canvas>'
}
//append canvasses to the body
$('body').append(htmlStr);
//to the fabricjs parent div elements assign id's and generate string for jQuery with div id's
for (var i in canvasArray){
fabricCanvasArray[i] = new fabric.Canvas(canvasArray[i], {
isDrawingMode: true
});
$('#' + canvasArray[i]).parent().attr('id', ('div' + canvasArray[i]));
canvasStr += '#div' + canvasArray[i];
if (i < canvasArray.length - 1){
canvasStr += ',';
}
}
//jQuery event for mouse over each div element of the fabric canvas
$(canvasStr).mouseover(function(){
for (var i in fabricCanvasArray){
if (fabricCanvasArray[i].lowerCanvasEl.id == $(this).children(':first').attr('id')){
canvas = fabricCanvasArray[i];
canvas.freeDrawingBrush.width = 10;
var r = 255 - i*50;
var g = i * 50;
var b = 200 - i * 40;
canvas.freeDrawingBrush.color = 'rgb(' + r + ',' + g + ',' + b + ')';
canvas.on('mouse:up', function() {
//do your stuff
// canvas.renderAll();
});
break;
}
}
});
Also, you can run fiddle

rotate on mouse hover

I have this function but there are two issues I can't solve, first one is that the mouse action is set on all the screen and I want it to be when hover over the dive "ehab" only, not when I move mouse over screen,
the other issue is that when I have more than one div , the function works only on the first one ...
kindly advise me
/*
By : Ofelquis
Twitter: #felquis
Blog : tutsmais.com.br
Simples implementação ;)
*/
!(function ($doc, $win) {
var screenWidth = $win.screen.width / 2,
screenHeight = $win.screen.height / 2,
$ehab = $doc.querySelectorAll('#ehab')[0],
validPropertyPrefix = '',
otherProperty = 'perspective(600px)';
if(typeof $ehab.style.webkitTransform == 'string') {
validPropertyPrefix = 'webkitTransform';
} else {
if (typeof $ehab.style.MozTransform == 'string') {
validPropertyPrefix = 'MozTransform';
}
}
$doc.addEventListener('mousemove', function (e) {
// vars
var centroX = e.clientX - screenWidth,
centroY = screenHeight - (e.clientY + 13),
degX = centroX * 0.1,
degY = centroY * 0.1
// Seta o rotate do elemento
$ehab.style[validPropertyPrefix] = otherProperty + 'rotateY('+ degX +'deg) rotateX('+ degY +'deg)';
});
})(document, window);
The first problem, (I want it to be when hover the div "#ehab"), you need the attach the mousemove event to your div:
$ehab.addEventListener('mousemove', function (e) {
//You code here.
});
The second problem, (when I have more than one div , the function works only on the first one), you can't have duplicated IDs on your DOM tree, change the selector to a class, for example, .ehab then you have to loop through the matched elements, please try this code:
/*
By : Ofelquis
Twitter: #felquis
Blog : tutsmais.com.br
Simples implementação ;)
*/
!(function($doc, $win) {
var $ehabDIVs = $doc.querySelectorAll('.ehab'),
otherProperty = 'perspective(600px)';
for (var i = 0; i < $ehabDIVs.length; ++i) {
var $ehab = $ehabDIVs[i];
$ehab.addEventListener('mousemove', function(e) {
// vars
var centroX = (e.pageX - this.offsetLeft) - this.offsetWidth/2,
centroY = this.offsetHeight/2 - (e.pageY-this.offsetTop),
degX = centroX * 0.1,
degY = centroY * 0.1
if(this._leave) clearInterval(this._leave);
// Seta o rotate do elemento
this.style.transform = otherProperty + 'rotateY(' + degX + 'deg) rotateX(' + degY + 'deg)';
});
$ehab.addEventListener('mouseleave', function(e) {
var self = this;
this._leave = setTimeout(function() {
self.style.transform = 'rotateY(0deg) rotateX(0deg)';
}, 250);
});
}
})(document, window);
.ehab {
width:300px;
height:300px;
background-color:red;
margin:15px;
float:left;
transition: transform 0.15s ease;
}
<div class="ehab">First Div</div><div class="ehab">Second Div</div>
Good Luck Ismaiel.

HTML5 & javascript - drawImage seems to trigger after animation completed

I'm trying to create the following animation:
- when the page loads, I load the 2 components of my logo and draw them onto the canvas
- after clicking the animate button, both images should smoothly move up to the top of the page and shrink
However, it seems that the drawImage() only takes place somewhere after the entire animation has been completed even though I can see it being executed at the right time in the console. Commenting out the clearRect function also shows me that every frame is actually drawn onto the screen, but sadly they all appear together after the animation should be completed.
I'm pretty new to canvases and relevant tutorials on such animations are scarce and don't get me much further.
Here's the relevant script:
<script type="text/javascript">
var logoCanvas;
var logoContext;
var direction = 1;
var logoAnimationDuration = 2000; //millisec
var frameSpeed = 30/1000; //frames per second
var logoImageRatio = 0;
var logoTextRatio = 0;
var initialLogoImageHeight = 0;
var initialLogoTextHeight = 0;
var initialLogoImageTop = 0;
var initialLogoImageLeft = 0;
var initialLogoTextTop = 0;
var initialLogoTextLeft = 0;
var newLogoImageLeft = 0;
var logoImageWidth = 0;
var logoImageHeight = 0;
var logoTextWidth = 0;
var logoTextHeight = 0;
var logoImageTop = 0;
var logoImageLeft = 0;
var logoTextTop = 0;
var logoTextLeft = 0;
var logoImageLoaded = false;
var logoTextLoaded = false;
var logoImage = new Image();
var logoText = new Image();
function AnimateFrontPageCanvas() {
if(logoCanvas.height <= $('#Page_0').height()) {
logoCanvas.height = $('#Page_0').height();
return;
}
if(logoImageHeight <= $('#Page_0').height() - 4) {
return;
}
if(logoImageTop <= 2) {
return;
}
//logoCanvas.height = parseFloat(logoCanvas.height) - (parseFloat(window.innerHeight) - parseFloat($('#Page_0').height())) * 1/frameSpeed * 1/logoAnimationDuration;
logoContext.clearRect(0, 0, logoCanvas.width, logoCanvas.height);
AnimateLogo();
setTimeout(AnimateFrontPageCanvas(), 1/frameSpeed);
}
function AnimateLogo() {
AnimateLogoImage();
AnimateLogoText();
}
function AnimateLogoImage() {
logoImageHeight = logoImageHeight - (initialLogoImageHeight - $('#Page_0').height() + 4) * (1/frameSpeed) * (1/logoAnimationDuration);
logoImageWidth = logoImageHeight*logoImageRatio;
logoImageTop = logoImageTop - (initialLogoImageTop - 2)*(1/frameSpeed) * (1/logoAnimationDuration);
logoImageLeft = logoImageLeft - (initialLogoImageLeft - newLogoImageLeft) * (1/frameSpeed) * (1/logoAnimationDuration);
logoContext.drawImage(logoImage, logoImageLeft, logoImageTop, logoImageWidth, logoImageHeight);
var time = new Date();
time = time.getTime();
console.log('logoimage drawn: ' + time);
}
function AnimateLogoText() {
logoTextHeight = logoTextHeight - (initialLogoTextHeight - $('#Page_0').height() + 4) * (1/frameSpeed) * (1/logoAnimationDuration);
logoTextWidth = logoTextHeight*logoTextRatio;
logoTextTop = logoTextTop - (initialLogoTextTop - 2) * (1/frameSpeed)*(1/logoAnimationDuration);
logoTextLeft = logoTextLeft - (initialLogoTextLeft - newLogoTextLeft)*(1/frameSpeed)*(1/logoAnimationDuration);
logoContext.drawImage(logoText, logoTextLeft, logoTextTop, logoTextWidth, logoTextHeight);
var time = new Date();
time = time.getTime();
console.log('logotext drawn: ' + time);
}
function InitiateFrontPageCanvas() {
logoImage.onload = function() {
logoImageLoaded = true;
AfterImagesLoadedActions();
}
logoImage.src = '/site_mats/images/logo_image.png';
logoText.onload = function() {
logoTextLoaded = true;
AfterImagesLoadedActions();
}
logoText.src = '/site_mats/images/logo_text.png';
}
function AfterImagesLoadedActions() {
if(logoImageLoaded && logoTextLoaded) {
logoImageRatio = logoImage.width/logoImage.height;
logoTextRatio = logoText.width/logoText.height;
if(logoImage.width > 0.8*logoCanvas.width) {
logoImage.width = 0.8*logoCanvas.width;
logoImage.height = logoImage.width/logoImageRatio;
}
if(logoText.width > 0.8*logoCanvas.width) {
logoText.width = 0.8*logoCanvas.width;
logoText.height = logoText.width/logoTextRatio;
}
if(parseFloat(logoImage.height) + parseFloat(logoText.height) > 0.66*logoCanvas.height) {
var x = (0.66*logoCanvas.height)/(parseFloat(logoImage.height) + parseFloat(logoText.height));
logoImage.height = x*logoImage.height;
logoImage.width = logoImage.height*logoImageRatio;
logoText.height = x*logoText.height;
logoText.width = logoText.height*logoTextRatio;
}
initialLogoImageHeight = logoImage.height;
initialLogoTextHeight = logoText.height;
logoImageHeight = logoImage.height;
logoImageWidth = logoImage.width;
logoTextHeight = logoText.height;
logoTextWidth = logoText.width;
initialLogoImageTop = parseFloat((logoCanvas.height-(parseFloat(logoImageHeight)+parseFloat(logoTextHeight)))/2);
initialLogoImageLeft = parseFloat((logoCanvas.width-logoImageWidth)/2);
initialLogoTextTop = parseFloat(((logoCanvas.height-(parseFloat(logoImageHeight)+parseFloat(logoTextHeight)))/2)+parseFloat(logoImageHeight));
initialLogoTextLeft = parseFloat((logoCanvas.width-logoImageWidth)/2);
logoImageTop = initialLogoImageTop;
logoImageLeft = initialLogoImageLeft;
logoTextTop = initialLogoTextTop;
logoTextLeft = initialLogoTextLeft;
newLogoImageLeft = parseFloat(2);
newLogoTextLeft = parseFloat((logoCanvas.width-$('#Page_0').height()*logoTextRatio)/2);;
logoContext.drawImage(logoText, logoTextLeft, logoTextTop, logoTextWidth, logoTextHeight);
logoContext.drawImage(logoImage, logoImageLeft, logoImageTop, logoImageWidth, logoImageHeight);
//remove onload from image objects
logoImage.onload = null;
logoText.onload = null;
}
}
function SetFrontPageCanvas() {
logoCanvas = document.getElementById('LogoCanvas');
logoContext = logoCanvas.getContext('2d');
logoCanvas.width = window.innerWidth;
logoCanvas.height = window.innerHeight;
logoContext.clearRect(0, 0, logoCanvas.width, logoCanvas.height);
InitiateFrontPageCanvas();
}
window.onload = function() {
SetFrontPageCanvas();
};
$(document).ready(function() {
windowWidth = $(window).width();
windowHeight = $(window).height();
});
$(window).resize(function() {
//alert($(window).width() + ' - ' + $(window).height());
logoImageLoaded = false;
logoTextLoaded = false;
SetFrontPageCanvas();
windowWidth = $(window).width();
windowHeight = $(window).height();
});
</script>
And here's the relevant html:
<canvas id="LogoCanvas" style="position:absolute;top:0;left:0;z-index:1;"></canvas>
<div id="Page_0" style="position:absolute;top:0;left:0;z-index:5;width:100%;height:90px;">
<div align="center" style="position:fixed;bottom:5px;z-index:100;width:100%;">
<input type="button" onClick="AnimateFrontPageCanvas()" value="Animate">
</div>
If desired, the code can also be seen in action here: http://villa-gloria-katouna.com/site_mats/animation.php

Where in the grid the tile belongs

If I created a virtual grid 32x32 as a <div> example:
I want to fill one of the tile with a black box on click I have so far this:
var _proto = {
id:0,
x:0,
y:0
}
var objects = [];
$(".test").on("mousedown", function(e) {
var offset = $(this).offset();
var prex2 = 0, prey2 = 0;
prex2 = _proto.x = e.pageX-offset.left;
prey2 = _proto.y = e.pageY-offset.top;
_proto.id = (_objects.length)?_objects[_objects.length-1].id+1:0;
// Add to grid (not sure how to get proper cordinates)
$("<div style='display:absolute;width:32px;height:32px;background:black'></div>")
.css("top","")
.css("left","")
.appendTo("#maindiv");
});
I have the coordinates as prex2, and prey2 where the user clicked, but how do I know where to put it in the grid? I'm sure there a simple math equation but I can't figure it out.
Here's a snippet from a map editor that I was working on a few months back. It might help you grapple with your own code.
mapBlanket.addEventListener("mousedown", function(e) {
var sideWidth = document.getElementById("mapSide").offsetWidth;
var headHeight = document.getElementById("system").offsetHeight + 32;
var clickX = e.pageX - mapBlanket.offsetLeft - sideWidth + mapBlanket.parentNode.scrollLeft;
var clickY = e.pageY - mapBlanket.offsetTop - headHeight + mapBlanket.parentNode.scrollTop;
var tileX = clickX - (clickX % map.grid);
var tileY = clickY - (clickY % map.grid);
if (paintOn == 5) {
eventThis(tileX, tileY);
} else if (paintOn < 5) {
paintThis(tileX, tileY);
}
...
}
For reference, the map.grid was 32, same as yours. I just had a good bit defined in an object at the top of the file.

Bind events to all elements in class instead of just to one id

I developed this interaction / script that scales whatever element is passed to it and if that element is pinched in on, it scales down / less.
This is how the script is initialised ( passing two arguments the container and the item to be scaled / transformed:
$(function(){
var zoom = new collapse('#zoom','#zoom :first');
var zoom2 = new collapse('#zoom2','#zoom2 :first');
var zoom3 = new collapse('#zoom3','#zoom3 :first');
});
It works fine as above on single IDs, but I need it to work on a class.
I tried this:
$(function(){
var zoom = new collapse('#zoom','.polaroid');
});
But that causes the whole script not to work because all the elements in that class are being passed instead of one as with an id.
This would only select the first item in the class so it won't work:
$(function(){
var zoom = new collapse('#zoom','.polaroid :first');
});
How can I change my script so that it is applied to all members of the .polaroid class in the #main container?
Here is my script:
function collapse(container, element){
container = $(container).hammer({
prevent_default: true,
scale_threshold: 0
});
element = $(element);
var displayWidth = container.width();
var displayHeight = container.height();
var MIN_ZOOM = 0;
var MAX_ZOOM = 1;
var scaleFactor = 1;
var previousScaleFactor = 1;
var startX = 0;
var startY = 0;
var translateX = 0;
var translateY = 0;
var previousTranslateX = 0;
var previousTranslateY = 0;
var time = 1;
var tch1 = 0,
tch2 = 0,
tcX = 0,
tcY = 0,
toX = 0,
toY = 0,
cssOrigin = "";
container.bind("transformstart", function(event){
e = event;
tch1 = [e.touches[0].x, e.touches[0].y],
tch2 = [e.touches[1].x, e.touches[1].y];
tcX = (tch1[0]+tch2[0])/2,
tcY = (tch1[1]+tch2[1])/2;
toX = tcX;
toY = tcY;
var left = $(element).offset().left;
var top = $(element).offset().top;
cssOrigin = (-(left) + toX)/scaleFactor +"px "+ (-(top) + toY)/scaleFactor +"px";
});
container.bind("transform", function(event){
scaleFactor = previousScaleFactor * event.scale;
scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));
transform(event);
});
container.bind("transformend", function(event){
previousScaleFactor = scaleFactor;
if(scaleFactor > 0.42){
$(element).css('-webkit-transform', 'scaleY(1.0)').css('transform', 'scaleY(1.0)');
}
});
function transform(e){
var cssScale = "scaleY("+ scaleFactor +")";
element.css({
webkitTransform: cssScale,
webkitTransformOrigin: cssOrigin,
transform: cssScale,
transformOrigin: cssOrigin,
});
if(scaleFactor <= 0.42){
$(element).animate({height:0}, function(){
$(this).remove();
});
}
}
}
Wrap it as a jquery plugin:
$.fn.collapse = function(filter) {
return this.each(function(){
collapse(this,filter);
});
}
$("#zoom,#zoom1,#zoom2").collapse(".polaroid");
or if each of the zoom elements had a common class,
$(".zoomel").collapse(".polaroid");
You have to run collapse for each element.
element = $(element);
element.each(function(){
//each element would be this here
var $this= $(this);
//do whatever you want with $this
})

Categories

Resources