Reputation: 505
I have to create such a slider on the site I design. Given JavaScript code, how can I design it in a clickable way? i want to make like drag and drop thing And can be used on all sites, especially small sizes such as mobile and tablet. This JavaScript code only organizes the float mode and is ineffective if clicked except in small sizes. How can we do this?
Thank you in advance for your cooperation.
class BeforeAfter {
constructor(enteryObject) {
const beforeAfterContainer = document.querySelector(enteryObject.id);
const before = beforeAfterContainer.querySelector('.bal-before');
const beforeText = beforeAfterContainer.querySelector('.bal-beforePosition');
const afterText = beforeAfterContainer.querySelector('.bal-afterPosition');
const handle = beforeAfterContainer.querySelector('.bal-handle');
var widthChange = 0;
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
window.onresize = function () {
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
}
before.setAttribute('style', "width: 50%;");
handle.setAttribute('style', "left: 50%;");
//touch screen event listener
beforeAfterContainer.addEventListener("touchstart", (e) => {
beforeAfterContainer.addEventListener("touchmove", (e2) => {
let containerWidth = beforeAfterContainer.offsetWidth;
let currentPoint = e2.changedTouches[0].clientX;
let startOfDiv = beforeAfterContainer.offsetLeft;
let modifiedCurrentPoint = currentPoint - startOfDiv;
if (modifiedCurrentPoint > 10 && modifiedCurrentPoint < beforeAfterContainer.offsetWidth - 10) {
let newWidth = modifiedCurrentPoint * 100 / containerWidth;
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index: 1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
});
});
//mouse move event listener
beforeAfterContainer.addEventListener('mousemove', (e) => {
let containerWidth = beforeAfterContainer.offsetWidth;
widthChange = e.offsetX;
let newWidth = widthChange * 100 / containerWidth;
if (e.offsetX > 10 && e.offsetX < beforeAfterContainer.offsetWidth - 10) {
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index:" + "1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
})
}
}
new BeforeAfter({
id: '#one'
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.top-title {
text-align: center;
font-family: Arial, Helvetica, sans-serif;
margin: 1rem 0.5rem;
}
.top-title span {
font-style: italic;
font-size: 1.5rem;
}
@media all and (max-width: 479px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 700px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (max-width: 599px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 800px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 480px) and (max-width: 768px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 1000px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 768px) and (max-width: 959px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 1100px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 960px) and (max-width: 1199px) {
.mainSection {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 500px;
padding: 10px;
}
.bal-container {
margin: 0 10px;
}
}
@media all and (min-width: 1199px) {
.mainSection {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 500px;
padding: 10px;
}
.bal-container {
margin: 0 10px;
}
}
/* Before After Container */
.bal-container {
position: relative;
width: 100%;
height: 100%;
cursor: grab;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.bal-after {
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.bal-before {
display: block;
position: absolute;
top: 0;
/* right: 0; */
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 15;
overflow: hidden;
}
.bal-before-inset {
position: absolute;
top: 0;
bottom: 0;
left: 0;
}
.bal-after img,
.bal-before img {
object-fit: cover;
position: absolute;
width: 100%;
height: 100%;
object-position: 50% 50%;
top: 0;
bottom: 0;
left: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.bal-beforePosition {
background: #121212;
color: #fff;
left: 0;
pointer-events: none;
border-radius: 0.2rem;
padding: 2px 10px;
}
.bal-afterPosition {
background: #121212;
color: #fff;
right: 0;
pointer-events: none;
border-radius: 0.2rem;
padding: 2px 10px;
}
.beforeLabel {
position: absolute;
bottom: 0;
margin: 1rem;
font-size: 1em;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.afterLabel {
position: absolute;
bottom: 0;
margin: 1rem;
font-size: 1em;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
/* handle and arrow */
.bal-handle {
height: 41px;
width: 41px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -20px;
margin-top: -21px;
border: 2px solid #fff;
border-radius: 1000px;
z-index: 20;
pointer-events: none;
box-shadow: 0 0 10px rgb(12, 12, 12);
}
.handle-left-arrow,
.handle-right-arrow {
width: 0;
height: 0;
border: 6px inset transparent;
position: absolute;
top: 50%;
margin-top: -6px;
}
.handle-left-arrow {
border-right: 6px solid #fff;
left: 50%;
margin-left: -17px;
}
.handle-right-arrow {
border-left: 6px solid #fff;
right: 50%;
margin-right: -17px;
}
.bal-handle::before {
bottom: 50%;
margin-bottom: 20px;
box-shadow: 0 0 10px rgb(12, 12, 12);
}
.bal-handle::after {
top: 50%;
margin-top: 20.5px;
box-shadow: 0 0 5px rgb(12, 12, 12);
}
.bal-handle::before,
.bal-handle::after {
content: " ";
display: block;
width: 2px;
background: #fff;
height: 9999px;
position: absolute;
left: 50%;
margin-left: -1.5px;
}
<div class="mainSection">
<div id="one" class="bal-container">
<div class="bal-before">
<div class="bal-before-inset">
<img src="https://farm2.staticflickr.com/1638/26145024230_06acd55d1b_b.jpg">
<div class="bal-afterPosition afterLabel">
before
</div>
</div>
</div>
<div class="bal-after">
<img src="https://farm2.staticflickr.com/1663/25814974803_d4c55ff708_b.jpg">
<div class="bal-afterPosition afterLabel">
After
</div>
</div>
<div class="bal-handle">
<span class=" handle-left-arrow"></span>
<span class="handle-right-arrow"></span>
</div>
</div>
</div>
Upvotes: 0
Views: 92
Reputation: 505
This code works by dragging and dropping with mousedown and mouseup events.
window.onload = function(){
class BeforeAfter {
constructor(enteryObject) {
const beforeAfterContainer = document.querySelector(enteryObject.id);
const before = beforeAfterContainer.querySelector('.bal-before');
const beforeText = beforeAfterContainer.querySelector('.bal-beforePosition');
const afterText = beforeAfterContainer.querySelector('.bal-afterPosition');
const handle = beforeAfterContainer.querySelector('.bal-handle');
var widthChange = 0;
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
window.onresize = function() {
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
}
before.setAttribute('style', "width: 50%;");
handle.setAttribute('style', "left: 50%;");
//touch screen event listener
beforeAfterContainer.addEventListener("touchstart", (e) => {
beforeAfterContainer.addEventListener("touchmove", (e2) => {let containerWidth = beforeAfterContainer.offsetWidth;
let currentPoint = e2.changedTouches[0].clientX;
let startOfDiv = beforeAfterContainer.offsetLeft;
let modifiedCurrentPoint = currentPoint - startOfDiv;
if (modifiedCurrentPoint > 10 && modifiedCurrentPoint < beforeAfterContainer.offsetWidth - 10) {
let newWidth = modifiedCurrentPoint * 100 / containerWidth;
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index: 1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
});
});
//toggle active state
beforeAfterContainer.addEventListener('mousedown', (e) => {
beforeAfterContainer.classList.add("active");
});
//toggle de-active state
beforeAfterContainer.addEventListener('mouseup', (e) => {
beforeAfterContainer.classList.remove("active");
});
//mouse move event listener
beforeAfterContainer.addEventListener('mousemove', (e) => {
if (beforeAfterContainer.classList.contains("active")) {
let containerWidth =beforeAfterContainer.offsetWidth;
widthChange = e.offsetX;
let newWidth = widthChange * 100 / containerWidth;
if (e.offsetX > 10 && e.offsetX < beforeAfterContainer.offsetWidth - 10) {
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index:" + "1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
}
});
}
}
new BeforeAfter({
id: '#one'
});
}
Upvotes: 0
Reputation: 34177
I've added a toggle click action to the whole element to turn dragging on and off.
Click the picture to enable the slider.
class BeforeAfter {
constructor(enteryObject) {
const beforeAfterContainer = document.querySelector(enteryObject.id);
const before = beforeAfterContainer.querySelector('.bal-before');
const beforeText = beforeAfterContainer.querySelector('.bal-beforePosition');
const afterText = beforeAfterContainer.querySelector('.bal-afterPosition');
const handle = beforeAfterContainer.querySelector('.bal-handle');
var widthChange = 0;
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
window.onresize = function() {
beforeAfterContainer.querySelector('.bal-before-inset').setAttribute("style", "width: " + beforeAfterContainer.offsetWidth + "px;")
}
before.setAttribute('style', "width: 50%;");
handle.setAttribute('style', "left: 50%;");
//touch screen event listener
beforeAfterContainer.addEventListener("touchstart", (e) => {
beforeAfterContainer.addEventListener("touchmove", (e2) => {
let containerWidth = beforeAfterContainer.offsetWidth;
let currentPoint = e2.changedTouches[0].clientX;
let startOfDiv = beforeAfterContainer.offsetLeft;
let modifiedCurrentPoint = currentPoint - startOfDiv;
if (modifiedCurrentPoint > 10 && modifiedCurrentPoint < beforeAfterContainer.offsetWidth - 10) {
let newWidth = modifiedCurrentPoint * 100 / containerWidth;
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index: 1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
});
});
//toggle active state
beforeAfterContainer.addEventListener('click', (e) => {
beforeAfterContainer.classList.toggle("active");
});
//mouse move event listener
beforeAfterContainer.addEventListener('mousemove', (e) => {
if (beforeAfterContainer.classList.contains("active")) {
let containerWidth = beforeAfterContainer.offsetWidth;
widthChange = e.offsetX;
let newWidth = widthChange * 100 / containerWidth;
if (e.offsetX > 10 && e.offsetX < beforeAfterContainer.offsetWidth - 10) {
before.setAttribute('style', "width:" + newWidth + "%;");
afterText.setAttribute('style', "z-index:" + "1;");
handle.setAttribute('style', "left:" + newWidth + "%;");
}
}
});
}
}
new BeforeAfter({
id: '#one'
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.top-title {
text-align: center;
font-family: Arial, Helvetica, sans-serif;
margin: 1rem 0.5rem;
}
.top-title span {
font-style: italic;
font-size: 1.5rem;
}
@media all and (max-width: 479px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 700px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (max-width: 599px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 800px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 480px) and (max-width: 768px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 1000px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 768px) and (max-width: 959px) {
.mainSection {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 1100px;
padding: 10px;
}
.bal-container {
margin: 10px 0;
}
}
@media all and (min-width: 960px) and (max-width: 1199px) {
.mainSection {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 500px;
padding: 10px;
}
.bal-container {
margin: 0 10px;
}
}
@media all and (min-width: 1199px) {
.mainSection {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: stretch;
align-content: stretch;
width: 100%;
height: 500px;
padding: 10px;
}
.bal-container {
margin: 0 10px;
}
}
/* Before After Container */
.bal-container {
position: relative;
width: 100%;
height: 100%;
cursor: grab;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.bal-after {
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.bal-before {
display: block;
position: absolute;
top: 0;
/* right: 0; */
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 15;
overflow: hidden;
}
.bal-before-inset {
position: absolute;
top: 0;
bottom: 0;
left: 0;
}
.bal-after img,
.bal-before img {
object-fit: cover;
position: absolute;
width: 100%;
height: 100%;
object-position: 50% 50%;
top: 0;
bottom: 0;
left: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.bal-beforePosition {
background: #121212;
color: #fff;
left: 0;
pointer-events: none;
border-radius: 0.2rem;
padding: 2px 10px;
}
.bal-afterPosition {
background: #121212;
color: #fff;
right: 0;
pointer-events: none;
border-radius: 0.2rem;
padding: 2px 10px;
}
.beforeLabel {
position: absolute;
bottom: 0;
margin: 1rem;
font-size: 1em;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.afterLabel {
position: absolute;
bottom: 0;
margin: 1rem;
font-size: 1em;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
/* handle and arrow */
.bal-handle {
height: 41px;
width: 41px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -20px;
margin-top: -21px;
border: 2px solid #fff;
border-radius: 1000px;
z-index: 20;
pointer-events: none;
box-shadow: 0 0 10px rgb(12, 12, 12);
}
.handle-left-arrow,
.handle-right-arrow {
width: 0;
height: 0;
border: 6px inset transparent;
position: absolute;
top: 50%;
margin-top: -6px;
}
.handle-left-arrow {
border-right: 6px solid #fff;
left: 50%;
margin-left: -17px;
}
.handle-right-arrow {
border-left: 6px solid #fff;
right: 50%;
margin-right: -17px;
}
.bal-handle::before {
bottom: 50%;
margin-bottom: 20px;
box-shadow: 0 0 10px rgb(12, 12, 12);
}
.bal-handle::after {
top: 50%;
margin-top: 20.5px;
box-shadow: 0 0 5px rgb(12, 12, 12);
}
.bal-handle::before,
.bal-handle::after {
content: " ";
display: block;
width: 2px;
background: #fff;
height: 9999px;
position: absolute;
left: 50%;
margin-left: -1.5px;
}
<div class="mainSection">
<div id="one" class="bal-container">
<div class="bal-before">
<div class="bal-before-inset">
<img src="https://farm2.staticflickr.com/1638/26145024230_06acd55d1b_b.jpg">
<div class="bal-afterPosition afterLabel">
before
</div>
</div>
</div>
<div class="bal-after">
<img src="https://farm2.staticflickr.com/1663/25814974803_d4c55ff708_b.jpg">
<div class="bal-afterPosition afterLabel">
After
</div>
</div>
<div class="bal-handle">
<span class=" handle-left-arrow"></span>
<span class="handle-right-arrow"></span>
</div>
</div>
</div>
Upvotes: 1