slider before and after in graph

how do i do this in dash?
example

in this discussion there is a solution for images. example discussion
How should I do it with vector files (points, lines, polygons)?

any help is appreciated!

Hi @Nicodiaz and welcome to the Dash community :slight_smile:

Cool app - I haven’t seen that one. That component is a Dash Enterprise component and is not available open-source.

Alright, so I figured out some stuff just for fun. It’s not perfect. And probably doesn’t have all the features. For example, the graphs arent linked in order to perform the same actions. The code could also get cleaned some more.

app.py

import dash
import dash_bootstrap_components as dbc
from dash import Dash, html, dcc
import plotly.express as px

df = px.data.gapminder()

fig1 = px.scatter(
    df.query("year==2007"),
    x="gdpPercap",
    y="lifeExp",
    size="pop",
    color="continent",
    log_x=True,
    size_max=60,
    template="plotly_white",  # use the pulse themed figure template
    title="Gapminder 2007: Plotly White",
)

fig1.update_layout(title_x=0.5)

fig2 = px.scatter(
    df.query("year==2007"),
    x="gdpPercap",
    y="lifeExp",
    size="pop",
    color="continent",
    log_x=True,
    size_max=60,
    template="plotly_dark",
    title="Gapminder 2007: Plotly Dark",
)
fig2.update_layout(title_x=0.5)


app = Dash(
    __name__,
    external_stylesheets=[dbc.themes.BOOTSTRAP, dbc.icons.FONT_AWESOME],
    external_scripts=[
                    {'src':"https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"}]
)

def beforeAfterSlide(fig1, fig2, style=None):
    bfA = []
    if not style:
        style = {'width':'100vw', 'height':'100vh'}
    for key in style:
        if '%' in style[key]:
            if key in ['width', 'left']:
                style[key] = style[key].replace('%','vw')
            if key in ['top', 'height']:
                style[key] = style[key].replace('%','vh')
    fig2.update_layout(title_x=0.5)
    fig1.update_layout(title_x=0.5)
    bfA.append(html.Div(dcc.Graph(figure=fig2, style={'width':'100%', 'height':'100%'})
                        , className='after'))
    bfA.append(html.Div(className='middle'))
    bfA.append(html.Div(dcc.Graph(figure=fig1, style=dict(width=style['width'], height=style['height'])),
                        className='before'))
    return html.Div(bfA, className='beforeAfter', style=style)

app.layout = html.Div(beforeAfterSlide(fig1, fig2, {'height':'75%', 'width':'75%', 'top':'10%', 'left':'6%'}))

if __name__ == "__main__":
    app.run_server(debug=True)

css file:

.beforeAfter {
    border-radius: 5px;
    border: 2px solid silver;
    position: relative;
    margin: 0;
    padding: 0;
}

.after {
    height:100%;
    width:100%;
    z-index: 1;
    position: absolute;
 }

.before {
    height: 100%;
    width: 50%;
    overflow: hidden;
    border-right: 4px solid silver;
    z-index: 40;
    position: absolute;
}

.middle {
    top: 45%;
    left: 48%;
    z-index: 50;
    draggable: true;
    position: absolute;
}

.middle:before {
    content: '\f1de';
    font-family: "Font Awesome 6 Free";
    font-size: 30pt;
    font-weight: 900;
    background-color: silver;
    border: 1pt solid black;
    cursor: grab;
    border-radius: 5pt;
}

.middle:hover:before {
    filter: brightness(1.15)
}

.middle:active:before {
    cursor: grabbing;
}

js file:


function coolEffects() {
    $(".middle").on("mousedown", function () {
        $(document).on("mouseup",function() {
            $(document).unbind("mousemove")
             $(document).unbind("mouseup")
             oldX = undefined
             oldY = undefined
             })
        $(document).on("mousemove", function () {
            adjustSize()
        })
    })

    $(".before .modebar").css({'left':'0px', 'position':'absolute'})
}

window.fetch = new Proxy(window.fetch, {
    apply(fetch, that, args) {
        // Forward function call to the original fetch
        const result = fetch.apply(that, args);

        // Do whatever you want with the resulting Promise
        result.then((response) => {
            if (args[0] == '/_dash-update-component') {
                setTimeout(function() {coolEffects()}, 500)
            }})
        return result
        }
    }
    )

var oldX;
var oldY;
function adjustSize() {
    if (event.screenX != 0) {
        if (oldX && !((parseInt($('.before').css("width"))+((event.clientX-$(document).scrollLeft())-oldX)) > $('.beforeAfter').width())) {
            $('.before').css("width", parseInt($('.before').css("width"))+((event.clientX-$(document).scrollLeft())-oldX)+'px')
            $('.middle').css("left", ($('.before').width()/$('.beforeAfter').width()*100)-2 + '%')
        }

        if (parseFloat($('.middle').css('left'))> $('.beforeAfter').width()) {
            $('.middle').css("left", '99.5%')
            $('.before').css("width", $('.beforeAfter').width())
        }
    }
    oldX = event.clientX-$(document).scrollLeft()
    event.target.style.cursor = 'grab';
}

$(document).ready(function() {
    setTimeout(function() {coolEffects()}, 1000)
})

Have fun. :slight_smile: