When a user scrolls through a webpage, how can I trigger animate css?
Is it a matter of when v-show="element" appears, trigger x?
Using Vue 2 + animate css
I found answer from Ikbel useful
How to display and transition when scroll position reaches element position in the screen?
you can achive this with custom directive which adds binding inViewport for window scroll event to elements that you want to animate.
I added data-transition to html element that I want to animate
<div v-vpshow data-transition="flipInX"><div>
and changed binding like this
el.$onScroll = function() {
if (binding.def.inViewport(el)) {
el.classList.add('animated')
el.classList.add(el.getAttribute('data-transition'))
el.classList.remove('before-enter')
binding.def.unbind(el, binding)
}
}
Related
I have a set of cards that are arranged vertically and are currently draggable. When you drag a card over another, you see this card as a semi-transparent card hovering over the target position, before you let go, the cards underneath swap positions.
I want to know how to trigger that behavior(swap positions/show animation of moving up/down) without dragging eg. click arrows up/down.
To clarify: "trigger event" as in not call the method that responds to the moving event(ending) but make the cards move as if a mouse/finger dragged the cards in a direction(up/down).
For now I have added a position switch that reorders the array but it does not trigger the visual aspect eg. dragging. You just see a flash and then cards are ordered differently.
See visual behavior
before move
during move
after move
Draggable component
<draggable v-model="things" :move="checkPosition" :options={animation:500}">
<div v-for="(thing, index) in things">
<div class="up" #clickSort"('up', index)">
<div class="down" #clickSort"('up', index)">
</div>
</draggable>
Relevant JS methods
watch: {
things: {
// this fires when you sort by dragging, as well as button click
// loop over things
// update vuex
}
}
checkPosition(event) {
if (event.related) {
// code that keeps draggable item pos in scope of existing elements
// some are hidden
return !event.related.classList.contains('locked');
}
}
clickDrag(direction, itemPos) {
// manual array sorting, no draggable event eg. hover/motion/transition
}
In order to create this transition effect, you must use Enter/Leave Transition provided by Vue https://v2.vuejs.org/v2/guide/transitions.html
You will need to define css animation styles that Vue will apply to your components when you want to trigger the animation, like ondrop event.
I have just started with Dojo widgets. Recently, I did this Dijit Horizontal Slider Sample,and I have been wondering how to make a tooltip follow the slider handle with the current slider value as the tooltip content.
I have tried the same but am facing two issues:
One, the tooltip appears at the end of the slider rather than constantly hovering on the slider handle.
Two, the tooltip displays a value only when I stop sliding rather than changing seamlessly.
How to overcome these?
If you want the tooltip to move with the slider, you have to find a way to open it from the slider handle, not from the entire horizontal slider widget. I do not know if the actual slider you move with the mouse is it's own widget or not. From the declarative sample online the HTML for the handle looks like this
<div data-dojo-attach-point="sliderHandle,focusNode" class="dijitSliderImageHandle dijitSliderImageHandleH" data-dojo-attach-event="press:_onHandleClick" role="slider" aria-valuemin="-10" aria-valuemax="10" tabindex="0" aria-valuenow="4" style="position: absolute;"></div>
So you can try something like the following, if you can get a reference to the sliderHandle object.
/*
* Create the tooltip dialog that you want to show (I use tooltip dialog,
* but you can do the same with basic tooltip)
*/
var myTooltipDialogbase = new ttdialog({
id: 'myTooltipDialogBase',
style: "width: 275px;"
});
Then in your event handler (in this example right mouse click) you open the popup
/**
* On right mouse click, opens the tooltip dialog
*/
on(sliderHandle, 'contextmenu', function (event) {
popup.open({
parent: sliderHandle,
popup: myTooltipDialogbase,
around: sliderHandle.domNode
});
});
EDIT:
For your second question, you can use the slider property onChange() to do something each time the value of the slider changes. You must set intermediateChanges=true so onChange is called when sliding. In your case, in onChange(), if you can get a reference to the tooltip, then change the value of one of the tooltip objects for every value change of the slider.
I'm trying to set the initial scroll position of a ListView in react native.
Right now, I'm doing this:
componentDidMount() {
let i = this.props.images.indexOf(this.props.current);
if(i != -1) {
this.refs.listView.scrollTo({ x:i*this.props.width, y:0, animated:false });
}
}
where the images prop is the datasource for the ListView, the current prop is where I want to be initially scrolled to, and the width prop is the width of the component. (The component scrolls horizontally).
This works, but there's a delay between the initial render and the call to componentDidMount, giving me a flash of the end of end of the list before the list is scrolled.
Is there a way of setting an initial scroll position of the list? Or better way of doing this to get rid of that flash?
On iOS you can use the ScrollView#contentOffset to set the initial scroll position of a ListView, which inherits the properties of ScrollView.
If you are looking for an Android solution, the ListView.scrollTo method you are calling seems like the best bet for the general case.
That said, if I interpret your code sample correctly, you are using the ListView for a paginated, horizontal list, perhaps with the help of the pagingEnabled property? If this is the case, on Android you might look at using ViewPagerAndroid instead, and setting the initialPage property.
Please see my fiddle below:
https://jsfiddle.net/okiewardoyo/s23v891m/11/
.affix {
top: 0;
}
To make the screen wider, scroll your screen.
What I want is, if I scroll, the sidebar become fixed when scrolling reach the bottom of header.
Then, when I scroll and reach the footer, the sidebar is not fixed and it follows the footer.
You will need to add an offset to the content class, and remove it again using jQuery.
Add the id 'content' to your content div. Then add the following jQuery script:
$('.sidebar').on('affix.bs.affix', function() {
$('#content').addClass('col-sm-offset-3');
}).on('affix-top.bs.affix', function(){
$('#content').removeClass('col-sm-offset-3');
});
You can test this here: https://jsfiddle.net/TimOgilvy/s23v891m/16/
Note I added a clearfix to the header.
If you look at the bootstrap demo that is hosted here And scroll down to the demo that has all 4 buttons. Now click on the left popover, it shows properly. However, When I shrink or extend the screen the popover is no longer anchored to the proper point. Is there a way around this?
This has to do with the container property for the popover.
http://jsfiddle.net/yvkhbw4b/1/
See the attached example. Show both popovers then resize the window from xs breakpoint to sm breakpoint. You will see the top item will seperate from the button as the container defaults to body. (I'm also setting it to body though options). The second item is attached to the parent div so that one remains attached to the element even though the breakpoint changed.
Documentation on popover options
Appends the popover to a specific element. Example: container: 'body'.
This option is particularly useful in that it allows you to position
the popover in the flow of the document near the triggering element -
which will prevent the popover from floating away from the triggering
element during a window resize.
$('#btn1').popover({
'container': 'body'
});
$('#btn2').popover({
'container': '.col-sm-12'
});
Potential Fix: you could add the following code. Currently only handles bottom aligned popovers but you can add options for other alignments.
$(window).resize(function () {
$('.popover.in').each(function () {
var el = $('[aria-describedby="' + this.id + '"]');
if ($(this).hasClass('bottom')){
$(this).css('top',el.offset().top + el.outerHeight(true));
}
});
});
http://jsfiddle.net/yvkhbw4b/2/