How to make two divs resizable only by width in vuejs - vue.js

I want to create two divs and make them re-sizable with respect to each others width in VueJS
$(function() {
var A = parseInt($('#A').width(), 10),
B = parseInt($('#B').width(), 10),
Z = parseInt($('#Z').width(), 10),
minw = parseInt((A + B + Z) * 10 / 100, 10),
offset = $('#container').offset(),
splitter = function(event, ui) {
var aw = parseInt(ui.position.left),
bw = A + B - aw;
//set widths and information...
$('#A').css({
width: aw
}).children().text(aw);
$('#B').css({
width: bw
}).children().text(bw);
};
$('#Z').draggable({
axis: 'x',
containment: [
offset.left + minw,
offset.top,
offset.left + A + B - minw,
offset.top + $('#container').height()
],
drag: splitter
});
//information...
$('#width').text(A + B + Z);
$('#A div').text(A);
$('#B div').text(B);
});
#container {
width: 90%;
height: 100px;
margin: 0 auto;
position: relative;
}
#A,
#B,
#Z {
position: absolute;
top: 0;
height: 100%;
}
#A {
left: 0;
width: 39%;
background-color: #ccffcc;
}
#B {
right: 0;
width: 59%;
background-color: #ccccff;
}
#Z {
left: 39%;
width: 2%;
background-color: #cc0000;
cursor: move;
}
#A div,
#B div {
position: absolute;
top: 40%;
left: 0;
width: 100%;
text-align: center;
}
#info {
text-align: center;
line-height: 2em;
}
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id='info'>container width : <span id='width'></span></div>
<div id='container'>
<div id='A'>
<div>a</div>
</div>
<div id='B'>
<div>b</div>
</div>
<div id='Z'></div>
</div>

You are mixing Vue with jQuery, so when your jQuery code runs the Vue app might not be ready.
A solution could be to wrap the draggable library in a <Draggable> component and use refs to access the DOM nodes from the mounted hook in the Vue component.

Related

Animate width of div bound to data property in Vue

I have this progress bar div, whichs width is bound to the data property result and changes accordingly. At the moment it still jumps, but I want to animate it. I thought of tracking the old and the new Value and injecting it in the css with css variables or just using a setInterval method, but tracking the 2 values seems to get quite complicated and it seemed like a overkill for me. Does anyone have an easier idea?
<template>
<div class="progress">
<div class="progress-value" :style="{ 'width': result + '%' }">
<h2>{{ result }}%</h2>
</div>
</div>
</template>
<script>
export default {
props: ["result"],
};
</script>
<style scoped>
.progress {
background: #ccc;
border-radius: 100px;
position: relative;
padding: 5px 5px;
margin: 5px 5px;
height: 40px;
width: auto;
}
.progress-value {
animation: load 3s normal forwards;
border-radius: 100px;
background: #fff;
height: 30px;
text-align: center;
}
/* #keyframes load {
0% {
width:
}
100% {
width:
}
} */
</style>
Add css transition like this:
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 1s;
And fix the binding:
<div class="progress-value" :style="'width: ' + result + '%'">
See this example
<template>
<div class="progress">
<div class="progress-value" :style="'width: ' + result + '%'">
<h2>{{ result }}%</h2>
</div>
</div>
</template>
<script>
export default {
data () {
return {
result: 5
}
},
mounted() {
this.increment()
},
methods: {
increment() {
this.result += 10
if (this.result < 95) {
setTimeout(this.increment, 1000)
}
}
}
}
</script>
<style scoped>
.progress {
background: #ccc;
border-radius: 100px;
position: relative;
padding: 5px 5px;
margin: 5px 5px;
height: 40px;
width: auto;
}
.progress-value {
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 1s;
background: #fff;
height: 30px;
text-align: center;
}
</style>

How to pass dynamic content to Vue v-bind:style on #mousemove method

<div
class="BgContainer"
#mousemove="mouseMove"
v-bind:style="{
transform: 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)',
}"
>
I am trying to update a transform: matrix3d() style on mouseMove function
methods: {
mouseMove(event) {
console.log(event.clientX, event.clientY)
},
},
trying to learn Vue (Nuxt.js) and I am wondering what would be the best way to update this transform based on mouse position and update the transform on mouseMove. How can I achieve something like this where newX and newY are dynamic based on mouse position?
v-bind:style="{
transform: 'matrix3d(1.025,0,0,"newX",0,1.025,0,"newY",0,0,1,0,0,0,0,1)',
}"
EDIT - whole vue file
<template>
<div class="prop_scroller">
<div
class="BgContainer"
#mousemove="mouseMove"
v-bind:style="{
transform:
'matrix3d(1.025,0,0,' +
newX+
',0,1.025,0,' +
newY +
',0,0,1,0,0,0,0,1)',
}"
>
<i class="sacbg"> </i>
<div class="after"></div>
</div>
</div>
</template>
<script>
import VanillaTilt from 'vanilla-tilt'
export default {
data: function () {
newX: 0
newY: 0
},
mounted: function () {
// VanillaTilt.init(this.$refs.bg)
console.log(this.$refs)
},
methods: {
mouseMove(event) {
console.log(event.clientX, event.clientY)
},
},
}
</script>
<style lang="scss" scoped>
.prop_scroller {
position: absolute;
top: -50px;
right: -70px;
bottom: -60px;
left: -50px;
overflow: scroll;
}
.js-tilt-glare-inner {
backface-visibility: hidden;
}
.BgContainer {
height: 100%;
width: 100%;
overflow: hidden;
position: absolute;
// object-fit: cover;
z-index: 300;
backface-visibility: hidden;
transform-style: preserve-3d;
top: 0;
right: 0;
bottom: 0;
left: 0;
i {
position: absolute !important;
top: -70px !important;
right: -70px !important;
bottom: -60px !important;
left: -60px !important;
background-size: cover;
background-position: center;
background-image: url('~static/mural-bg.jpg');
}
.MuralBg {
// animation: 1s appear;
margin: auto;
width: 100vw;
height: auto;
}
.after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(26, 33, 42, 0.2);
animation: 1.2s fadeBgOut;
}
}
#keyframes fadeBgOut {
0% {
background-color: rgba(26, 33, 42, 0.8);
}
100% {
background-color: rgba(26, 33, 42, 0.2);
}
}
</style>
Try out with string template literals :
v-bind:style="{
transform: `matrix3d(1.025,0,0,${newX},0,1.025,0,${newY},0,0,1,0,0,0,0,1)`,
}"
or by concatenation :
v-bind:style="{
transform: 'matrix3d(1.025,0,0,'+newX+',0,1.025,0,'+newY+',0,0,1,0,0,0,0,1)',
}"
and your data property should be a function that returns an object :
<script>
import VanillaTilt from 'vanilla-tilt'
export default {
data: function () {
return {
newX: 0
newY: 0
}
},
mounted: function () {
// VanillaTilt.init(this.$refs.bg)
console.log(this.$refs)
},
methods: {
mouseMove(event) {
console.log(event.clientX, event.clientY)
this.newX=event.clientX;
this.newY=event.clientY;
},
},
}
</script>

vue.js, vuetify scroll event not firing when using css scroll snap

UPDATE dropped this approach and went with vue-awesome-swiper script
I"m been stuck on this for days. Basically I want to use css scroll snap and I want to monitor scroll also.
In this basic example with just javascript it works fine scroll event fires and div snaps with css. The other pen below with vue.js does not and that is my problem. Losing hair about this... any help appreciated!
https://codepen.io/travis-pancakes/pen/pGYOZK?editors=0011
var i = 0;
function Onscrollfnction(event) { document.getElementById("demo").innerHTML = i;
i = i + 1;
};
/* setup */
html, body, .holster {
height: 100%;
}
.holster {
display: flex;
align-items: center;
justify-content: space-between;
flex-flow: column nowrap;
font-family: monospace;
}
.container {
display: flex;
overflow: auto;
outline: 1px dashed lightgray;
flex: none;
}
.container.x {
width: 100%;
height: 128px;
flex-flow: row nowrap;
}
.container.y {
width: 256px;
height: 256px;
flex-flow: column nowrap;
}
/* scroll-snap */
.x.mandatory-scroll-snapping {
scroll-snap-type: x mandatory;
}
.y.mandatory-scroll-snapping {
scroll-snap-type: y mandatory;
}
.x.proximity-scroll-snapping {
scroll-snap-type: x proximity;
}
.y.proximity-scroll-snapping {
scroll-snap-type: y proximity;
}
.container > div {
text-align: center;
scroll-snap-align: center;
flex: none;
}
.x.container > div {
line-height: 128px;
font-size: 64px;
width: 100%;
height: 128px;
}
.y.container > div {
line-height: 256px;
font-size: 128px;
width: 256px;
height: 256px;
}
/* appearance fixes */
.y.container > div:first-child {
line-height: 1.3;
font-size: 64px;
}
/* coloration */
.container > div:nth-child(even) {
background-color: #87EA87;
}
.container > div:nth-child(odd) {
background-color: #87CCEA;
}
<div><p>Scrolled <span id="demo">0</span> times.</p></div>
<div class="container y mandatory-scroll-snapping" onscroll="Onscrollfnction();" dir="ltr">
<div>Y Mand. LTR</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
The vue.js, vuetify version does not
https://codepen.io/travis-pancakes/pen/BMbqPq?editors=1111
new Vue({
el: '#app',
data: function(){
return {
i: 0
}
},
created () {
},
methods: {
Onscrollfnction (event) {
document.getElementById("demo").innerHTML = this.i;
this.i = this.i + 1;
console.log('i ', i)
}
}
});
/* setup */
html, body, .holster {
height: 100%;
}
.holster {
display: flex;
align-items: center;
justify-content: space-between;
flex-flow: column nowrap;
font-family: monospace;
}
.container {
display: flex;
overflow: auto;
outline: 1px dashed lightgray;
flex: none;
}
.container.x {
width: 100%;
height: 128px;
flex-flow: row nowrap;
}
.container.y {
width: 256px;
height: 256px;
flex-flow: column nowrap;
}
/* scroll-snap */
.x.mandatory-scroll-snapping {
scroll-snap-type: x mandatory;
}
.y.mandatory-scroll-snapping {
scroll-snap-type: y mandatory;
}
.x.proximity-scroll-snapping {
scroll-snap-type: x proximity;
}
.y.proximity-scroll-snapping {
scroll-snap-type: y proximity;
}
.container > div {
text-align: center;
scroll-snap-align: center;
flex: none;
}
.x.container > div {
line-height: 128px;
font-size: 64px;
width: 100%;
height: 128px;
}
.y.container > div {
line-height: 256px;
font-size: 128px;
width: 256px;
height: 256px;
}
/* appearance fixes */
.y.container > div:first-child {
line-height: 1.3;
font-size: 64px;
}
/* coloration */
.container > div:nth-child(even) {
background-color: #87EA87;
}
.container > div:nth-child(odd) {
background-color: #87CCEA;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<!-- could use v-scroll="Onscrollfnction" with vuetify" --->
<div class="container y mandatory-scroll-snapping"
v-on:scroll.native="Onscrollfnction" dir="ltr">
<div>Y Mand. LTR</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
<p>Scrolled <span id="demo">0</span> times.</p>
</div>
</div>
vue-awesome-swiper does the functionality I'm going for

Vue I want an image to follow the mouse

I am having trouble with a Vue component https://jsfiddle.net/shawnswebsites/fep1p02c/20/. I have a div in the component and when the user's mouse enters the div I want an image to be shown and I want the image to follow the mouse.
new Vue({
el: '#app',
data: {
showImage: false,
page: {
left : 0,
top: 0
},
},
methods: {
onMouseMove(e) {
console.log('page x: ' + this.page.left);
this.page.left = e.pageX;
this.page.top = e.pageY;
}
}
})
.container {
height: 400px;
width: 400px;
border: 1px solid #FFF;
background-color: grey;
margin: 40px;
}
.image {
position: absolute;
z-index: 1000;
overflow:hidden;
}
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div class="container"
#mouseenter="showImage = true"
#mousemove.self="onMouseMove($event)"
#mouseleave="showImage = false">
</div>
<img v-show="showImage" class="image" src="http://via.placeholder.com/350x150" :style="{ left: page.left + 'px', top: page.top + 'px' }">
</div>
I use a #mouseenter to show the image and #mouseleave to hide the image. However, #mouseleave is still being called as I scroll over the div, which is causing the image to blink on and off. Can any help?
As said Oxcarga in the comment below you need to add pointer-events: none; to your image style:
.image {
position: absolute;
z-index: 1000;
overflow:hidden;
pointer-events: none;
}

Simple Gallery Slider

I'm trying to create a simple slider using divs and javascript. I set up a div with six images and an arrow that movies the containder holding the images 528px (the width of each image) every time it's clicked. When I reach the begining or end of the gallery, I want the respective arrow button to fade out so that the user won't keep pressing next/prev.
Any help is appreciated.
JAVASCRIPT
$("#btn-gallery-next").click(function(){
$("div#gallery li").not(this).removeClass('clicked');
$("div#gallery-slide").animate({left:"-=528px"});
if($("div#gallery-slide").position().left < -3168)
{
$("#btn-gallery-next").fadeOut();
}
else {
$("#btn-gallery-next").fadeIn();
}
});
$("#btn-gallery-prev").click(function(){
$("div#gallery li").not(this).removeClass('clicked');
$("div#gallery-slide").animate({left:"+=528px"});
if($("div#gallery-slide").position().left > 0)
{
$("#btn-gallery-prev").fadeOut();
}
else {
$("#btn-gallery-prev").fadeIn();
}
});
HTML
<div id="gallery-slide">
<img class="gallery-img" src="_/img/gallery/img1.jpg" alt="" />
<img class="gallery-img" src="_/img/gallery/img2.jpg" alt="" />
<img class="gallery-img" src="_/img/gallery/img3.jpg" alt="" />
<img class="gallery-img" src="_/img/gallery/img4.jpg" alt="" />
<img class="gallery-img" src="_/img/gallery/img5.jpg" alt="" />
<img class="gallery-img" src="_/img/gallery/img6.jpg" alt="" />
</div>
Try flex slider from woothemes, it have all ur needs.
Why not use a slider library like Owl Slider? It comes with lots of options and configurations. It is super simple to integrate into any project.
Example #1 www.midwestgathering.com/#galleries
Example #2 www.owlgraphic.com/owlcarousel/demos/images.html
Another option is jcarousel. The basic slider is shown with an example that makes the left next button inactive until the user slides to the right, then once the user gets to the end of the gallery the right next button becomes inactive:
JS
(function($) {
$(function() {
$('.jcarousel').jcarousel();
$('.jcarousel-control-prev')
.on('jcarouselcontrol:active', function() {
$(this).removeClass('inactive');
})
.on('jcarouselcontrol:inactive', function() {
$(this).addClass('inactive');
})
.jcarouselControl({
target: '-=1'
});
$('.jcarousel-control-next')
.on('jcarouselcontrol:active', function() {
$(this).removeClass('inactive');
})
.on('jcarouselcontrol:inactive', function() {
$(this).addClass('inactive');
})
.jcarouselControl({
target: '+=1'
});
$('.jcarousel-pagination')
.on('jcarouselpagination:active', 'a', function() {
$(this).addClass('active');
})
.on('jcarouselpagination:inactive', 'a', function() {
$(this).removeClass('active');
})
.jcarouselPagination();
});
})(jQuery);
CSS
.jcarousel-wrapper {
margin: 20px auto;
position: relative;
border: 10px solid #fff;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0 0 2px #999;
-moz-box-shadow: 0 0 2px #999;
box-shadow: 0 0 2px #999;
}
.jcarousel-wrapper .photo-credits {
position: absolute;
right: 15px;
bottom: 0;
font-size: 13px;
color: #fff;
text-shadow: 0 0 1px rgba(0, 0, 0, 0.85);
opacity: .66;
}
.jcarousel-wrapper .photo-credits a {
color: #fff;
}
/** Carousel **/
.jcarousel {
position: relative;
overflow: hidden;
width: 600px;
height: 400px;
}
.jcarousel ul {
width: 20000em;
position: relative;
list-style: none;
margin: 0;
padding: 0;
}
.jcarousel li {
float: left;
}
/** Carousel Controls **/
.jcarousel-control-prev,
.jcarousel-control-next {
position: absolute;
top: 200px;
width: 30px;
height: 30px;
text-align: center;
background: #4E443C;
color: #fff;
text-decoration: none;
text-shadow: 0 0 1px #000;
font: 24px/27px Arial, sans-serif;
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
border-radius: 30px;
-webkit-box-shadow: 0 0 2px #999;
-moz-box-shadow: 0 0 2px #999;
box-shadow: 0 0 2px #999;
}
.jcarousel-control-prev {
left: -50px;
}
.jcarousel-control-next {
right: -50px;
}
.jcarousel-control-prev:hover span,
.jcarousel-control-next:hover span {
display: block;
}
.jcarousel-control-prev.inactive,
.jcarousel-control-next.inactive {
opacity: .5;
cursor: default;
}
/** Carousel Pagination **/
.jcarousel-pagination {
position: absolute;
bottom: 0;
left: 15px;
}
.jcarousel-pagination a {
text-decoration: none;
display: inline-block;
font-size: 11px;
line-height: 14px;
min-width: 14px;
background: #fff;
color: #4E443C;
border-radius: 14px;
padding: 3px;
text-align: center;
margin-right: 2px;
opacity: .75;
}
.jcarousel-pagination a.active {
background: #4E443C;
color: #fff;
opacity: 1;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.75);
}
You can find documentation for jcarousel at www.sorgalla.com/jcarousel/docs/.
see demo - http://codepen.io/vsync/pen/waKju?editors=011
javascript
/**
* Slider - loops over images
* SEP 2014
* By - Yair Even-Or
*/
var Slider = function(elm, prev, next){
var that = this;
this.locked = false;
this.slider = elm;
this.children = this.slider.children;
this.itemWidth = this.children[0].clientWidth;
this.preloadImages();
next && next.addEventListener('click', function(){ that.move('next') });
prev && prev.addEventListener('click', function(){ that.move('prev') });
}
Slider.prototype = {
move : function(dir){
var that = this,
itemToMove;
if( this.locked ){
this.locked.removeAttribute('style');
this.slider.appendChild(this.locked);
clearTimeout(this.timer);
moveToEnd();
}
// do nothing if there are no items
if( this.children.length < 2 )
return false;
itemToMove = this.children[0];
this.locked = itemToMove;
if( dir == 'next' )
itemToMove.style.marginLeft = -this.itemWidth + 'px';
else{
itemToMove = this.children[this.children.length-1];
itemToMove.style.marginLeft = -this.itemWidth + 'px';
this.slider.insertBefore(itemToMove, this.children[0]);
setTimeout(function(){
itemToMove.removeAttribute('style');
},50);
this.preloadImages();
this.locked = false;
}
// move the child to the end of the items' list
if( dir == 'next' )
this.timer = setTimeout(moveToEnd, 420);
function moveToEnd(el){
itemToMove = el || itemToMove;
if( !itemToMove ) return;
itemToMove.removeAttribute('style');
that.slider.appendChild(itemToMove);
that.locked = false;
that.preloadImages();
}
},
preloadImages : function(){
this.lazyload(this.children[1].getElementsByTagName('img')[0] );
this.lazyload(this.children[this.children.length-1].getElementsByTagName('img')[0] );
},
// lazy load image
lazyload : function(img){
var lazy = img.getAttribute('data-src');
if( lazy ){
img.src = lazy;
img.removeAttribute('data-src');
}
}
}
// HOW TO USE /////////////////
var sliderElm = document.querySelector('.content'),
next = document.querySelector('.next'),
prev = document.querySelector('.prev'),
slider = new Slider(sliderElm, prev, next);
HTML (JADE syntax)
.slider
a.arrow.next
a.arrow.prev
ul.content
li
img(src='image1.jpg')
li
img(src='image2.jpg')
li
img(src='image3.jpg')
li
img(src='image4.jpg')