I actually want to change the background-image with mouse wheel, touchpad and touchscreen scroll, but I don't want the page to have the scroll bar. My idea is the page with no scrolling, which would change background images (from the list of about 5-7 images) when user turns mouse wheel, scrolls on touchpad or touchscreen. Is it possible? Html + javascript + css would be okay.
using pure html/javascript/css
function addListeners() {
// var bdy = document.body;
var bdy = document.body;
if (bdy.addEventListener) {
// IE9, Chrome, Safari, Opera
bdy.addEventListener("mousewheel", MouseWheelHandler, false);
// Firefox
bdy.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
}
// IE 6/7/8
else bdy.attachEvent("onmousewheel", MouseWheelHandler);
return false;
}
var counter = 0 ;
var maxCount = 4 ;
function MouseWheelHandler(e) {
var bdy = document.body;
// cross-browser wheel delta
var e = window.event || e; // old IE support
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
counter += delta ;
counter = counter%maxCount ;
if( counter < 0 ) counter = maxCount ;
bdy.style.backgroundImage = 'url(images/' + counter + '.jpg)' ;
return false;
}
<html>
<head>
<script type="text/javascript" src="scripts.js" >
</script>
</head>
<body onload="return addListeners();">
</body>
</html>
Related
I search on my friend Google for some code to do smooth scroll and found this : Smooth vertical scrolling on mouse wheel in vanilla javascript?
It works well but if i scroll once and then try to use my mouse to manually move the scrollbar, it's broken...
SmoothScroll(document, 120, 12);
function SmoothScroll(target, speed, smooth) {
if (target === document)
target = (document.scrollingElement ||
document.documentElement ||
document.body.parentNode ||
document.body) // cross browser support for document scrolling
var moving = false
var pos = target.scrollTop
var frame = target === document.body &&
document.documentElement ?
document.documentElement :
target // safari is the new IE
target.addEventListener('scroll', scrolled, {
passive: false
})
target.addEventListener('mousewheel', scrolled, {
passive: false
})
target.addEventListener('DOMMouseScroll', scrolled, {
passive: false
})
function scrolled(e) {
e.preventDefault(); // disable default scrolling
var delta = normalizeWheelDelta(e)
pos += -delta * speed
pos = Math.max(0, Math.min(pos, target.scrollHeight - frame.clientHeight)) // limit scrolling
if (!moving) update()
}
function normalizeWheelDelta(e) {
if (e.detail) {
if (e.wheelDelta)
return e.wheelDelta / e.detail / 40 * (e.detail > 0 ? 1 : -1) // Opera
else
return -e.detail / 3 // Firefox
} else
return e.wheelDelta / 120 // IE,Safari,Chrome
}
function update() {
moving = true
var delta = (pos - target.scrollTop) / smooth
target.scrollTop += delta
if (Math.abs(delta) > 0.5)
requestFrame(update)
else
moving = false
}
var requestFrame = function () { // requestAnimationFrame cross browser
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (func) {
window.setTimeout(func, 1000 / 50);
}
);
}()
}
So... i want it to work properly when i already scroll once but try to use the mouse to move the scrollbar instead of mousewheel.
Thanks for helping!
Looks like you could fix it by re-adjusting the pos variable to the scrollTop before your scrolling calculations.
Additionally theres a bug where your scroll could get stuck in an infinite render loop causing you to never stop animating. This was due to the delta being .5 < delta < 1 making the request frame get called forever. You cant actually move the scrollTop anything less than 1 so I adjusted the conditions for another render loop and rounded the delta
function scrolled(e) {
// if currently not animating make sure our pos is up to date with the current scroll postion
if(!moving) {
pos = target.scrollTop;
}
e.preventDefault(); // disable default scrolling
var delta = normalizeWheelDelta(e)
pos += -delta * speed
pos = Math.max(0, Math.min(pos, target.scrollHeight - frame.clientHeight)) // limit scrolling
if (!moving) update()
}
function update() {
moving = true;
// scrollTop is an integer and moving it by anything less than a whole number wont do anything
// to prevent a noop and an infinite loop we need to round it
var delta = absRound((pos - target.scrollTop) / smooth)
target.scrollTop += delta
if (Math.abs(delta) >= 1) {
requestFrame(update)
} else {
moving = false
}
}
function absRound(num) {
if(num < 0) {
return -1*Math.round(-1*num);
} else {
return Math.round(num);
}
}
That way when manually adjusting the scroll position if the wheel is used it doesnt jump to the position it was once at, but instead adjust itself to the current scroll position.
I'm in developing custom Map View component with kendo-colorpicker(kendoFlatColorPicker) to change color of markers.
the root element of flatcolorpicker is child element of map view wrapper element.
<div id="map-view">
<!--some elements....-->
<div id="custom-flat-color-picker"></div>
</div>
In kendoFlatColorPicker, user can select color in hsvRect panel by dragging mouse.
There is a critical issue...
When Pressing mouse button and dragging mouse on FlatColorPicker panel, the map image in Map View is also dragged.
I think that this issue came from event-bubbling. So, I try to use e.stopPropagation() method in 'mousedown' event.
However, it is not working.
Other ways, I also try to customize _hsvEvets method in kendo FlatColorPicker source code through widget extends like below code.
var KEYDOWN_NS = 'keydown.kendoEditor';
var bind = kendo.bind;
var FlatColorPicker = kendo.ui.FlatColorPicker;
var extendFlatColorPicker = FlatColorPicker.extend({
options: {
name: 'CustomFlatColorPicker'
},
init: function (element, options){
var self = this;
FlatColorPicker.fn.init.call(self, element, options);
},
_hsvArea: function () {
var that = this,
element = that.element,
hsvRect = element.find('.k-hsv-rectangle'),
hsvHandle = hsvRect.find('.k-draghandle').attr('tabIndex', 0);
function update(x, y) {
var offset = this.offset, dx = x - offset.left, dy = y - offset.top, rw = this.width, rh = this.height;
dx = dx < 0 ? 0 : dx > rw ? rw : dx;
dy = dy < 0 ? 0 : dy > rh ? rh : dy;
that._svChange(dx / rw, 1 - dy / rh);
}
that._hsvEvents = new kendo.UserEvents(hsvRect, {
global: true,
press: function (e) {
//this.element.get(0).dispatchEvent(new Event('mousedown'));
this.offset = kendo.getOffset(hsvRect);
this.width = hsvRect.width();
this.height = hsvRect.height();
hsvHandle.focus();
update.call(this, e.x.location, e.y.location);
},
start: function () {
hsvRect.addClass('k-dragging');
hsvHandle.focus();
},
move: function (e) {
e.preventDefault();
update.call(this, e.x.location, e.y.location);
},
end: function () {
hsvRect.removeClass('k-dragging');
}
});
that._hsvRect = hsvRect;
that._hsvHandle = hsvHandle;
// var cb = that._hsvEvents.press;
// that._hsvEvents.press = function(e){
// e.stopPropagation();
// cb.call(this);
// };
}
});
kendo.ui.plugin(extendFlatColorPicker);
When user press mouse button to drag mouse, 'press' event is occured on flat color picker, however parameter 'e' has no method stopPropagation().
How can I stop bubbling from colorpicker to map view?
I solved this issue.
I found event 'pointerdown' in event listener stack that can be found in chrome dev tool. About this event, I applied e.stopPropagation().
im currently building a website using fullpage js and lottie animations. Now im trying to trigger an animation when the user scrolls to the section with the animation. Here is what i tried:
(please note that im very new to js)
$(document).ready(function($) {'use strict';
$('#fullpage').fullpage({
sectionsColor: ['white', '#004E8A', 'white','#004E8A', 'white', '#004E8A',
'white','#004E8A', 'white'],
anchors:['startseite','pers_vermittler','team','konzept','rechner','mod_portfolio','sicherheit','absatz'],
onLeave: function(index, nextIndex, direction) {
if( index == 3 && direction == 'down' ) {
lottie.play('k2an');
}
(at the end of the body section ->)
<script>
var params = {
container: document.getElementById('k2an'),
renderer: 'svg',
loop: true,
autoplay: false,
path: 'k2an.json',
};
anim = lottie.loadAnimation(params);
You should be using fullPage.js callbacks to fire your JS animations.
See the example:
$('#fullpage').fullpage({
anchors: ['firstPage', 'secondPage', 'thirdPage', 'fourthPage', 'lastPage'],
afterLoad: function(anchorLink, index){
var loadedSection = $(this);
//using index
if(index == 3){
alert("Section 3 ended loading");
}
//using anchorLink
if(anchorLink == 'secondSlide'){
alert("Section 2 ended loading");
}
}
});
Feel free to also check my video tutorial on how to create animations using fullPage.js state classes.
Right now im using this approach on a couple production sites. It plays the animation as the user scrolls.
I basically check how much of the animation objects box is visible in the viewport, calculate the total length of the animation (in frames) and then project the percentage to a frame where i gotoAndStop().
var anim = <YOUR LOTTIE ANIMATION OBJECT>
// play around with these
var speed = 1; // speed of animation
var scrollOffset = 0; // start animation sooner / later
function scrollHandler() {
if (!anim.isLoaded) return;
p = percentageSeen(e) / 100 - (scrollOffset || 0);
if (p <= 0 || p >= 1) return
var length = anim.totalFrames / anim.frameModifier;
var pos = length * p * (speed || 1);
anim.goToAndStop(pos);
}
$(window).on('scroll', scrollHandler);
/**
* returns percentage of scrolling element through viewport
* 0% until element-middle is at bottom of viewport
* 100% if element-middle is at top of viewport
*
* #param id
* #returns {number}
*/
function percentageSeen(idOrElement) {
var $element;
if (typeof idOrElement === 'object') {
$element = idOrElement;
} else {
$element = $('#' + id);
if (!$element[0]) return 0;
}
var $win = $(window), viewportHeight = $(window).height(),
scrollTop = $win.scrollTop(),
elementOffsetTop = $element.offset().top,
elementHeight = $element.height();
if (elementOffsetTop > (scrollTop + viewportHeight)) {
return 0;
} else if ((elementOffsetTop + elementHeight) < scrollTop) {
return 100;
} else {
var distance = (scrollTop + viewportHeight) - elementOffsetTop - (elementHeight / 2);
if (distance < 0) return 0;
var percentage = distance / (viewportHeight / 100);
if (percentage > 100) return 100;
return percentage;
}
}
If you want to only start the animation and let it run (independently of further user-scrolling-behaviour), just use the jquery inview plugin, disable autoplay on your animation and trigger the play() once like this:
$(".animation-container").one("inview", function() {
anim.play()
});
I am making a webpage with a "time line" style, it's navigated horizontally but has a fixed menu with an element that slides along a bar when you click on every element.
Now I was using a blueprint of vertical timeline that also moved the element across the bar when you got to the element by scrolling normally
http://www.webdesigncrowd.com/demo/slider-timeline-menu-12.2.13/
Now, I am using a page-wrap div to keep the elements within a certain boundary along with a css style for the body to stack elements horizontally.
When I click on ever it takes me to the correct page like normal, and the bar element works as intended, but the feature for it to work when the linked element moves into view doesn't seem to work anymore
This is the original JS code
// Scroll Spy
$(window).scroll(function() {
var top = $(window).scrollTop() + 100; // Take into account height of fixed menu
$(".container").each(function() {
var c_top = $(this).offset().top;
var c_bot = c_top + $(this).height();
var hash = $(this).attr("id");
var li_tag = $('a[href$="' + hash + '"]').parent();
if ((top > c_top) && (top < c_bot)) {
if (li_tag.hasClass("active")) {
return false;
} else {
li_tag.siblings().andSelf().removeClass("active");
li_tag.addClass("active");
$(".menu ul li.active a").slideToPos();
}
}
});
});
And this is what I edited to try to make it work on a Horizontal display.
// Scroll Spy
$(window).scroll(function() {
var left = $(window).scrollLeft() + 1300; // Take into account height of fixed menu
$(".container").each(function() {
var c_Left = $(this).offset().left;
var c_bot = c_left + $(this).width();
var hash = $(this).attr("id");
var li_tag = $('a[href$="' + hash + '"]').parent();
if ((left > c_Left) && (left < c_bot)) {
if (li_tag.hasClass("active")) {
return false;
} else {
li_tag.siblings().andSelf().removeClass("active");
li_tag.addClass("active");
$(".menu ul li.active a .navut").slideToPos();
}
}
});
});
Now I have tried using the original one without change too, but that feature is still not working.
I thank you guys in advance.
What I'm trying to do is reload my labels when the user moves or scrolls the map to a different position. Currently when the user zooms in past a certain level the labels load and every thing works correct. When the user starts to move the map to a different state the labels disappear and you have to zoom out and zoom back in to regenerate the labels.
I've changed onZoomEnd to update / update-end / load / onLoad
Here is the code:
function initUI(graphics) {
dojo.connect(globals.map, 'onZoomEnd', function () {
console.log("Initial zoom level is :" + globals.map.getZoom());
var font = new esri.symbol.Font(14, esri.symbol.Font.STYLE_NORMAL, esri.symbol.Font.VARIANT_NORMAL, esri.symbol.Font.WEIGHT_BOLDER, "Arial");
var gl = globals.featureLayers[1].graphics;
globals.map.graphics.clear();
if (globals.map.getZoom() >= 9) {
console.log(codeID);
for (var i = 0; i < gl.length ; i++) {
var g = globals.featureLayers[1].graphics[i];
if (codeID == 1 || codeID == 32 || codeID == 28 || codeID == 33 || codeID == 10) {
var strLabel = g.attributes.NAME + ":" + $.formatNumber(findFips(g), { format: '#,###', locale: "us" });//creates string label formatted
var textSymbol = new esri.symbol.TextSymbol(strLabel, font);//create symbol with attribute name
textSymbol.setColor(new dojo.Color([0, 0, 0]));//set the color
var pt = g.geometry.getExtent().getCenter(); //get center of county
var labelPointGraphic = new esri.Graphic(pt, textSymbol); //create label graphic
//add label to the intended graphic
globals.map.graphics.add(labelPointGraphic);
}
else {
var strLabelPct = g.attributes.NAME + " : " + $.formatNumber(findFips(g), {format: '#,###.0', locale: "us"}) + "%";
var textSymbol = new esri.symbol.TextSymbol(strLabelPct);//create symbol with attribute name
textSymbol.setColor(new dojo.Color([0, 0, 0]));//set the color
var pt = g.geometry.getExtent().getCenter(); //get center of county
var labelPointGraphic = new esri.Graphic(pt, textSymbol); //create label graphic
//add label to the intended graphic
globals.map.graphics.add(labelPointGraphic);
}
}//end for
}//end if
});//end on zoom end
If possible, the new 3.7 Esri ArcGIS JavaScript API has a new LabelLayer that may help deal with your issue. It doesn't have as many features but is a great start for a beta feature.
Label Layer
Here is a block of code that I've used (written in 3.7). It uses the new AMD style require and "dojo/on" to attach the updated event triggers to the map.
map.on('zoom-end', function() {
handleMapPanZoom(); // Turns some complex layers on and off.
maxOffset = calcOffset(map); // Updates the max offset at each zoom level.
for (var i = 0; i < lyrs.length; i++) {
lyrs[i].setMaxAllowableOffset(maxOffset);
}
});
map.on('extent-change', function() {
handleMapPanZoom();
});