My multilayer canvas scrolls too slowly using the scrollbar - javascript

I have a multilayered canvas. The images inside can be big so they overflow the dimensions of the , and I have to scroll (and I want that it works so). I draw different images in each layer but I want their relative position fixed, so I have to scroll all the canvas together: when I scroll the first one I want they all to scroll.
The problem is that it scrolls very slowly. When I click on the arrows down/up it scrolls only some pixel. When I keep the mouse down on an arrow it scroll few pixels/second. When I click on the scrollbar, outside the bar, it make a jump of only 50-100 pixels. But if I drag the bar it move normally (fast).
My html:
<div style='display:inline-block; width:100%; position:relative; top: 0px; left: 0px;'>
<div id='canvas1' class='canvas canvas_map' style='overflow:scroll; background-color: lightgrey; z-index: 1; position:absolute; left:133px; top:0px;'></div>
<div id='canvas2' class='canvas canvas_map' style='overflow:scroll; z-index: 2; position:absolute; left:133px; top:0px;'></div>
[...]
<div id='canvas12' class='canvas canvas_map' style='overflow:scroll; z-index: 12; position:absolute; left:133px; top:0px;'></div>
<div id='canvas13' draggable='true' class='canvas canvas_map' style='overflow:scroll; cursor: crosshair; z-index: 13; position:absolute; left:133px; top:0px;'></div>
</div>
My javascript:
var canvas_list=document.getElementsByClassName('canvas_map');
document.getElementById('canvas13').addEventListener(
'scroll', function() {
var scroll_x = document.getElementById('canvas13').scrollLeft;
var scroll_y = document.getElementById('canvas13').scrollTop;
for (var i=0; i<canvas_list.length; i++) {
canvas_list[i].scrollLeft=scroll_x;
canvas_list[i].scrollTop=scroll_y;
};
});
PS: I'm using Raphael library for drawing the images:
var paper_map1 = Raphael(canvas1, '100%', '100%');
[...]
PS2: most canvas are empty, the other have 1-2 light images, so it shouldn't be a memory problem.

Related

Jquery - Move an shape all around a transparent image

I have an image with transparent areas.
I dev another green div.
How can I move the green div all around the image by respecting the transparent areas. So the green div can pass under the transparent areas but not the non transparent one ?
Js Fiddle can be found here:
https://jsfiddle.net/Lcper5y1/
function handle_mousedown(e){
window.my_dragging = {};
my_dragging.pageX0 = e.pageX;
my_dragging.pageY0 = e.pageY;
my_dragging.elem = this;
my_dragging.offset0 = $(this).offset();
function handle_dragging(e){
var left = my_dragging.offset0.left + (e.pageX - my_dragging.pageX0);
var top = my_dragging.offset0.top + (e.pageY - my_dragging.pageY0);
$(my_dragging.elem)
.offset({top: top, left: left});
}
function handle_mouseup(e){
$('body')
.off('mousemove', handle_dragging)
.off('mouseup', handle_mouseup);
}
$('body')
.on('mouseup', handle_mouseup)
.on('mousemove', handle_dragging);
}
$('.box').mousedown(handle_mousedown);
Thanks a lot.
<div class="box" style="height:100px;
width: 100px;
background: green;
position: absolute; /* or relative */
z-index: 1;">A</div>
<img src="https://i.ibb.co/L8hb78X/Final-Apple-i-Phone-13-Skin-Cutfile-Full-Wrap-Antenna-Display.png" width="300"
style="z-index: 2;
position: relative;
pointer-events: none;
user-select: none;">
The z-index together with the position attribute is for stacking context and allows placing them above each other.
The pointer-events: none; on the img is required to click through and allow the movement of the green container.
The user-select: none; is just cosmetic.

Positioning of element with JS transform properties (CSS get's overwritten by JS)

I'm trying to position two images on top of eachother, and having one of them rotate on scroll while the other one is not rotating - which works, except i'm unable to position and scale my elements in my CSS. As soon as i start scrolling, the image with the JS jumps into the corner while the other one remains where it is. I believe it's because my JS overwrites my CSS properties, but is there any way of working around this? Can i position my two elements while maintaining my JS?
var elem = document.getElementById("rotatelogo");
window.addEventListener('scroll', function() {
var value = window.scrollY * 0.25;
elem.style.transform = `translatex(-50%) translatey(-50%) rotate(${value}deg)`;
});
body {
height: 200vh;
background: darkblue;
}
.guide {
width:150px;
height:150px;
margin-top:50px;
margin-bottom:-300px;
margin-left:50px;
}
<div class="guide" style="position:relative">
<img src="http://jakobnatorp.com/wp-content/uploads/2021/10/ARROW.png" style="position:fixed;"/>
<img class="portfolio" id="rotatelogo" src="http://jakobnatorp.com/wp-content/uploads/2021/10/SELECTED-WORK-BEIGE.png" style="position:fixed"/>
</div>
Remove translate from your code.
var elem = document.getElementById("rotatelogo");
window.addEventListener('scroll', function() {
var value = window.scrollY * 0.25;
elem.style.transform = `rotate(${value}deg)`;
});
body {
height: 200vh;
background: darkblue;
}
.guide {
width:150px;
height:150px;
margin-top:50px;
margin-bottom:-300px;
margin-left:50px;
}
<div class="guide" style="position:relative">
<img src="http://jakobnatorp.com/wp-content/uploads/2021/10/ARROW.png" style="position:fixed;"/>
<img class="portfolio" id="rotatelogo" src="http://jakobnatorp.com/wp-content/uploads/2021/10/SELECTED-WORK-BEIGE.png" style="position:fixed"/>
</div>
I am not sure what you want to achieve by usingtranslatex(-50%) translatey(-50%), but this is causing the images center to be positioned on the top left corner of the parent element.
If you just use elem.style.transform = `rotate(${value}deg)`; it will rotate in place.

smooth horizontal scroll like k2.pl

I am trying to build a website with a horizontal scroll like this website k2.pl
Desc
i have made this code so far jquery animate and scroll to
// i am getting y and x axis and moving the whole page agains it
$('.scroll').animate( { scrollLeft: '+='+newScroll }
but what i made is that my script gets page X axis of website and move againts it but what i want is that when i hover on an element on the site it should scroll to the center like on this site k2.pl
can you guys suggest me some jquery plugin or that tell me how can improve it
If you check the website and move the mouse, you'll see that the element that you hover on doesn't really go to the center, the movement of the scroll is associated to the horizontal movement of the mouse and has nothing to do with hovering over the different list elements.
The idea is simple:
Have a container that occupies the whole width of the window and that has a overflow:hidden.
Inside that container have a second container with the same width as the list of elements.
Inside that container have a list of elements (or a series of inline elements) that occupy more than the width of the window.
When the mouse moves over the container, calculate the position of the mouse within the window, and scroll the container horizontally accordingly.
A basic version of it would be like this:
$(document).ready(function() {
$(".scroll").on("mousemove", function(e) {
var ww = $(window).width(); // window width
var uw = $(".scroll ul").width(); // ul width
var mp = e.clientX; // mouse position
var ms = uw - ww; // max scroll
var sc = - ms * mp / ww; // amount to be scrolled
$(".scroll > div").stop().animate({ left: sc +"px" }, 600, "easeOutCirc");
});
});
html, body {
margin:0;
padding:0;
border:0;
}
div.scroll {
width:100%;
height:400px;
overflow:hidden;
background:#f0f0f0;
position:relative;
}
div.scroll > div {
width:1400px;
position:absolute;
top:0;
left:0;
}
div.scroll > div > ul {
width:1400px;
margin:0;
padding:0;
}
div.scroll > div > ul > li {
display:inline-block;
float:left;
width:200px;
height:400px;
opacity:0.7;
transition:all 0.5s;
}
div.scroll > div > ul > li:hover {
opacity:1;
background:#6699cc;
}
div.scroll > div > ul > li:hover > span {
color:white;
background:black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<div class="scroll">
<div>
<ul>
<li><span>AAA</span></li>
<li><span>BBB</span></li>
<li><span>CCC</span></li>
<li><span>DDD</span></li>
<li><span>EEE</span></li>
<li><span>FFF</span></li>
<li><span>GGG</span></li>
</ul>
</div>
</div>
(Note: the code above may not work if the width of the window is larger than 1400px)
If you check the source code for k2.pl you'll see that they are using jQuery, jQuery UI, and Ariel Flesler's scrollTo plugin. You can see the code that controls the scrolling (in a different way to what I explained above) in the script.min.js file (search for mousemove.sapp).
As promised, here's my working solution. Alvaro's is great, but it uses the jQuery animate function which is a big no-no (it's about 10x slower than CSS transitions / the GSAP JavaScript animation library, for example), so I thought you might benefit from another implementation.
I personally like GSAP, which is super easy to pick up; that's why I've used it here. The rest is in native JS so you don't need all that library bloat:
var wrapper = document.getElementById("wrapper");
var tiles = document.getElementsByClassName("tile");
var tileWidth = tiles[0].getBoundingClientRect().width;
var containingWidth = tileWidth * tiles.length;
wrapper.addEventListener("mousemove", function(e){
var pos = (e.clientX / (wrapper.getBoundingClientRect().width)) * containingWidth - (tileWidth / 1.5);
TweenLite.to(wrapper, 1, { scrollLeft: pos, ease: Circ.easeOut })
});
html, body {
height: 100%;
overflow: hidden;
white-space: nowrap;
}
#wrapper {
height: 100%;
overflow-y: hidden;
overflow-x: auto;
}
.tile {
display: inline-block;
height: 100%;
width: 400px;
transition: background 0.2s ease-in-out;
}
.tile:hover {
background: transparent !important;
}
<div id="wrapper">
<div style="background: #6d8745" class="tile"></div>
<div style="background: #aa715a" class="tile"></div>
<div style="background: #a25fe3" class="tile"></div>
<div style="background: #8e84f5" class="tile"></div>
<div style="background: #259a5c" class="tile"></div>
<div style="background: #d5b67a" class="tile"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
The principles are essentially the same as Alvaro's. What you have to understand is that the width of the viewport will be a certain percentage of the width of the div / element which contains all of the "tiles" so, taking this into consideration, you have to calculate how to make them map at a 1:1 ratio. That calculation is represented by this line of code (the subtraction at the end is an offset):
var pos = (e.clientX / (wrapper.getBoundingClientRect().width)) * containingWidth - (tileWidth / 1.5);
Hope this helps!
Original codepen

I need the contents of an iframe to expand like an animation and fill up the entire screen and shrink to it original size

I need the contents of an iframe which has height of 100px(displays only part of iframe) to expand like an animation on read more button click,and fill up the entire screen(expands in all directions), and on clicking close button positioned on top of it, it needs to animate and shrink to it original size.
I found a fiddle that dooes something similar
http://jsfiddle.net/FP2DZ/.
But my issue is that my div cannot be absolutely positioned as I have contents underneath that and that gets affected if I make this one absolutely positioned.
Absolutely positioning rest of the contents also does not seem to me like a good solution
Code
<html>
<head>
<script type="text/javascript">
var isFullscreen = false;
function fullscreen(){
//var d = document.getElementById('controls').style;
var d = {};
var speed = 900;
if(!isFullscreen){ // MAXIMIZATION
/*comment to have smooth transition from centre but loose covering the header*/
//document.getElementById('controls').style.position= "absolute";
d.width = "100%";
d.height="100%";
//d.left="0%";
d.top="0px";
//d.margin="0 0 0 0";
$("#header").animate({
height: 0
}, speed);
$("#controls2").animate(d,speed);
isFullscreen = true;
}else{ // MINIMIZATION
d.width="300px";
d.height="100px";
d.margin="0 auto";
d.position="relative";
//d.top="+=30px";
/* comment to have smooth minimze transition but not be placed below header */
// document.getElementById('controls').style.position= "relative";
$("#header").animate({
height: 30
}, speed);
$("#controls2").animate(d,speed);
isFullscreen = false;
}
}
</script>
<style>
* { margin: 0 }
#controls {
width:100%;
height:100%;
margin: 0 auto;
display:block;
position:absolute;
left: 50%;
z-index:5;
}
#controls2 {
overflow:visible;
width: 300px;
height: 100px;
position: relative;
left: -50%;
background-color: green;
z-index:10;
}
</style>
</head>
<body>
<h1 id="header" align=center> Header (To be covered on Fullscreen) </h1>
<div id='controls' style="" align="center">
<div id='controls2'>
<input type='button' value='fullscreen' onclick='fullscreen();' /><br>
I am some centered shrink-to-fit content! <br />
tum te tum
</div>
</div>
</body>
Probably the easiest way is to utilize the .animate({}) method in Jquery.
Check out this fiddle: http://jsfiddle.net/cm6v7bca/2/
$("#clickhere").on("click", function () {
$("#myframe").animate({
width: "200px",
height: "200px"
}, 1000);
});
.animate({}) allows you to change the css properties and then smoothly animates the changes onto the element. There are several different parameters you can pass. In the fiddle you'll see that I passed "1000" - that's the duration for the animation to complete in ms.
You can read more about the parameters and the method here: https://api.jquery.com/animate/
That really helps. But then the iframe needs to cover rest of the contents in the page and overlay them, Thats seems possible only if iframe is absolutely positioned. But there is so much dynamic content in the page, I do not want to absolute position the iframe.
http://jsfiddle.net/CvhkM/2833/
this is like what I want just that am not able to absolute position.
JS:
$(this).stop().animate({
left: parseInt(this.style.left)-100,
top: parseInt(this.style.top)-100,
width: parseInt(this.style.width)+200,
height: parseInt(this.style.height)+200
}, 300);

How to scroll diagonally with jQuery or Javascript

Are there projects or plugins that utilize javascript or jQuery to scroll diagonally?
e.g. when you scroll down your content, It would be pulled at the top-left corner of the browser; and when you scroll up your content would be pulled at the bottom-right of the corner.
I see some similar project/website that they animate their elements when scroll. Most of the site that use javascript has some lags with the effect though. Another i've seen is using html5 + parallax effect similar to "Nike a Better World" (http://coding.smashingmagazine.com/2011/07/12/behind-the-scenes-of-nike-better-world/)
Can you point me where can be a good starting point? Basically I want to scroll the items diagonally left-or-right. If this can be done plainly in HTML5, I would highly consider that since I feel It would have less lag or less calculation being done.
I was able to create the effect that you wanted in a fiddle:
http://jsfiddle.net/t0nyh0/8QTYt/36/
Important Tidbits
A "fixed" full-width and full-height wrapper that holds all your moving elements help you animate the div more consistently based on the scroll position (which is effectively the "keyframe" number).
scroll_max, wrapper_width, and wrapper_height helps normalize the dimensions of wrapper. I.e. the very bottom of the scroll corresponds to the bottom/right of the wrapper, and the very top of the scroll corresponds with the top/left of the wrapper.
Set your body's height to whatever number of "keyframes" that you want.
To move from top left to bottom right on going down, adjust the top and left properties. For the reverse, adjust the bottom and right properties. Of course, you will need to formulate your own calculations for more complex animations, but know that doing $window.scrollTop() will give you the "keyframe" number.
HTML
<div id="wrapper">
<div id="a">
<h1>Meats</h1>
</div>
<div id="b">
<h1>Veggies</h1>
<hr/>
<p>Veggies sunt bona vobis, proinde vos postulo esse magis daikon epazote peanut chickpea bamboo shoot rutabaga maize radish broccoli rabe lotus root kohlrabi napa cabbage courgette mustard squash mung bean.</p>
</div>
</div>​
CSS
body
{
height: 1000px; // 1000 keyframes
}
#wrapper
{
width: 100%;
height: 100%;
position: fixed;
border: 2px solid navy;
overflow:hidden;
}
#a {
position:absolute;
background-color: #daf1d7;
width: 300px;
height: 300px;
}
#b
{
position: absolute;
background-color: #d2d0ee;
width: 200px;
height: 200px;
bottom: 0px;
right: 0px;
}
​
Javscript
var $window = $(window);
var $a = $('#a');
var $b = $('#b');
var scroll_max = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var wrapper_height = $('#wrapper').height();
var wrapper_width = $('#wrapper').width();
$window.scroll(function() {
console.log(scroll_max);
$a.css({
'top': ($window.scrollTop() / scroll_max) * wrapper_height,
'left': ($window.scrollTop() / scroll_max) * wrapper_width
});
$b.css({
'bottom': ($window.scrollTop() / scroll_max) * wrapper_height,
'right': ($window.scrollTop() / scroll_max) * wrapper_width
});
});​
Here's a potential solution for you (jsFiddle example):
jQuery:
$(window).scroll(function() {
console.log($(this).scrollTop());
$('#a').css({
'width': $(this).scrollTop(),
'height': $(this).scrollTop()
});
$('#b').css({
'width': 300-$(this).scrollTop(),
'height': 300-$(this).scrollTop()
});
});
CSS:
#a,#b {
position:fixed;
background: orange;
}
#a{
top:0;
left:0;
}
#b {
bottom:0;
right:0;
width:300px;
height:300px;
}
body {
height:2000px;
}
HTML:
<div id="a"></div>
<div id="b"></div>

Categories