Scrollama, changing charts - javascript

I'm trying to make a simple static webpage to accompany my research paper. While looking for solutions I stumbled upon scrollama.js. On the surface it does everything I want, but I just can't figure out how to add multiple charts (a single chart for example works since I replace the contents of the chart div). So how would one insert several simple d3 graphs into the scrollama.js demo? I'm guessing it's a javascript solution and my javascript knowledge is severely limited.
I would be grateful for any suggestions.
Also a jsfiddle of the demo I found while searching for any related scrollama materials:
https://codepen.io/bclinkinbeard/pen/OOKXjz
html
<section id='intro'>
<p class='intro__overline'>
<a href='https://github.com/russellgoldenberg/scrollama'>scrollama.js</a>
</p>
<h1 class='intro__hed'>Demo: Sticky Graphic</h1>
<p class='intro__dek'>
Start scrolling to see how it works.
</p>
</section>
<section id='scroll'>
<div class='scroll__graphic'>
<div class='chart'>
<p>0</p>
</div>
</div>
<div class='scroll__text'>
<div class='step' data-step='1'>
<p>STEP 1</p>
</div>
<div class='step' data-step='2'>
<p>STEP 2</p>
</div>
<div class='step' data-step='3'>
<p>STEP 3</p>
</div>
<div class='step' data-step='4'>
<p>STEP 4</p>
</div>
</div>
</section>
<section id='outro'></section>
<div class='debug'></div>
And js
// using d3 for convenience
var container = d3.select("#scroll");
var graphic = container.select(".scroll__graphic");
var chart = graphic.select(".chart");
var text = container.select(".scroll__text");
var step = text.selectAll(".step");
// initialize the scrollama
var scroller = scrollama();
// generic window resize listener event
function handleResize() {
// 1. update height of step elements
var stepHeight = Math.floor(window.innerHeight * 0.75);
step.style("height", stepHeight + "px");
// 2. update width/height of graphic element
var bodyWidth = d3.select("body").node().offsetWidth;
graphic
.style("width", bodyWidth + "px")
.style("height", window.innerHeight + "px");
var chartMargin = 32;
var textWidth = text.node().offsetWidth;
var chartWidth = graphic.node().offsetWidth - textWidth - chartMargin;
chart
.style("width", chartWidth + "px")
.style("height", Math.floor(window.innerHeight / 2) + "px");
// 3. tell scrollama to update new element dimensions
scroller.resize();
}
// scrollama event handlers
function handleStepEnter(response) {
// response = { element, direction, index }
// add color to current step only
step.classed("is-active", function(d, i) {
return i === response.index;
});
// update graphic based on step
chart.select("p").text(response.index + 1);
}
function handleContainerEnter(response) {
// response = { direction }
// sticky the graphic (old school)
graphic.classed("is-fixed", true);
graphic.classed("is-bottom", false);
}
function handleContainerExit(response) {
// response = { direction }
// un-sticky the graphic, and pin to top/bottom of container
graphic.classed("is-fixed", false);
graphic.classed("is-bottom", response.direction === "down");
}
function init() {
// 1. force a resize on load to ensure proper dimensions are sent to scrollama
handleResize();
// 2. setup the scroller passing options
// this will also initialize trigger observations
// 3. bind scrollama event handlers (this can be chained like below)
scroller
.setup({
container: "#scroll",
graphic: ".scroll__graphic",
text: ".scroll__text",
step: ".scroll__text .step",
debug: true
})
.onStepEnter(handleStepEnter)
.onContainerEnter(handleContainerEnter)
.onContainerExit(handleContainerExit);
// setup resize event
window.addEventListener("resize", handleResize);
}
// kick things off
init();

I believe that the only way is instantiate scrollama more than once:
var scroller1 = scrollama();
var scroller2 = scrollama();
See example here:
https://github.com/russellgoldenberg/scrollama/blob/master/dev/multiple.html

Related

Run function on load and resize & get height of class

I have created this function but there are two things that are not working and, after a while trying to find why, I can't find the reason.
First, it should take the height from .bar-info, but is not. It gets -10, instead of 100px
Second, when the page loads (and on resize), it should run this function and get the height, but it doesn't. It works on resize, but not on ready
onResize = function() {
if($(window).width() < 1000) {
//Set height based in number of bars
$('.vert .bars').each(function(){
var length = $(this).find(".bar-info").length;
var info = $(this).find(".bar-info").height(); // 1. Not taking the correct height
var height = (info * length) + 1270 + "px";
$(this).parent().css({"height":height}); // 2. Wrong height just on load
});
} else {
$('.vert .bars').each(function(){
$(this).parent().css({"height":"1200px"});
});
}
}
$(document).ready(onResize); // Why it doesn't work?
$(window).resize(onResize); // This works
HTML:
<div class="container vertical flat vert">
<div class="bars">
<div class="bar-general">
<div class="bar-info">Content</div>
</div>
</div>
</div>

console error for my ripple effect: Uncaught TypeError: $(...).click(...) is not a function

I'm getting this error in the console: Uncaught TypeError: $(...).click(...) is not a function and I'm not sure where is the error. The code seems to be fine. I also add the html file.
html
<section>
<div class="fu-ripple-effect">
<header><h2>hello world</h2>
<p>hello world paragraph</p>
</header>
</div>
</section>
js
var parent, ink, d, x, y;
$("section .fu-ripple-effect").click(function(e) {
parent = $(this).parent();
//create .ink element if it doesn't exist
if (parent.find(".ink").length == 0)
parent.prepend("<span class='ink'></span>");
ink = parent.find(".ink");
//incase of quick double clicks stop the previous animation
ink.removeClass("animate");
//set size of .ink
if (!ink.height() && !ink.width()) {
//use parent's width or height whichever is larger for the diameter to make a circle which can cover the entire element.
d = Math.max(parent.outerWidth(), parent.outerHeight());
ink.css({
height: d,
width: d
});
}
//get click coordinates
//logic = click coordinates relative to page - parent's position relative to page - half of self height/width to make it controllable from the center;
x = e.pageX - parent.offset().left - ink.width() / 2;
y = e.pageY - parent.offset().top - ink.height() / 2;
//set the position and add class .animate
ink.css({
top: y + 'px',
left: x + 'px'
}).addClass("animate");
})
There are three things you might need to do:
You need to import jQuery
You need to add a $(document).ready(function() {...});
You need to end blocks like:
$(...).click(function() {})
with a semicolon.
Example:
$(document).ready(function() {
// put jQuery code here
$('.foo').click(function() {
$('.foo').fadeOut(1000);
});
});
<!--Importing jQuery-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">bar</div>

jQuery UI Layout - How change a pane's options and dynamically apply them without toggling the pane open/closed?

http://jsfiddle.net/jc3rj681/2/
Using the plugin jQuery UI Layout, I have several different panes. When the user resizes the window to a small size, I would like to call a function that changes the minsize and size of the pane so that I can make it smaller with the window.
I can do this, but for the changes to apply, I must toggle closed and then toggle open the pane. This creates a lot of flickering and ends up being pretty messy looking. I only need this one pane to resize in this fashion.
QUESTION: Is there a way I can apply these layout changes without having to toggle the pane twice for them to apply?
Check out this Fiddle that I made: http://jsfiddle.net/jc3rj681/2/
In here, the changes to the "width" of the show/hide button don't get applied until you toggle the pane. If you can make this width change work without toggling, I'm sure it would solve my problem as well.
$("#eastToggle").click(function () {
testLayout.toggle('east');
});
$("#attempt").click(function () {
testLayout.options.east.spacing_closed = 20;
testLayout.options.east.spacing_open = 20;
});
I'm not sure if there is a callback function or any special utility method that'll do the trick.
But you can try something like the following (probably with a resize function that'll resize the panes manually) -
var testLayout = $('body').layout({
applyDefaultStyles: true,
east: {
spacing_closed: 100, //toggler width
spacing_open: 100,
togglerLength_closed: 200, //toggler height (length)
togglerLength_open: 200
}
});
$("#eastToggle").click(function() {
testLayout.toggle('east');
});
$("#attempt").click(function() {
resize('east', 20);
});
// A function to resize the tab
function resize(region, space) {
// Width of the new center pane
var newCenterWidth = parseInt($('body .ui-layout-center').css('width').split('px')[0]) + testLayout.options.east.spacing_closed - space;
// Change the options so they don't affect the layout when you expand / collapse again
testLayout.options.east.spacing_closed = space;
testLayout.options.east.spacing_open = space;
// Manually resize the panes
$('body .ui-layout-resizer-' + region).css('width', space);
$('body .ui-layout-center').css('width', newCenterWidth);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://layout.jquery-dev.net/lib/js/jquery.layout-latest.js"></script>
<div class="ui-layout-center">Center</div>
<div class="ui-layout-north">North</div>
<div class="ui-layout-south">South</div>
<div class="ui-layout-east">East</div>
<div class="ui-layout-west">West
<br/>
<br/>
<button id="eastToggle">Toggle East Panel</button>
<br/>
<br/>
<button id="attempt">Change Width?</button>
</div>

Responsive font size using CSS/jQuery

I want to create a responsive text inside a div.
I tried jquery-textfill and FlowType, but they are not working for me at all.
FlowType does not use all the available space, only a part of it (demo), while textfill does not respect the height (demo).
Am I using them incorrecly or what I want is too hard to achieve?
My HTML:
<body>
<div class="external">
<div class="internal">Example</div>
</div>
</body>
My CSS:
.internal{width:100%;height:100%}
.external{width:400px;height:50px;}
PS. Viewports are not supported enough for now.
EDIT: Updated with resize event listener. Updated fiddle.
As I understand it, you want the text to be as large as possible while still fitting inside the containing <div>, correct? My solution is to put a <span> around the text, which conforms to the text's normal size. Then calculate the ratios between the container's dimensions and the <span>'s dimensions. Whichever is the smaller ratio (either width or height), use that ratio to enlarge the text.
HTML:
<div class="container">
<span class="text-fitter">
text here
</span>
</div>
JS (jQuery):
textfit();
$(window).on('resize', textfit);
function textfit() {
$('.text-fitter').css('font-size', 'medium');
var w1 = $('.container').width()-10;
var w2 = $('.text-fitter').width();
var wRatio = Math.round(w1 / w2 * 10) / 10;
var h1 = $('.container').height()-10;
var h2 = $('.text-fitter').height();
var hRatio = Math.round(h1 / h2 * 10) / 10;
var constraint = Math.min(wRatio, hRatio);
$('.text-fitter').css('font-size', constraint + 'em');
}
Here's a fiddle. Adjust the .container dimensions in the CSS to see it in action.
CSS
.internal{width:100%;height:100%}
.external{width:auto;height:auto;background-color:yellow}
JQuery
$(".external").fitText(0.5);
DEMO 1
Update 1:
CSS
.internal{width:auto;height:auto;position:absolute;}
.external{width:400px;height:50px;background-color:yellow;position:relative;}
JQuery
$(".external").fitText();
DEMO 2
Update 2:
JQuery
var ex=$(".external");
var h=ex.height();
var w=ex.width();
ex.fitText(Math.min(h,w)/Math.max(h,w) );
DEMO 3
Update 4:
Bigtext is a jQuery text plugin that automatically enlarge the font size of your text to fill its parent container, without overflowing the container Div.
jQuery Bigtext Plugin
For anyone who stumbles upon this old post, I have found a solution I consider perfect.
You take this beautiful plugin written by Dave Rupert, configure the settings to your liking, and I added a wrapper for it that allows you to define the elements you want to resize. It also stores the original font size so when you scale back up, the text is limited by it's original size, otherwise it scales without limit.
Here's a snippet and a jsfiddle. JSFiddle
NOTE: the snippet only runs on resize in JSFiddle so be sure to resize your screen. In production it runs on load.
var headings = [$('h1'), $('h2'), $('h3')]
$.each(headings, function(index, heading) {
var fontsize = heading.css('font-size');
$(window).on('load resize', function() {
if (heading.parent()[0] &&
heading.parent()[0].scrollWidth > $('.container').innerWidth()) {
heading.fitText(1, {
minFontSize: '10px',
maxFontSize: fontsize
});
}
});
});
/*global jQuery */
/*!
* FitText.js 1.2
*
* Copyright 2011, Dave Rupert http://daverupert.com
* Released under the WTFPL license
* http://sam.zoy.org/wtfpl/
*
* Date: Thu May 05 14:23:00 2011 -0600
*/
$.fn.fitText = function(kompressor, options) {
// Setup options
var compressor = kompressor || 1,
settings = $.extend({
'minFontSize': Number.NEGATIVE_INFINITY,
'maxFontSize': Number.POSITIVE_INFINITY
}, options);
return this.each(function() {
// Store the object
var $this = $(this);
// Resizer() resizes items based on the object width divided by the compressor * 10
var resizer = function() {
$this.css('font-size', Math.max(Math.min($this.width() / (compressor * 10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
};
// Call once to set.
resizer();
// Call on resize. Opera debounces their resize by default.
$(window).on('resize.fittext orientationchange.fittext', resizer);
});
};
.container {
width: 80vw;
background: yellow;
}
h1 {
font-size: 5rem;
}
h2 {
font-size: 4rem;
}
h3 {
font-size: 3rem;
}
h4 {
font-size: 1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h1>GIGANTICFONT</h1>
</div>
<div class="container">
<h2>LargishFont</h2>
</div>
<div class="container">
<h3>Mediumfont</h3>
</div>
<div class="container">
<h4>smallfont</h4>
</div>

Curved image path when scrolling page

I'm trying to create a rollercoaster ride for a project and need the rollercoaster to follow a path.
You can see my illustration on rollercoaster
I need the red box to follow the rollercoaster road in the background? The red box illustreres the image I'm going to use. Is this possible? I'm trying using this code...
<script type="text/javascript">
$(window).on('scroll', function(e) {
var scrollTop = $(window).scrollTop();
//var windowHeight = $(window).height();
var windowHeight = $('.road2').height();
//var S = scrollTop + Math.floor(windowHeight / 2);
var S = $(this).scrollTop(); // scrolled distance
var t = 0 + (S/windowHeight);
//var T = 0 + (S/36); // value for Top
//var L = 300 + Math.abs(Math.sin(S/400)*460); // value for Left
//
//$(".rollerImage").css({top: T+'%', left: L+'px'}); //set CSS
var canvas_X=400;
var canvas_Y=400;
// Increment Parameterization
t += 0.05;
// Width of Car
var car_X=150;
// Hieght of Car
var car_Y=50;
// Point A
var a_X=0;
var a_Y=0;
// Point B
var b_X=canvas_X-car_X; //Place point B at the end
var b_Y=0;
// Center of Semi Circle
var c_X=(b_X-a_X)/2;
var c_Y=(a_Y-a_Y)/2;
// Calculate X and Y point on trajectory
var x = a_X + t * (b_X- a_X);
var y = Math.sqrt(Math.pow((b_X - a_X),2)/4 + Math.pow((x-c_X),2));
$(".rollerImage").css({top: x+'px', left: y+'px'}); //set CSS
});
</script>
Hope someone can help with this type of path animation. Maybe it is possible to define the path in a array of coordinates?
I've tried using joel scrollpath, but can't "bind" an image to the path :(
//Graahf
I've tried to get it working with the jQuery Scrollpath using your html and css files plus the code from the demo site.
Check if this is OK for you: http://jsfiddle.net/Skr4R/6/embedded/result/
You can also check the sources of the fiddle: http://jsfiddle.net/Skr4R/6/
Important for this, is that the entire wrapper moves and rotates, that is why in my solution the train-image is outside of the wrapper, like this:
<div class="rollerCoasters">
<img src="" style="background:red; height:100px; width:50px; position:absolute; top:380px; left:50%; z-index:200; margin-left:-25px">
</div>
<div class="wrapper">
<div class="road1"><img src="base64-encoded-img" width="1434" height="539"/></div>
</div>
Hope this gets you started. It might not be the best solution, if you want the train to move, and not it's surroundings.
i am trying to achieve the same process and this has helped me along, the way forward about roating the train/object with the track could you not rotate the background(track to make the train look like it is following the track)

Categories