glide icon indicating copy to clipboard operation
glide copied to clipboard

3D Transform documentation

Open andreslopezdreams opened this issue 6 years ago • 13 comments

I am currently using version 3.x only vanilla js, could you indicate where you can configure the 3D transformation on the elements as you could do in previous versions

andreslopezdreams avatar Oct 10 '18 16:10 andreslopezdreams

Hi, @andreslopezdreams!

I did some research on that and found quite small on that: image

As you can see in the screenshot, there's a Translate function in glide.js but I didn't figure out how it works =(

I also found that as for 3D @jedrzejchalubek uses classes like .frames, .frames__list, .frames__item and .frame on the promo page glidejs.com that are linked to a specific app.css. There's nothing like that in 'glide.core.css' or 'glide.theme.css'.

Seems like it disappeared from there even it was there =(

RShalman avatar Oct 21 '18 07:10 RShalman

I am also interested in 3D Transforms with Glide js. How is it possible to reproduce the promo page slider?

SimonScheidler avatar Dec 27 '18 20:12 SimonScheidler

I was attracted by the promo page slider, but I found that I can not do the 3D slider according to the doc, pity

Feuda avatar Sep 18 '19 12:09 Feuda

I found this digging through the code inside the demo,

Coverflow: function(e, t, n) {
    var i = {
        tilt: function(e) {
            (e.querySelector(c).style.transform =
                'perspective(1500px) rotateY(0deg)'),
                this.tiltPrevElements(e),
                this.tiltNextElements(e);
        },
        tiltPrevElements: function(e) {
            for (
                var t = (function(e) {
                        var t = [];
                        if (e)
                            for (; (e = e.previousElementSibling); )
                                t.push(e);
                        return t;
                    })(e),
                    n = 0;
                n < t.length;
                n++
            ) {
                var i = t[n].querySelector(c);
                (i.style.transformOrigin = '100% 50%'),
                    (i.style.transform =
                        'perspective(1500px) rotateY(' +
                        20 * Math.max(n, 2) +
                        'deg)');
            }
        },
        tiltNextElements: function(e) {
            for (
                var t = (function(e) {
                        var t = [];
                        if (e)
                            for (; (e = e.nextElementSibling); ) t.push(e);
                        return t;
                    })(e),
                    n = 0;
                n < t.length;
                n++
            ) {
                var i = t[n].querySelector(c);
                (i.style.transformOrigin = '0% 50%'),
                    (i.style.transform =
                        'perspective(1500px) rotateY(' +
                        -20 * Math.max(n, 2) +
                        'deg)');
            }
        }
    };
    return (
        n.on(['mount.after', 'run'], function() {
            i.tilt(t.Html.slides[e.index]);
        }),
        i
    );
}

It sounds like this is a custom plugin that was made, it's uglified, but I don't think its so bad that someone couldn't decipher it

ghost avatar Sep 18 '19 20:09 ghost

Hello! I want made Coverflow effects but i didn't find any informations about this. Could you help me please?

blogaster avatar Nov 18 '19 16:11 blogaster

I agree it's a bit odd to have something in the demo that isn't easily reproduced from the docs.

zinabat avatar Nov 22 '19 19:11 zinabat

I was looking for a fix for this as well, couldn't find anything about it in the docs so I decided to recreate it from scratch (using the uglified code as an example).

This is my HTML structure, using .glide__container as my transformable container.

<div class="glide">
    <div data-glide-el="track" class="glide__track">
        <ul class="glide__slides">
            <li class="glide__slide">
                <div class="glide__container">

                </div>
            </li>
            <li class="glide__slide">
                <div class="glide__container">

                </div>
            </li>
            <li class="glide__slide">
                <div class="glide__container">

                </div>
            </li>
            <li class="glide__slide">
                <div class="glide__container">

                </div>
            </li>
            <li class="glide__slide">
                <div class="glide__container">

                </div>
            </li>
            <li class="glide__slide">
                <div class="glide__container">

                </div>
            </li>
        </ul>
    </div>
</div>

This is all the CSS i've used, using a black border around the container for testing purposes.

.glide__slides {
  overflow: visible;
  transform-style: preserve-3d;
}

.glide__slide {
  transform: perspective(2000px);
}

.glide__container {
  border: 2px solid #000;
  border-radius: 4px;
  width: 200px;
  height: 200px;
  transition: all 500ms ease;
  will-change: transform;
  transform-style: preserve-3d;
  position: relative;
}

Now for the fun part, I've created a custom plugin that does the tilting based on the currently active slide. It's nowhere near perfect, but it should be a good starting point for anyone who's trying to achieve the same result. Keep in mind that this only works for the 'slider' type, as the clones that glide creates when using carousel mode interfere with the transforming.

const glider = new Glide('.glide', {
  autoplay: 10000,
  type: 'slider',
  perView: 5,
  focusAt: 'center'
});

// The classname for the element that gets transformed
const tiltableElement = '.glide__container';
glider.mount({
  Coverflow: (Glide, Components, Events) => {
    const Plugin = {
      tilt (element) {
        element.querySelector(tiltableElement).style.transform = "perspective(1500px) rotateY(0deg)";
        this.tiltPrevElements();
        this.tiltNextElements();
      },
      tiltPrevElements () {
        const activeSlide = Components.Html.slides[Glide.index];

        const previousElements = [];
        const getPrevious = (element) => {
          const e = element.previousElementSibling;
          if (e) {
            previousElements.push(e.querySelector(tiltableElement));
            getPrevious(e);
          }
        };
        getPrevious(activeSlide);

        previousElements.forEach((item, index) => {
          item.style.transformOrigin = "100% 50%";
          item.style.transform = `perspective(1500px) rotateY(${20 * Math.max(index, 2)}deg)`
        })

      },
      tiltNextElements () {
        const activeSlide = Components.Html.slides[Glide.index];

        const nextElements = [];

        const getNext = (element) => {
          const e = element.nextElementSibling;
          if (e) {
            nextElements.push(e.querySelector(tiltableElement));
            getNext(e);
          }
        };
        getNext(activeSlide);

        nextElements.forEach((item, index) => {
          item.style.transformOrigin = "0% 50%";
          item.style.transform = `perspective(1500px) rotateY(${-20 * Math.max(index, 2)}deg)`
        })
      }
    }

    Events.on(['mount.after', 'run'], () => {
      Plugin.tilt(Components.Html.slides[Glide.index]);
    });

    return Plugin;
  }
});

LeanderFS avatar Jan 03 '20 13:01 LeanderFS

I found the relative css in the download that makes the 3D transformation. It's far from ideal, but works. No Javascript required.

Find the file "docs/assets/css/main.css" Then just look for "glider-persp" classes and copy those.

Give your glider container that class, and you're good to go.

AvanOsch avatar Jan 15 '21 14:01 AvanOsch

Hi @AvanOsch

Find the file "docs/assets/css/main.css" Then just look for "glider-persp" classes and copy those.

Looked everywhere on GitHub and Gliderjs.com and could not find "main.css". Any ideas or help would be greatly appreciated!

Numinous avatar Feb 27 '22 20:02 Numinous

@Numinous It's been a while, so I don't remember exactly... Maybe you'll have to build it first?

You could also try and get the source code from glidejs.com (maybe glidejs.com/css/app.css) and use the homepage's example to work from...

Good luck!

AvanOsch avatar Feb 28 '22 23:02 AvanOsch

@AvanOsch - ah yes it has been a while and thanks so much for circling back after so long! I haven't tried building it first - will do. I found the CodePen for the actual promo used on the GlideJS home page. In case you or anyone else is interested: https://codepen.io/smuglovsky/pen/RJBqpR

Numinous avatar Mar 01 '22 01:03 Numinous

You can do it with just a little bit of CSS. No JS.

/* Rotate all */ .glide__slide { transform: perspective(600px) rotateY(20deg); transition: all ease-in-out 0.35s; }

/* Make the active one straight */ .glide__slide--active { transform: perspective(600px) rotateY(0deg); }

/* Give opposite rotation to slides after the active one */ .glide__slide--active ~ .glide__slide { transform: perspective(600px) rotateY(-20deg); }

Example: https://codepen.io/Jovan-Ralic/pen/ZEjbQKM

Rale379 avatar Jan 04 '23 14:01 Rale379

Agree that it is weird that the API docs for mount() don't mention the Extensions object parameter.

...But that is the nice thing about open source...

Here is the mount() function you call to initialize Glide. It defaults the Extensions parameter to an empty object ({}) and ultimately calls another mount() function in core/index.js. So this "feature" is called "extensions" in the source.

That second mount() function is where the behaviour of the Extensions is easily discernible.

  • iterate the keys in the extensions object (doesn't care what the keys are)
    • the value for each key MUST be type function
    • each extension function is called passing parameters: glide, components, events
      • glide is the Glide object
      • components is an object containing the RESULT (by name) of calling each extension function. This allows individual extensions/components to interact with others.
      • events is the Glide event bus

finally, after all the extension functions have been called and resulting object/function stored into components object by name... the components are iterated and the ones that have a mount() function are called. I guess this provides a signal to say: "all components have been initialized" in case one component wants to talk to another.

So in the simplest case if you you don't care about your components talking to each other you can just provide object of functions (keys arbitrary) that take Glide, components, eventbus and then listen for events and do certain things. They don't need to return any API in that case.

If you want components to talk to each other, they need to know each others' names/APIs and return an object with a mount function and wait for the mount function before calling other components APIs.

Example

So something like this would have 2 (useless) components that initialize and talk to each other after both are initialized.


const extensions = {
	foo: function (glide, components, eventBus) {
		console.log('foo initialized');
		return {
			mount: function () {
				console.log('foo mount was called.');
				components['bar'].myApi('hello from foo');
			},
			myApi: function () {
				console.log('foo myApi was called');
				console.log.apply(null, arguments);
			},
		};
	},
	bar: function (glide, components, eventBus) {
		console.log('bar initialized');
		return {
			mount: function () {
				console.log('bar mount was called.');
				components['foo'].myApi('hello from bar');
			},
			myApi: function () {
				console.log('bar myApi was called');
				console.log.apply(null, arguments);
			},
		};
	},
};


new Glide('#slider-container', {
  type: 'slider',
  focusAt: 'center',
  perView: 3
}).mount(extensions);

...will result in the following console output:

foo initialized
bar initialized
foo mount was called.
bar myApi was called
hello from foo
bar mount was called.
foo myApi was called
hello from bar

by the way... it is in the docs

Not sure why the API Docs for mount() don't mention/link to it...but extensions are documented here:

https://glidejs.com/docs/extending-components/

in addition to the extensions/components there is a very similar "transformer" extensions documented here...

https://glidejs.com/docs/extending-transformers/

image

It is odd that this issue sits open even though it is documented. The only "fix" would be to mention the extensions object on the API page and link to the extending-components page for details.

mattpr avatar Nov 01 '23 17:11 mattpr