Make this 3D Curved Image Slider/Carousel in Elementor

https://www.youtube.com/watch?v=PCLt3ZM5fsc

 

Want to get this as ready made template with just 1 CLICK INSTALL?

I want it as Ready Template

 

Code Snippet for 3D Curved Image Slider/Carousel:

<style>
[class^='mdw-curved-slider'],
[class*=' mdw-curved-slider']{
    height: var(--min-height, 100vh);
}
[class^='mdw-curved-slider'] canvas,
[class*=' mdw-curved-slider'] canvas{
    position: absolute;
    top: 0;
    left: 0;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.min.js"></script>
<script>

if(!MDWNonce111){
var MDWNonce111 = true

var selector = "[class^='mdw-curved-slider'], [class*=' mdw-curved-slider']",
    scene = [],
    renderer = [],
    options = [],
    time = [],
    camera = [],
    slideAmount = [],
    currentContainerHeight = [],
    previousContainerHeight = [],
    planes = []

addEventListener('DOMContentLoaded', function(){
    
function getWidth(gap){ return 1 + gap/100 }

function getPlaneWidth(el, camera){
    var vFov = camera.fov*Math.PI/180,
    height = 2*Math.tan(vFov/2)*camera.position.z,
    aspect = el.clientWidth/el.clientHeight,
    width = height*aspect
    return el.clientWidth/width
}

function init(e = 'none'){
Array.from(document.querySelectorAll(selector)).forEach(function(el, index){
    
    if( e == 'none' ){
        currentContainerHeight[index] = previousContainerHeight[index] = el.clientHeight
    }else{
        currentContainerHeight[index] = el.clientHeight
        if( mobileHeightChage && currentContainerHeight[index] == previousContainerHeight[index] ) return
    }

    previousContainerHeight[index] = currentContainerHeight[index]
    
    var className = el.getAttribute('class'),
    classNameIndex = className.indexOf('mdw-curved-slider'),
    shortClass = className.substring(classNameIndex, className.indexOf(' ',classNameIndex)),
    values = shortClass.split('-')
    
    options[index] = {
        speed: 30,
        gap: 10,
        curve: 12,
        direction: -1
    }
    
    values.forEach(function(value, i){
        if(value=='speed' && values[i+1] && !isNaN(values[i+1])){
            options[index].speed = values[i+1] }
        if(value=='gap' && values[i+1] && !isNaN(values[i+1])){
            options[index].gap = values[i+1] }
        if(value=='curve' && values[i+1] && !isNaN(values[i+1])){
            options[index].curve = values[i+1] }
        if(value=='reverse'){ options[index].direction = 1 }
    })
    
    var images = [],
        allImages = []
        
    time[index] = 0
        
    Array.from(el.querySelectorAll('.elementor-widget-image-gallery .gallery-item')).forEach(function(el, index){
        images.push(el.querySelector('img').getAttribute('src'))
    })
    allImages = images
    slideAmount[index] = images.length

    scene[index] = new THREE.Scene()
    camera[index] = new THREE.PerspectiveCamera( 75, el.clientWidth / el.clientHeight, 0.1, 20 )
    camera[index].position.z = 2
    
    renderer[index] = new THREE.WebGLRenderer({ alpha: true, antialias: true })
    renderer[index].setSize(el.clientWidth, el.clientHeight)
    renderer[index].setPixelRatio(window.devicePixelRatio)
    
    var previousCanvas = el.querySelector('canvas')
    if(previousCanvas) { el.removeChild(previousCanvas) }
    el.appendChild(renderer[index].domElement)
    
    var geometry = new THREE.PlaneGeometry(1, 1, 20, 20),
        planeSpace = getPlaneWidth(el,camera[index])*getWidth(options[index].gap),
        ratio = Math.ceil(el.clientWidth/(planeSpace*images.length)),
        totalImage = Math.ceil(el.clientWidth/planeSpace) + 1 + images.length,
        initialOffset = Math.ceil(el.clientWidth/(2*planeSpace)-0.5)
        
    for( var i = slideAmount[index]; i < totalImage; i++ ){
        allImages.push(images[i%slideAmount[index]])
    }
    
    planes[index] = []
    
    allImages.forEach(function (image, i) {
        var loader = new THREE.TextureLoader()
        loader.load(
            image,
            function ( texture ) {
                var material = new THREE.ShaderMaterial({
                    uniforms: {
                        tex: { value: texture },
                        curve: { value: options[index].curve }
                    },
                    vertexShader: `
                        uniform float curve;
                        varying vec2 vertexUV;
                        void main(){
                            vertexUV = uv;
                            vec3 newPosition = position;
                            float distanceFromCenter = abs(modelMatrix*vec4(position, 1.0)).x;
                            newPosition.y *= 1.0 + (curve/100.0)*pow(distanceFromCenter,2.0);
                            
                            gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
                        }
                    `,
                    fragmentShader: `
                        uniform sampler2D tex;
                        varying vec2 vertexUV;
                        void main(){
                            gl_FragColor = texture2D(tex, vertexUV);
                        }
                    `
                })

                planes[index][i] = new THREE.Mesh( geometry, material )
                planes[index][i].position.x = -1*options[index].direction*(i-initialOffset)*getWidth(options[index].gap)
                scene[index].add( planes[index][i] )
            }
        )
    })
})
}
init()

var currentWidth,
    previousWidth = window.innerWidth,
    mobileHeightChage = false
    
function onResize(){
    currentWidth = window.innerWidth
    mobileHeightChage = currentWidth < 768 && currentWidth == previousWidth
    init('resize')
    previousWidth = currentWidth
}

window.addEventListener('resize', function(){
    onResize()
    setTimeout(onResize, 100)
})

var previousTime = 0

function animate(currentTime){
    
    var timePassed = currentTime - previousTime
    
    Array.from(document.querySelectorAll(selector)).forEach(function(el, index){
        if(Math.abs(scene[index].position.x) >= getWidth(options[index].gap)*slideAmount[index]){ time[index] = 0 }
        time[index] += options[index].direction*timePassed*0.00001
        scene[index].position.x = time[index]*options[index].speed
        renderer[index].render(scene[index], camera[index])
    })
    
    previousTime = currentTime
    requestAnimationFrame(animate)
}
requestAnimationFrame(animate)

})
}
</script>